AWSTemplateFormatVersion: 2010-09-09
Description: AWS Lambda function to make API Gateway call. (qs-1q5uqlscb)
Metadata:
  'AWS::CloudFormation::Interface':
    ParameterGroups:
      - Label:
          default: Minimum requirements
        Parameters:
          - TermsAndConditions
          - VolumeOfData
          - PermissionToTransfer
          - PermissionToProcess
          - MFA
      - Label:
          default: Customer information
        Parameters:
          - CustomerName
          - CustomerRegisteredAddress
          - CustomerIndustry
          - BriefDescriptionOfCustomer
          - PreviousCustomerNames
          - ListedOrQuoted
          - PersonCompletingForm
          - PersonCompletingEmailAddress
          - CustomerMainContactName
          - CustomerMainContactEmail
      - Label:
          default: Scope
        Parameters:
          - Level1Services
          - Level2Services
      - Label:
          default: TrueVoice front end 
        Parameters:
          - UsersPov
      - Label:
          default: TrueVoice audio recordings
        Parameters:
          - AudioFormatsFile
          - AudioFormatsCodecs
          - MultiChannel
          - Metadata
          - SendingFiles
          - DataRetention
    ParameterLabels:
      VolumeOfData:
        default: Volume of data
      PermissionToTransfer:
        default: Permission to transfer
      PermissionToProcess:
        default: Permission to process
      MFA:
        default: Multi-factor authentication
      DataRetention:
        default: Data retention
      SendingFiles:
        default: Sending files
      Metadata:
        default: Metadata
      MultiChannel:
        default: Multi-channel
      AudioFormatsCodecs:
        default: Audio format codecs
      AudioFormatsFile:
        default: Audio file formats
      UsersPov:
        default: User profiles for PoV
      CustomerMainContactName:
        default: Customer main contact name
      CustomerMainContactEmail:
        default: Customer main contact email
      CustomerName:
        default: Customer name
      PersonCompletingForm:
        default: Name of person completing the form
      PersonCompletingEmailAddress:
        default: Email of person completing the form
      CustomerIndustry:
        default: Customer industry
      ListedOrQuoted:
        default: Stock exchange listing
      PreviousCustomerNames:
        default: Previous company names
      BriefDescriptionOfCustomer:
        default: Brief description of company
      CustomerRegisteredAddress:
        default: Company registered address
      Level1Services:
        default: Level 1 services
      Level2Services:
        default: Level 2 services
      TermsAndConditions:
        default: Terms and conditions
