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