Parameters:
  TermsAndConditions:
    Type: String
    Description: By submitting this form, you agree that Deloitte may process any personal data supplied by you (e.g., name, email address) as necessary in connection with the Deloitte TrueVoice service. For more details on how Deloitte handles and shares your information, your rights, and how to contact us, see the privacy statement(https://www2.deloitte.com/uk/en/footerlinks1/privacy.html). Please note that any agreement to provide the True Voice service is subject the information we receive from you and agreeing a suitable contract between us for your selected services. By clicking Yes, you confirm you have read and you agree to Deloitte’s Terms and Conditions(https://d154d4u55he2e5.cloudfront.net/). You represent to us that you are lawfully able to enter into contracts, and if you are entering into these Terms & Conditions on behalf of an entity, such as the company you work for, you represent to us that you have legal authority to bind that entity. We reserve the right, at our sole discretion, to change, modify, or update these Terms & Conditions at any time. Please select Yes to confirm this.
    AllowedValues: 
      - 'Yes'
  Level1Services:
    Type: String
    Description: Level 1 services for the PoV. To use TrueVoice, either Level 1 or Level 2 services must be selected. Level 1 services will be discussed in more detail in the workshop session. Note that these services typically have a 1-4 week engagement window.
    AllowedValues: 
      - 'Yes'
      - 'No'
  Level2Services:
    Type: String
    Description: Level 2 services for the PoV. To use TrueVoice, either Level 1 or Level 2 services must be selected. Level 2 services will be discussed in more detail in the workshop session. Note that these services typically have a 4–8 week engagement window.
    AllowedValues: 
      - 'Yes'
      - 'No'
  MFA:
    Description: MFA user name and password. Users of the Deloitte Hosted Web Application will be provisioned with the MFA user name and password. Choose Yes to confirm this.
    Type: String
    AllowedValues: 
      - 'Yes'
      - 'No'
  PermissionToProcess:
    Description: Permission to process your data on the TrueVoice platform. By submitting this application, you permit Deloitte to process your data on the TrueVoice platform for the Deloitte-provisioned AWS Cloud in the EU (London) Region.  The service may be expanded to other Regions based on customer demand, localization, data sovereignty requirements, or other relevant criteria. Choose Yes to confirm this.
    Type: String
    AllowedValues: 
      - 'Yes'
      - 'No'
  PermissionToTransfer:
    Description: Confirmation that it is appropriate for you to transfer this data to TrueVoice for processing and use in this engagement. For the PoV, Deloitte will hold your data for 90 days post PoV completion, after which data will be deleted. Choose Yes to confirm this.
    Type: String
    AllowedValues: 
      - 'Yes'
      - 'No'
  VolumeOfData:
    Description: Confirmation that you are able to provide at least 1,000 hours of audio, which is a requirement for this engagement (maximum of 3,000 hours). Choose Yes to confirm this.
    Type: String
    AllowedValues: 
      - 'Yes'
      - 'No'
  DataRetention:
    Description: Confirmation of data retention. For the PoV, Deloitte will hold your data for 90 days post PoV completion, after which the data will be deleted. Choose Yes to confirm this.
    Type: String
    AllowedValues: 
      - 'Yes'
      - 'No'
  SendingFiles:
    Description: Media upload. Choose Yes to confirm that you are able to push media into a dedicated pre-specified TrueVoice S3 bucket.
    Type: String
    AllowedValues: 
      - 'Yes'
      - 'No'
  Metadata:
    Description: Minimum required metadata. Choose Yes to confirm that you are able to supply, alongside the media files, the minimum required metadata using the required format (refer to the File transfer to the TrueVoice AWS account section in the deployment guide). Please also detail any other metadata, beyond the minimum amount, that you can be provide.
    Type: String
    AllowedValues: 
      - 'Yes'
      - 'No'
  MultiChannel:
    Description: Single-channel or multiple-channel. For each audio format listed, please list whether the audio will be single-channel or multi-channel, and whether caller audio and operator audio are separated by channel.
    Type: String
    AllowedValues: 
      - Unknown
      - Single (Mono)
      - Multi (Stereo)
  AudioFormatsCodecs:
    Description: 'A comma-delimited list of audio format codecs for TrueVoice to use. Available options: Unknown, G729a, and G711.'
    Type: String
    AllowedPattern: ^\s*[A-Za-z0-9\.]+(?:,+[A-Za-z0-9\.]+)*,*$
  AudioFormatsFile:
    Description: 'A comma-delimited list of audio file formats for TrueVoice to process. Available options: Unknown, .mp3, .wav, and .mov.'
    Type: String
    AllowedPattern: ^\s*[A-Za-z0-9\.]+(?:,+[A-Za-z0-9\.]+)*,*$
  UsersPov:
    Description: The number of Deloitte Hosted Web Application user profiles that you require. The maximum is 5 for a PoV. Deloitte will request these user details in the kickoff workshop.
    Type: String
    AllowedPattern: ^.+$
  CustomerName:
    Description: The name of the company this service is for.
    Type: String
    AllowedPattern: ^.+$
  CustomerMainContactName:
    Description: The name of the main customer contact for this service. Correspondence will be with this person.
    Type: String
    AllowedPattern: ^.+$
  CustomerMainContactEmail:
    Description: The email address of the main customer contact for this service. Correspondence will be with this person.
    Type: String
    AllowedPattern: ([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)
  PersonCompletingForm:
    Description: The name of the person completing this template.
    Type: String
    AllowedPattern: ^.+$
  PersonCompletingEmailAddress:
    Description: The email address of the person completing this template.
    Type: String
    AllowedPattern: ([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)
  CustomerIndustry:
    Description: The industry the company serves.
    Type: String
    AllowedPattern: ^.+$
  ListedOrQuoted:
    Description: Stock exchange listing. Choose Yes if the company is listed on a stock exchange.
    Type: String
    AllowedValues: 
      - 'Yes'
      - 'No'
  PreviousCustomerNames:
    Description: Company names. List any other company names from the last 3 years.
    Type: String
    AllowedPattern: ^.+$
  BriefDescriptionOfCustomer:
    Description: A brief overview of the company’s work.
    Type: String
    AllowedPattern: ^.+$
  CustomerRegisteredAddress:
    Description: The address of the company this service is for.
    Type: String
    AllowedPattern: ^.+$
Resources:
  TVQSCW01:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: !Sub '/aws/lambda/${TVQSL01}'
      RetentionInDays: 60
  TVQSCR01:
    Type: Custom::TVQSCR01
    DependsOn: TVQSCW01
    Properties:
      ServiceToken: !GetAtt 'TVQSL01.Arn'
      accountNum: !Sub ${AWS::AccountId}
      awsRegion: !Sub ${AWS::Region}
      customerName: !Ref CustomerName
      customerRegisteredAddress: !Ref CustomerRegisteredAddress
      customerIndustry: !Ref CustomerIndustry
      briefDescriptionOfCustomer: !Ref BriefDescriptionOfCustomer
      previousCustomerNames: !Ref PreviousCustomerNames
      listedOrQuoted: !Ref ListedOrQuoted
      personCompletingForm: !Ref PersonCompletingForm
      personCompletingEmailAddress: !Ref PersonCompletingEmailAddress
      customerMainContactName: !Ref CustomerMainContactName
      customerMainContactEmail: !Ref CustomerMainContactEmail
      usersPov: !Ref UsersPov
      audioFormatsFile: !Ref AudioFormatsFile
      audioFormatsCodecs: !Ref AudioFormatsCodecs
      multiChannel: !Ref MultiChannel
      metadata: !Ref Metadata
      sendingFiles: !Ref SendingFiles
      dataRetention: !Ref DataRetention
      volumeOfData: !Ref VolumeOfData
      permissionToTransfer: !Ref PermissionToTransfer
      permissionToProcess: !Ref PermissionToProcess
      scopeOfServices1: !Ref Level1Services
      scopeOfServices2: !Ref Level2Services
      termsAndConditions : !Ref TermsAndConditions
      mfa: !Ref MFA
  TVQSIAM01:
    Type: 'AWS::IAM::Role'
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service: lambda.amazonaws.com
            Action: 'sts:AssumeRole'
      ManagedPolicyArns:
        - 'arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole'
      Path: /
      Policies:
      - PolicyName: logs
        PolicyDocument:
          Version: '2012-10-17'
          Statement:
          - Effect: Allow
            Action:
            - 'logs:CreateLogGroup'
            - 'logs:CreateLogStream'
            - 'logs:PutLogEvents'
            - 'logs:DescribeLogStreams'
            Resource: "*"
  TVQSL01:
    Type: 'AWS::Lambda::Function'
    Properties:
      Description: Calls API
      Handler: index.handler
      Runtime: python3.7
      Role: !GetAtt 
        - TVQSIAM01
        - Arn
      Timeout: 60
      Code:
        ZipFile: |
          import json
          import logging
          import boto3
          import signal
          import traceback
          from urllib.parse import urlparse, urlencode
          from urllib.request import urlopen, Request, build_opener, HTTPSHandler
          from urllib.error import HTTPError

          def handler(event, context):
            print('Received event')
            print(event)
            p=event['ResourceProperties']
            signal.alarm(context.get_remaining_time_in_millis() - 1000)
            try:
              if event['RequestType'] == 'Create':
                payload = bytes(json.dumps( { "RequestType": "Create","cn":p['customerName'],"cra":p['customerRegisteredAddress'],"ci":p['customerIndustry'],"bdoc":p['briefDescriptionOfCustomer'],"pcn":p['previousCustomerNames'],"loq":p['listedOrQuoted'],"pcf":p['personCompletingForm'],"pcea":p['personCompletingEmailAddress'],"cmcn":p['customerMainContactName'],"cmce":p['customerMainContactEmail'],"up":p['usersPov'],"aff":p['audioFormatsFile'],"afc":p['audioFormatsCodecs'],"mch":p['multiChannel'],"me":p['metadata'],"sf":p['sendingFiles'],"dr":p['dataRetention'],"vod":p['volumeOfData'],"ptt":p['permissionToTransfer'],"ptp":p['permissionToProcess'],"mf":p['mfa'],"sos1":p['scopeOfServices1'],"sos2":p['scopeOfServices2'],"tac":p['termsAndConditions'],"an":p['accountNum'],"re":p['awsRegion'] }), encoding='utf8')
                handler = build_opener(HTTPSHandler)
                url = 'https://sd5f44wtp3.execute-api.eu-west-2.amazonaws.com/prod/req'
                rq = Request(url, data=payload)
                rq.add_header('Content-Type', 'application/json')
                rq.add_header('x-api-key', 'Knab57eJ6n2eml9GprBGz3xkMXmVE8kp8FGlOuvs')
                rq.get_method = lambda: 'POST'
                response = handler.open(rq)
                send_response(event, context, "SUCCESS", {"TrueVoicePoVRegId": json.loads(response.read())['body']})
              elif event['RequestType'] == 'Update':
                send_response(event, context, "SUCCESS", {"Message": "Resource update successful!"})
              elif event['RequestType'] == 'Delete':
                send_response(event, context, "SUCCESS", {"Message": "Resource deletion successful!"})
              else:
                send_response(event, context, "FAILED", {"Message": "Unexpected event received from CloudFormation"})
            except Exception:
              traceback.print_exc()
              send_response(event, context, "FAILED", {"Message": "Exception during processing"})
          def send_response(event, context, response_status, response_data):
            response_body = bytes(json.dumps( { "Status": response_status,"Reason": "See the details in CloudWatch Log Stream: " + context.log_stream_name,"PhysicalResourceId": context.log_stream_name,"StackId": event['StackId'],"RequestId": event['RequestId'],"LogicalResourceId": event['LogicalResourceId'],"Data": response_data } ), encoding='utf8')
            opener = build_opener(HTTPSHandler)
            request = Request(event['ResponseURL'], data=response_body)
            request.add_header('Content-Type', '')
            request.add_header('Content-Length', len(response_body))
            request.get_method = lambda: 'PUT'
            response = opener.open(request)
            
          def timeout_handler(_signal, _frame):
            raise Exception('Time exceeded')
            
          signal.signal(signal.SIGALRM, timeout_handler)
Outputs:
  TrueVoicePoVRegId:
    Description: TrueVoice PoV Registration Id
    Value:
      Fn::GetAtt:
      - TVQSCR01
      - TrueVoicePoVRegId