{
  "Resources": {
    "PreUpgradeExport": {
      "Type": "Custom::PreUpgradeExport",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "bucket": {"Ref": "ExportBucket"},
        "id": "ExportAll_QnABot_v5.4.0.json",
        "index": {"Fn::Sub": "${Var.QnaIndex}"},
        "encryption": {"Ref": "Encryption"},
        "PRE_UPGRADE_EXPORT_TRIGGERS": {
          "Fn::Sub": [
            "${EmbeddingsApi} ${EmbeddingsLambdaDimensions} ${EmbeddingsLambdaArn} ${SMEmbeddingEndpoint}",
            {
              "SMEmbeddingEndpoint": {
                "Fn::If": [
                  "EmbeddingsSagemaker",
                  {
                    "Fn::GetAtt": [
                      "SagemakerEmbeddingsStack",
                      "Outputs.EmbeddingsSagemakerEndpoint"
                    ]
                  },
                  ""
                ]
              }
            }
          ]
        }
      }
    },
    "PreUpgradeExportMetrics": {
      "Type": "Custom::PreUpgradeExport",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "bucket": {"Ref": "ExportBucket"},
        "id": "ExportAll_QnABot_v5.4.0_metrics.json",
        "index": {"Fn::Sub": "${Var.MetricsIndex}"},
        "encryption": {"Ref": "Encryption"},
        "PRE_UPGRADE_EXPORT_TRIGGERS": {
          "Fn::Sub": [
            "${EmbeddingsApi} ${EmbeddingsLambdaDimensions} ${EmbeddingsLambdaArn} ${SMEmbeddingEndpoint}",
            {
              "SMEmbeddingEndpoint": {
                "Fn::If": [
                  "EmbeddingsSagemaker",
                  {
                    "Fn::GetAtt": [
                      "SagemakerEmbeddingsStack",
                      "Outputs.EmbeddingsSagemakerEndpoint"
                    ]
                  },
                  ""
                ]
              }
            }
          ]
        }
      }
    },
    "PreUpgradeExportFeedback": {
      "Type": "Custom::PreUpgradeExport",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "bucket": {"Ref": "ExportBucket"},
        "id": "ExportAll_QnABot_v5.4.0_feedback.json",
        "index": {"Fn::Sub": "${Var.FeedbackIndex}"},
        "encryption": {"Ref": "Encryption"},
        "PRE_UPGRADE_EXPORT_TRIGGERS": {
          "Fn::Sub": [
            "${EmbeddingsApi} ${EmbeddingsLambdaDimensions} ${EmbeddingsLambdaArn} ${SMEmbeddingEndpoint}",
            {
              "SMEmbeddingEndpoint": {
                "Fn::If": [
                  "EmbeddingsSagemaker",
                  {
                    "Fn::GetAtt": [
                      "SagemakerEmbeddingsStack",
                      "Outputs.EmbeddingsSagemakerEndpoint"
                    ]
                  },
                  ""
                ]
              }
            }
          ]
        }
      }
    },
    "Application": {
      "Type": "AWS::ServiceCatalogAppRegistry::Application",
      "Properties": {
        "Description": "Service Catalog application to track and manage all your resources for the solution qnabot-on-aws",
        "Name": {
          "Fn::Join": [
            "-",
            [
              "App",
              {"Ref": "AWS::StackName"},
              {
                "Fn::FindInMap": [
                  "Solution",
                  "Data",
                  "AppRegistryApplicationName"
                ]
              }
            ]
          ]
        },
        "Tags": {
          "Solutions:SolutionID": {"Fn::FindInMap": ["Solution", "Data", "ID"]},
          "Solutions:SolutionVersion": {
            "Fn::FindInMap": ["Solution", "Data", "Version"]
          },
          "Solutions:SolutionName": {
            "Fn::FindInMap": ["Solution", "Data", "SolutionName"]
          },
          "Solutions:ApplicationType": {
            "Fn::FindInMap": ["Solution", "Data", "ApplicationType"]
          }
        }
      }
    },
    "DefaultApplicationAttributes": {
      "Type": "AWS::ServiceCatalogAppRegistry::AttributeGroup",
      "Properties": {
        "Attributes": {
          "SolutionID": {"Fn::FindInMap": ["Solution", "Data", "ID"]},
          "Version": {"Fn::FindInMap": ["Solution", "Data", "Version"]},
          "SolutionName": {
            "Fn::FindInMap": ["Solution", "Data", "SolutionName"]
          },
          "ApplicationType": {
            "Fn::FindInMap": ["Solution", "Data", "ApplicationType"]
          }
        },
        "Description": "Attribute group for solution information",
        "Name": {"Fn::Join": ["-", ["AttrGrp", {"Ref": "AWS::StackName"}]]}
      }
    },
    "AppRegistryApplicationAttributeAssociation": {
      "Type": "AWS::ServiceCatalogAppRegistry::AttributeGroupAssociation",
      "Properties": {
        "Application": {"Fn::GetAtt": ["Application", "Id"]},
        "AttributeGroup": {"Fn::GetAtt": ["DefaultApplicationAttributes", "Id"]}
      }
    },
    "AppRegistryApplicationStackAssociation": {
      "Type": "AWS::ServiceCatalogAppRegistry::ResourceAssociation",
      "Properties": {
        "Application": {"Fn::GetAtt": ["Application", "Id"]},
        "Resource": {"Ref": "AWS::StackId"},
        "ResourceType": "CFN_STACK"
      }
    },
    "AppRegistryApplicationStackAssociationExamples": {
      "Type": "AWS::ServiceCatalogAppRegistry::ResourceAssociation",
      "Condition": "BuildExamples",
      "Properties": {
        "Application": {"Fn::GetAtt": ["Application", "Id"]},
        "Resource": {"Ref": "ExamplesStack"},
        "ResourceType": "CFN_STACK"
      }
    },
    "AppRegistryApplicationStackAssociationExport": {
      "Type": "AWS::ServiceCatalogAppRegistry::ResourceAssociation",
      "Properties": {
        "Application": {"Fn::GetAtt": ["Application", "Id"]},
        "Resource": {"Ref": "ExportStack"},
        "ResourceType": "CFN_STACK"
      }
    },
    "AppRegistryApplicationStackAssociationImport": {
      "Type": "AWS::ServiceCatalogAppRegistry::ResourceAssociation",
      "Properties": {
        "Application": {"Fn::GetAtt": ["Application", "Id"]},
        "Resource": {"Ref": "ImportStack"},
        "ResourceType": "CFN_STACK"
      }
    },
    "AppRegistryApplicationStackAssociationSagemakerEmbeddings": {
      "Type": "AWS::ServiceCatalogAppRegistry::ResourceAssociation",
      "Condition": "EmbeddingsSagemaker",
      "Properties": {
        "Application": {"Fn::GetAtt": ["Application", "Id"]},
        "Resource": {"Ref": "SagemakerEmbeddingsStack"},
        "ResourceType": "CFN_STACK"
      }
    },
    "AppRegistryApplicationStackAssociationTestAll": {
      "Type": "AWS::ServiceCatalogAppRegistry::ResourceAssociation",
      "Properties": {
        "Application": {"Fn::GetAtt": ["Application", "Id"]},
        "Resource": {"Ref": "TestAllStack"},
        "ResourceType": "CFN_STACK"
      }
    },
    "AssetBucket": {
      "Type": "AWS::S3::Bucket",
      "Properties": {
        "BucketEncryption": {
          "Fn::If": [
            "Encrypted",
            {
              "ServerSideEncryptionConfiguration": [
                {"ServerSideEncryptionByDefault": {"SSEAlgorithm": "AES256"}}
              ]
            },
            {"Ref": "AWS::NoValue"}
          ]
        },
        "PublicAccessBlockConfiguration": {
          "BlockPublicAcls": true,
          "BlockPublicPolicy": true,
          "IgnorePublicAcls": true,
          "RestrictPublicBuckets": true
        }
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W35",
              "reason": "Access logging is not required for this Bucket."
            }
          ]
        }
      }
    },
    "HTTPSOnlyAssetBucketPolicy": {
      "Type": "AWS::S3::BucketPolicy",
      "Properties": {
        "Bucket": {"Ref": "AssetBucket"},
        "PolicyDocument": {
          "Statement": [
            {
              "Action": "*",
              "Condition": {"Bool": {"aws:SecureTransport": "false"}},
              "Effect": "Deny",
              "Principal": "*",
              "Resource": {
                "Fn::Join": ["", [{"Fn::GetAtt": ["AssetBucket", "Arn"]}, "/*"]]
              },
              "Sid": "HttpsOnly"
            }
          ],
          "Version": "2012-10-17"
        }
      }
    },
    "AssetClear": {
      "Type": "Custom::S3Clear",
      "DependsOn": ["CFNInvokePolicy"],
      "Condition": "BuildExamples",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "Bucket": {"Ref": "AssetBucket"}
      }
    },
    "AssetZipVersion": {
      "Condition": "BuildExamples",
      "Type": "Custom::S3Version",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
        "Key": {"Fn::Join": ["", ["qnabot-on-aws/v5.4.0", "/assets.zip"]]},
        "BuildDate": "2023-07-27T21:25:41.815Z"
      }
    },
    "AssetUnzip": {
      "Type": "Custom::S3Unzip",
      "Condition": "BuildExamples",
      "DependsOn": ["AssetClear"],
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "SrcBucket": {"Fn::Sub": "solutions-${AWS::Region}"},
        "Key": {"Fn::Join": ["", ["qnabot-on-aws/v5.4.0", "/assets.zip"]]},
        "DstBucket": {"Ref": "AssetBucket"},
        "version": {"Ref": "AssetZipVersion"}
      }
    },
    "ExportBucket": {
      "Type": "AWS::S3::Bucket",
      "Properties": {
        "LifecycleConfiguration": {
          "Rules": [
            {"NoncurrentVersionExpirationInDays": 1, "Status": "Enabled"},
            {
              "AbortIncompleteMultipartUpload": {"DaysAfterInitiation": 1},
              "Status": "Enabled"
            }
          ]
        },
        "VersioningConfiguration": {"Status": "Enabled"},
        "CorsConfiguration": {
          "CorsRules": [
            {
              "AllowedHeaders": ["*"],
              "AllowedMethods": ["GET"],
              "AllowedOrigins": ["*"]
            }
          ]
        },
        "BucketEncryption": {
          "Fn::If": [
            "Encrypted",
            {
              "ServerSideEncryptionConfiguration": [
                {"ServerSideEncryptionByDefault": {"SSEAlgorithm": "AES256"}}
              ]
            },
            {"Ref": "AWS::NoValue"}
          ]
        },
        "PublicAccessBlockConfiguration": {
          "BlockPublicAcls": true,
          "BlockPublicPolicy": true,
          "IgnorePublicAcls": true,
          "RestrictPublicBuckets": true
        }
      },
      "UpdateReplacePolicy": "Retain",
      "DeletionPolicy": "Retain",
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W35",
              "reason": "Access logging is not required for this Bucket."
            }
          ]
        }
      }
    },
    "HTTPSOnlyExportBucketPolicy": {
      "Type": "AWS::S3::BucketPolicy",
      "Properties": {
        "Bucket": {"Ref": "ExportBucket"},
        "PolicyDocument": {
          "Statement": [
            {
              "Action": "*",
              "Condition": {"Bool": {"aws:SecureTransport": "false"}},
              "Effect": "Deny",
              "Principal": "*",
              "Resource": {
                "Fn::Join": [
                  "",
                  [{"Fn::GetAtt": ["ExportBucket", "Arn"]}, "/*"]
                ]
              },
              "Sid": "HttpsOnly"
            }
          ],
          "Version": "2012-10-17"
        }
      }
    },
    "ImportBucket": {
      "Type": "AWS::S3::Bucket",
      "Properties": {
        "LifecycleConfiguration": {
          "Rules": [{"ExpirationInDays": 1, "Status": "Enabled"}]
        },
        "VersioningConfiguration": {"Status": "Enabled"},
        "CorsConfiguration": {
          "CorsRules": [
            {
              "AllowedHeaders": ["*"],
              "AllowedMethods": ["PUT"],
              "AllowedOrigins": ["*"]
            }
          ]
        },
        "BucketEncryption": {
          "Fn::If": [
            "Encrypted",
            {
              "ServerSideEncryptionConfiguration": [
                {"ServerSideEncryptionByDefault": {"SSEAlgorithm": "AES256"}}
              ]
            },
            {"Ref": "AWS::NoValue"}
          ]
        },
        "PublicAccessBlockConfiguration": {
          "BlockPublicAcls": true,
          "BlockPublicPolicy": true,
          "IgnorePublicAcls": true,
          "RestrictPublicBuckets": true
        }
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W35",
              "reason": "Access logging is not required for this Bucket."
            }
          ]
        }
      }
    },
    "HTTPSOnlyImportBucketPolicy": {
      "Type": "AWS::S3::BucketPolicy",
      "Properties": {
        "Bucket": {"Ref": "ImportBucket"},
        "PolicyDocument": {
          "Statement": [
            {
              "Action": "*",
              "Condition": {"Bool": {"aws:SecureTransport": "false"}},
              "Effect": "Deny",
              "Principal": "*",
              "Resource": {
                "Fn::Join": [
                  "",
                  [{"Fn::GetAtt": ["ImportBucket", "Arn"]}, "/*"]
                ]
              },
              "Sid": "HttpsOnly"
            }
          ],
          "Version": "2012-10-17"
        }
      }
    },
    "TestAllBucket": {
      "Type": "AWS::S3::Bucket",
      "Properties": {
        "LifecycleConfiguration": {
          "Rules": [{"ExpirationInDays": 1, "Status": "Enabled"}]
        },
        "VersioningConfiguration": {"Status": "Enabled"},
        "CorsConfiguration": {
          "CorsRules": [
            {
              "AllowedHeaders": ["*"],
              "AllowedMethods": ["GET"],
              "AllowedOrigins": ["*"]
            }
          ]
        },
        "BucketEncryption": {
          "Fn::If": [
            "Encrypted",
            {
              "ServerSideEncryptionConfiguration": [
                {"ServerSideEncryptionByDefault": {"SSEAlgorithm": "AES256"}}
              ]
            },
            {"Ref": "AWS::NoValue"}
          ]
        },
        "PublicAccessBlockConfiguration": {
          "BlockPublicAcls": true,
          "BlockPublicPolicy": true,
          "IgnorePublicAcls": true,
          "RestrictPublicBuckets": true
        }
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W35",
              "reason": "Access logging is not required for this Bucket."
            }
          ]
        }
      }
    },
    "HTTPSOnlyTestAllBucketPolicy": {
      "Type": "AWS::S3::BucketPolicy",
      "Properties": {
        "Bucket": {"Ref": "TestAllBucket"},
        "PolicyDocument": {
          "Statement": [
            {
              "Action": "*",
              "Condition": {"Bool": {"aws:SecureTransport": "false"}},
              "Effect": "Deny",
              "Principal": "*",
              "Resource": {
                "Fn::Join": [
                  "",
                  [{"Fn::GetAtt": ["TestAllBucket", "Arn"]}, "/*"]
                ]
              },
              "Sid": "HttpsOnly"
            }
          ],
          "Version": "2012-10-17"
        }
      }
    },
    "VersionLambda": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Code": {
          "ZipFile": "const { S3Client, HeadObjectCommand } = require(\"@aws-sdk/client-s3\");\nconst client = new S3Client({region: process.env.AWS_REGION})\n\nexports.handler = function(event, context) {\n    console.log(JSON.stringify(event,null,2))\n    if(event.RequestType!==\"Delete\"){\n        client.send(new HeadObjectCommand({\n            Bucket:event.ResourceProperties.Bucket,\n            Key:event.ResourceProperties.Key\n        }))\n        .then(result=>send(event, context, SUCCESS,{\n            version:result.VersionId ? result.VersionId : 1\n        }))\n        .catch(x=>{\n            console.log(x)\n            send(event, context, FAILED)\n        })\n    }else{\n        send(event, context, SUCCESS)\n    }\n}\nconst SUCCESS = \"SUCCESS\";\nconst FAILED = \"FAILED\";\n\nfunction send(event, context, responseStatus, responseData, physicalResourceId, noEcho) {\n\n    var responseBody = JSON.stringify({\n        Status: responseStatus,\n        Reason: \"See the details in CloudWatch Log Stream: \" + context.logStreamName,\n        PhysicalResourceId: physicalResourceId || context.logStreamName,\n        StackId: event.StackId,\n        RequestId: event.RequestId,\n        LogicalResourceId: event.LogicalResourceId,\n        NoEcho: noEcho || false,\n        Data: responseData\n    });\n\n    console.log(\"Response body:\\n\", responseBody);\n\n    var https = require(\"https\");\n    var url = require(\"url\");\n\n    var parsedUrl = url.parse(event.ResponseURL);\n    var options = {\n        hostname: parsedUrl.hostname,\n        port: 443,\n        path: parsedUrl.path,\n        method: \"PUT\",\n        headers: {\n            \"content-type\": \"\",\n            \"content-length\": responseBody.length\n        }\n    };\n\n    var request = https.request(options, function(response) {\n        console.log(\"Status code: \" + response.statusCode);\n        console.log(\"Status message: \" + response.statusMessage);\n        context.done();\n    });\n\n    request.on(\"error\", function(error) {\n        console.log(\"send(..) failed executing https.request(..): \" + error);\n        context.done();\n    });\n\n    request.write(responseBody);\n    request.end();\n}\n"
        },
        "Handler": "index.handler",
        "MemorySize": "3008",
        "Role": {"Fn::GetAtt": ["CFNLambdaRole", "Arn"]},
        "Runtime": "nodejs18.x",
        "Timeout": 60,
        "VpcConfig": {
          "Fn::If": [
            "VPCEnabled",
            {
              "SubnetIds": [{"Ref": "AWS::NoValue"}],
              "SecurityGroupIds": [{"Ref": "AWS::NoValue"}]
            },
            {"Ref": "AWS::NoValue"}
          ]
        },
        "TracingConfig": {
          "Fn::If": ["XRAYEnabled", {"Mode": "Active"}, {"Ref": "AWS::NoValue"}]
        },
        "Tags": [{"Key": "Type", "Value": "CustomResource"}]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W92",
              "reason": "This lambda function does not require to have ReservedConcurrentExecutions"
            }
          ]
        }
      }
    },
    "CFNVersion": {
      "Type": "Custom::S3Version",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["VersionLambda", "Arn"]},
        "Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
        "Key": {"Fn::Sub": "qnabot-on-aws/v5.4.0/lambda/cfn.zip"},
        "BuildDate": "2023-07-27T21:25:41.816Z"
      }
    },
    "CFNLambda": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Code": {
          "S3Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
          "S3Key": {
            "Fn::Join": ["", ["qnabot-on-aws/v5.4.0", "/lambda/cfn.zip"]]
          },
          "S3ObjectVersion": {"Fn::GetAtt": ["CFNVersion", "version"]}
        },
        "Handler": "index.handler",
        "MemorySize": "3008",
        "Role": {"Fn::GetAtt": ["CFNLambdaRole", "Arn"]},
        "Runtime": "nodejs18.x",
        "Timeout": 180,
        "VpcConfig": {
          "Fn::If": [
            "VPCEnabled",
            {
              "SubnetIds": [{"Ref": "AWS::NoValue"}],
              "SecurityGroupIds": [{"Ref": "AWS::NoValue"}]
            },
            {"Ref": "AWS::NoValue"}
          ]
        },
        "TracingConfig": {
          "Fn::If": ["XRAYEnabled", {"Mode": "Active"}, {"Ref": "AWS::NoValue"}]
        },
        "Tags": [{"Key": "Type", "Value": "CustomResource"}]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W92",
              "reason": "This lambda function does not require to have ReservedConcurrentExecutions"
            }
          ]
        }
      }
    },
    "CFNInvokePolicy": {
      "Type": "AWS::IAM::ManagedPolicy",
      "Properties": {
        "PolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Action": ["lambda:InvokeFunction"],
              "Resource": [{"Fn::GetAtt": ["CFNLambda", "Arn"]}]
            }
          ]
        },
        "Roles": [{"Ref": "CFNLambdaRole"}]
      }
    },
    "CognitoDomain": {
      "Type": "Custom::CognitoDomain",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "UserPool": {"Ref": "UserPool"}
      }
    },
    "CognitoLoginClient": {
      "Type": "Custom::CognitoLogin",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "UserPool": {"Ref": "UserPool"},
        "ClientId": {"Ref": "ClientClient"},
        "LoginCallbackUrls": [{"Fn::GetAtt": ["Urls", "Client"]}],
        "CSS": ".logo-customizable{max-width:60%;max-height:30%}.banner-customizable{padding:25px 0px 25px 0px;background-color:#d3d3d3}.label-customizable{font-weight:410}.textDescription-customizable{padding-top:10px;padding-bottom:10px;display:block;font-size:16px}.idpDescription-customizable{padding-top:10px;padding-bottom:10px;display:block;font-size:16px}.legalText-customizable{color:#747474;font-size:11px}.submitButton-customizable{font-size:14px;font-weight:bold;margin:20px 0px 10px 0px;height:40px;width:100%;color:#fff;background-color:#337ab7}.submitButton-customizable:hover{color:#fff;background-color:#286090}.errorMessage-customizable{padding:5px;font-size:14px;width:100%;background:#f5f5f5;border:2px solid #d64958;color:#d64958}.inputField-customizable{width:100%;height:34px;color:#555;background-color:#fff;border:1px solid #ccc}.inputField-customizable:focus{border-color:#66afe9;outline:0}.idpButton-customizable{height:41px;width:100%;width:100%;text-align:center;margin-bottom:15px;color:#fff;background-color:#5bc0de;border-color:#46b8da}.idpButton-customizable:hover{color:#fff;background-color:#31b0d5}.socialButton-customizable{height:40px;text-align:left;width:100%;margin-bottom:15px}.redirect-customizable{text-align:center}.passwordCheck-notValid-customizable{color:#df3312}.passwordCheck-valid-customizable{color:#19bf00}.background-customizable{background-color:#fff}"
      }
    },
    "CognitoLoginDesigner": {
      "Type": "Custom::CognitoLogin",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "UserPool": {"Ref": "UserPool"},
        "ClientId": {"Ref": "ClientDesigner"},
        "LoginCallbackUrls": [{"Fn::GetAtt": ["Urls", "Designer"]}],
        "CSS": ".logo-customizable{max-width:60%;max-height:30%}.banner-customizable{padding:25px 0px 25px 0px;background-color:#d3d3d3}.label-customizable{font-weight:410}.textDescription-customizable{padding-top:10px;padding-bottom:10px;display:block;font-size:16px}.idpDescription-customizable{padding-top:10px;padding-bottom:10px;display:block;font-size:16px}.legalText-customizable{color:#747474;font-size:11px}.submitButton-customizable{font-size:14px;font-weight:bold;margin:20px 0px 10px 0px;height:40px;width:100%;color:#fff;background-color:#337ab7}.submitButton-customizable:hover{color:#fff;background-color:#286090}.errorMessage-customizable{padding:5px;font-size:14px;width:100%;background:#f5f5f5;border:2px solid #d64958;color:#d64958}.inputField-customizable{width:100%;height:34px;color:#555;background-color:#fff;border:1px solid #ccc}.inputField-customizable:focus{border-color:#66afe9;outline:0}.idpButton-customizable{height:41px;width:100%;width:100%;text-align:center;margin-bottom:15px;color:#fff;background-color:#5bc0de;border-color:#46b8da}.idpButton-customizable:hover{color:#fff;background-color:#31b0d5}.socialButton-customizable{height:40px;text-align:left;width:100%;margin-bottom:15px}.redirect-customizable{display:none;text-align:center}.passwordCheck-notValid-customizable{color:#df3312}.passwordCheck-valid-customizable{color:#19bf00}.background-customizable{background-color:#fff}"
      }
    },
    "DesignerLogin": {
      "Type": "Custom::CognitoUrl",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "adad": "adaad",
        "ClientId": {"Ref": "ClientDesigner"},
        "Domain": {"Ref": "CognitoDomain"},
        "LoginRedirectUrl": {"Fn::GetAtt": ["Urls", "Designer"]},
        "response_type": "code"
      }
    },
    "ClientLogin": {
      "Type": "Custom::CognitoUrl",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "ClientId": {"Ref": "ClientClient"},
        "Domain": {"Ref": "CognitoDomain"},
        "LoginRedirectUrl": {"Fn::GetAtt": ["Urls", "Client"]},
        "response_type": "token"
      }
    },
    "User": {
      "Type": "AWS::Cognito::UserPoolUser",
      "DependsOn": [
        "SignupPermision",
        "MessagePermision",
        "KibanaRoleAttachment",
        "RoleAttachment"
      ],
      "Properties": {
        "DesiredDeliveryMediums": ["EMAIL"],
        "UserAttributes": [{"Name": "email", "Value": {"Ref": "Email"}}],
        "Username": {"Ref": "Username"},
        "UserPoolId": {"Ref": "UserPool"}
      }
    },
    "UserToGroup": {
      "Type": "AWS::Cognito::UserPoolUserToGroupAttachment",
      "Properties": {
        "GroupName": {"Ref": "Admins"},
        "Username": {"Ref": "User"},
        "UserPoolId": {"Ref": "UserPool"}
      }
    },
    "IdPool": {
      "Type": "AWS::Cognito::IdentityPool",
      "Properties": {
        "IdentityPoolName": {
          "Fn::Join": ["-", ["QnaBotIdPool", {"Ref": "AWS::StackName"}]]
        },
        "AllowUnauthenticatedIdentities": true,
        "CognitoIdentityProviders": [
          {
            "ClientId": {"Ref": "ClientDesigner"},
            "ProviderName": {"Fn::GetAtt": ["UserPool", "ProviderName"]},
            "ServerSideTokenCheck": true
          },
          {
            "ClientId": {"Ref": "ClientClient"},
            "ProviderName": {"Fn::GetAtt": ["UserPool", "ProviderName"]},
            "ServerSideTokenCheck": true
          }
        ]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W57",
              "reason": "This IdentityPool has proper restrictions for unauthenticated users"
            }
          ]
        }
      }
    },
    "KibanaIdPool": {
      "Type": "AWS::Cognito::IdentityPool",
      "Properties": {
        "IdentityPoolName": {
          "Fn::Join": ["-", ["KibanaIdPool", {"Ref": "AWS::StackName"}]]
        },
        "AllowUnauthenticatedIdentities": false
      }
    },
    "KibanaRoleAttachment": {
      "Type": "Custom::CognitoRole",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "IdentityPoolId": {"Ref": "KibanaIdPool"},
        "DomainName": {"Fn::GetAtt": ["ESVar", "ESDomain"]},
        "Roles": {
          "authenticated": {"Fn::GetAtt": ["UserRole", "Arn"]},
          "unauthenticated": {"Fn::GetAtt": ["UnauthenticatedRole", "Arn"]}
        },
        "RoleMappings": [
          {
            "ClientId": {"Fn::GetAtt": ["KibanaClient", "ClientId"]},
            "UserPool": {"Ref": "UserPool"},
            "Type": "Rules",
            "AmbiguousRoleResolution": "Deny",
            "RulesConfiguration": {
              "Rules": [
                {
                  "Claim": "cognito:groups",
                  "MatchType": "Contains",
                  "Value": "Admin",
                  "RoleARN": {"Fn::GetAtt": ["KibanaRole", "Arn"]}
                }
              ]
            }
          }
        ]
      }
    },
    "RoleAttachment": {
      "Type": "Custom::CognitoRole",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "IdentityPoolId": {"Ref": "IdPool"},
        "Roles": {
          "authenticated": {"Fn::GetAtt": ["UserRole", "Arn"]},
          "unauthenticated": {"Fn::GetAtt": ["UnauthenticatedRole", "Arn"]}
        },
        "RoleMappings": [
          {
            "ClientId": {"Ref": "ClientClient"},
            "UserPool": {"Ref": "UserPool"},
            "Type": "Rules",
            "AmbiguousRoleResolution": "AuthenticatedRole",
            "RulesConfiguration": {
              "Rules": [
                {
                  "Claim": "cognito:groups",
                  "MatchType": "Contains",
                  "Value": "Admin",
                  "RoleARN": {"Fn::GetAtt": ["UserRole", "Arn"]}
                }
              ]
            }
          },
          {
            "ClientId": {"Ref": "ClientDesigner"},
            "UserPool": {"Ref": "UserPool"},
            "Type": "Rules",
            "AmbiguousRoleResolution": "Deny",
            "RulesConfiguration": {
              "Rules": [
                {
                  "Claim": "cognito:groups",
                  "MatchType": "Contains",
                  "Value": "Admin",
                  "RoleARN": {"Fn::GetAtt": ["AdminRole", "Arn"]}
                }
              ]
            }
          }
        ]
      }
    },
    "UserPool": {
      "Type": "AWS::Cognito::UserPool",
      "Properties": {
        "UserPoolName": {
          "Fn::Join": ["-", ["UserPool", {"Ref": "AWS::StackName"}]]
        },
        "AdminCreateUserConfig": {
          "AllowAdminCreateUserOnly": {"Fn::If": ["AdminSignUp", true, false]},
          "InviteMessageTemplate": {
            "EmailMessage": {
              "Fn::Sub": "<p>Hello {username},\n<p>Welcome to QnABot! Your temporary password is:\n<p>     {####}\n<p>\n<p>When the CloudFormation stack is COMPLETE, use the link below to log in to QnABot Content Designer, set your permanent password, and start building your bot!\n<p>     ${ApiUrl.Name}/pages/designer\n<p>\n<p>Good luck!\n<p>QnABot (www.amazon.com/qnabot)\n"
            },
            "EmailSubject": "Welcome to QnABot!"
          }
        },
        "AliasAttributes": ["email"],
        "AutoVerifiedAttributes": ["email"],
        "Schema": [
          {
            "Required": true,
            "Name": "email",
            "AttributeDataType": "String",
            "Mutable": true
          }
        ],
        "LambdaConfig": {
          "CustomMessage": {"Fn::GetAtt": ["MessageLambda", "Arn"]},
          "PreSignUp": {"Fn::GetAtt": ["SignupLambda", "Arn"]}
        }
      }
    },
    "KibanaClient": {
      "Type": "Custom::ESCognitoClient",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "UserPool": {"Ref": "UserPool"},
        "DomainName": {"Fn::GetAtt": ["ESVar", "ESDomain"]}
      }
    },
    "ClientDesigner": {
      "Type": "AWS::Cognito::UserPoolClient",
      "Properties": {
        "ClientName": {
          "Fn::Join": ["-", ["UserPool", {"Ref": "AWS::StackName"}, "designer"]]
        },
        "GenerateSecret": false,
        "UserPoolId": {"Ref": "UserPool"}
      }
    },
    "ClientClient": {
      "Type": "AWS::Cognito::UserPoolClient",
      "Properties": {
        "ClientName": {
          "Fn::Join": ["-", ["UserPool", {"Ref": "AWS::StackName"}, "client"]]
        },
        "GenerateSecret": false,
        "UserPoolId": {"Ref": "UserPool"}
      }
    },
    "Users": {
      "Type": "AWS::Cognito::UserPoolGroup",
      "Properties": {"GroupName": "Users", "UserPoolId": {"Ref": "UserPool"}}
    },
    "Admins": {
      "Type": "AWS::Cognito::UserPoolGroup",
      "Properties": {"GroupName": "Admins", "UserPoolId": {"Ref": "UserPool"}}
    },
    "DefaultUserPoolJwksUrl": {
      "Type": "AWS::SSM::Parameter",
      "Properties": {
        "Description": "Default QnABot Setting - DO NOT MODIFY",
        "Type": "String",
        "Value": {
          "Fn::Join": [
            "",
            [
              "https://cognito-idp.",
              {"Ref": "AWS::Region"},
              ".amazonaws.com/",
              {"Ref": "UserPool"},
              "/.well-known/jwks.json"
            ]
          ]
        }
      }
    },
    "DefaultQnABotSettings": {
      "Type": "AWS::SSM::Parameter",
      "Properties": {
        "Description": "Default QnABot Settings - DO NOT MODIFY",
        "Type": "String",
        "Tier": "Advanced",
        "Value": {
          "Fn::Sub": [
            "{\"ENABLE_DEBUG_RESPONSES\":\"false\",\"ENABLE_DEBUG_LOGGING\":\"false\",\"ES_USE_KEYWORD_FILTERS\":\"${ES_USE_KEYWORD_FILTERS}\",\"ES_EXPAND_CONTRACTIONS\":\"{\\\"you're\\\":\\\"you are\\\",\\\"I'm\\\":\\\"I am\\\",\\\"can't\\\":\\\"cannot\\\"}\",\"ES_KEYWORD_SYNTAX_TYPES\":\"NOUN,PROPN,VERB,INTJ\",\"ES_SYNTAX_CONFIDENCE_LIMIT\":\".20\",\"ES_MINIMUM_SHOULD_MATCH\":\"2<75%\",\"ES_NO_HITS_QUESTION\":\"no_hits\",\"ES_USE_FUZZY_MATCH\":\"false\",\"ES_PHRASE_BOOST\":\"4\",\"ES_SCORE_ANSWER_FIELD\":\"false\",\"ES_SCORE_TEXT_ITEM_PASSAGES\":\"true\",\"ENABLE_SENTIMENT_SUPPORT\":\"true\",\"ENABLE_MULTI_LANGUAGE_SUPPORT\":\"false\",\"ENABLE_CUSTOM_TERMINOLOGY\":\"false\",\"MINIMUM_CONFIDENCE_SCORE\":0.6,\"ALT_SEARCH_KENDRA_FALLBACK_CONFIDENCE_SCORE\":\"HIGH\",\"ALT_SEARCH_KENDRA_FAQ_CONFIDENCE_SCORE\":\"HIGH\",\"ALT_SEARCH_KENDRA_INDEXES\":\"${DefaultKendraIndexId}\",\"ALT_SEARCH_KENDRA_S3_SIGNED_URLS\":\"true\",\"ALT_SEARCH_KENDRA_S3_SIGNED_URL_EXPIRE_SECS\":300,\"ALT_SEARCH_KENDRA_MAX_DOCUMENT_COUNT\":2,\"ALT_SEARCH_KENDRA_TOP_ANSWER_MESSAGE\":\"Amazon Kendra suggested answer.\",\"ALT_SEARCH_KENDRA_FAQ_MESSAGE\":\"Answer from Amazon Kendra FAQ.\",\"ALT_SEARCH_KENDRA_ANSWER_MESSAGE\":\"While I did not find an exact answer, these search results from Amazon Kendra might be helpful.\",\"ALT_SEARCH_KENDRA_RESPONSE_TYPES\":\"ANSWER,DOCUMENT,QUESTION_ANSWER\",\"ALT_SEARCH_KENDRA_ABBREVIATE_MESSAGE_FOR_SSML\":\"true\",\"KENDRA_FAQ_INDEX\":\"${DefaultKendraIndexId}\",\"KENDRA_FAQ_CONFIG_MAX_RETRIES\":8,\"KENDRA_FAQ_CONFIG_RETRY_DELAY\":600,\"KENDRA_FAQ_ES_FALLBACK\":\"true\",\"ENABLE_KENDRA_WEB_INDEXER\":\"false\",\"KENDRA_INDEXER_URLS\":\"\",\"KENDRA_INDEXER_CRAWL_DEPTH\":3,\"KENDRA_INDEXER_CRAWL_MODE\":\"SUBDOMAINS\",\"KENDRA_INDEXER_SCHEDULE\":\"rate(1 day)\",\"KENDRA_WEB_PAGE_INDEX\":\"${DefaultKendraIndexId}\",\"KENDRA_INDEXED_DOCUMENTS_LANGUAGES\":\"en\",\"ERRORMESSAGE\":\"Unfortunately I encountered an error when searching for your answer. Please ask me again later.\",\"EMPTYMESSAGE\":\"You stumped me! Sadly I do not know how to answer your question.\",\"DEFAULT_ALEXA_LAUNCH_MESSAGE\":\"Hello, Please ask a question\",\"DEFAULT_ALEXA_REPROMPT\":\"Please either answer the question, ask another question or say Goodbye to end the conversation.\",\"DEFAULT_ALEXA_STOP_MESSAGE\":\"Goodbye\",\"SMS_HINT_REMINDER_ENABLE\":\"true\",\"SMS_HINT_REMINDER\":\" (Feedback? Reply THUMBS UP or THUMBS DOWN. Ask HELP ME at any time)\",\"SMS_HINT_REMINDER_INTERVAL_HRS\":\"24\",\"IDENTITY_PROVIDER_JWKS_URLS\":[],\"ENFORCE_VERIFIED_IDENTITY\":\"false\",\"NO_VERIFIED_IDENTITY_QUESTION\":\"no_verified_identity\",\"ELICIT_RESPONSE_MAX_RETRIES\":3,\"ELICIT_RESPONSE_RETRY_MESSAGE\":\"Please try again.\",\"ELICIT_RESPONSE_BOT_FAILURE_MESSAGE\":\"Your response was not understood. Please start again.\",\"ELICIT_RESPONSE_DEFAULT_MSG\":\"Ok. \",\"CONNECT_IGNORE_WORDS\":\"\",\"CONNECT_ENABLE_VOICE_RESPONSE_INTERRUPT\":\"false\",\"CONNECT_NEXT_PROMPT_VARNAME\":\"connect_nextPrompt\",\"ENABLE_REDACTING\":\"false\",\"REDACTING_REGEX\":\"\\\\b\\\\d{4}\\\\b(?![-])|\\\\b\\\\d{9}\\\\b|\\\\b\\\\d{3}-\\\\d{2}-\\\\d{4}\\\\b\",\"ENABLE_REDACTING_WITH_COMPREHEND\":\"false\",\"COMPREHEND_REDACTING_CONFIDENCE_SCORE\":0.99,\"COMPREHEND_REDACTING_ENTITY_TYPES\":\"ADDRESS,EMAIL,SSN,PHONE,PASSWORD,BANK_ACCOUNT_NUMBER,BANK_ROUTING,CREDIT_DEBIT_NUMBER\",\"PII_REJECTION_ENABLED\":false,\"PII_REJECTION_QUESTION\":\"pii_rejection_question\",\"PII_REJECTION_REGEX\":\"\\\\b\\\\d{4}\\\\b(?![-])|\\\\b\\\\d{9}\\\\b|\\\\b\\\\d{3}-\\\\d{2}-\\\\d{4}\\\\b\",\"PII_REJECTION_ENTITY_TYPES\":\"ADDRESS,EMAIL,SSN,PHONE,PASSWORD,BANK_ACCOUNT_NUMBER,BANK_ROUTING,CREDIT_DEBIT_NUMBER\",\"PII_REJECTION_CONFIDENCE_SCORE\":0.99,\"DISABLE_CLOUDWATCH_LOGGING\":\"false\",\"MINIMAL_ES_LOGGING\":\"false\",\"S3_PUT_REQUEST_ENCRYPTION\":\"\",\"BOT_ROUTER_WELCOME_BACK_MSG\":\"Welcome back to QnABot.\",\"BOT_ROUTER_EXIT_MSGS\":\"exit,quit,goodbye,leave\",\"RUN_LAMBDAHOOK_FROM_QUERY_STEP\":\"true\",\"LAMBDA_PREPROCESS_HOOK\":\"\",\"LAMBDA_POSTPROCESS_HOOK\":\"\",\"SEARCH_REPLACE_QUESTION_SUBSTRINGS\":\"\",\"EMBEDDINGS_ENABLE\":\"${EMBEDDINGS_ENABLE}\",\"EMBEDDINGS_SCORE_THRESHOLD\":0.85,\"EMBEDDINGS_SCORE_ANSWER_THRESHOLD\":0.8,\"EMBEDDINGS_TEXT_PASSAGE_SCORE_THRESHOLD\":0.8,\"LLM_API\":\"${LLMApi}\",\"LLM_GENERATE_QUERY_ENABLE\":\"${LLM_GENERATE_QUERY_ENABLE}\",\"LLM_GENERATE_QUERY_PROMPT_TEMPLATE\":\"${LLM_GENERATE_QUERY_PROMPT_TEMPLATE}\",\"LLM_GENERATE_QUERY_MODEL_PARAMS\":\"${LLM_GENERATE_QUERY_MODEL_PARAMS}\",\"LLM_QA_ENABLE\":\"${LLM_QA_ENABLE}\",\"LLM_QA_USE_KENDRA_RETRIEVAL_API\":\"${LLM_QA_ENABLE}\",\"LLM_QA_PROMPT_TEMPLATE\":\"${LLM_QA_PROMPT_TEMPLATE}\",\"LLM_QA_MODEL_PARAMS\":\"${LLM_QA_MODEL_PARAMS}\",\"LLM_QA_PREFIX_MESSAGE\":\"LLM Answer:\",\"LLM_QA_SHOW_CONTEXT_TEXT\":\"TRUE\",\"LLM_QA_SHOW_SOURCE_LINKS\":\"TRUE\",\"LLM_CHAT_HISTORY_MAX_MESSAGES\":12,\"LLM_QA_NO_HITS_REGEX\":\"Sorry,  //remove comment to enable custom no match (no_hits) when LLM does not know the answer.\"}",
            {
              "ES_USE_KEYWORD_FILTERS": {
                "Fn::If": ["EmbeddingsEnable", "FALSE", "TRUE"]
              },
              "EMBEDDINGS_ENABLE": {
                "Fn::If": ["EmbeddingsEnable", "TRUE", "FALSE"]
              },
              "LLM_GENERATE_QUERY_ENABLE": {
                "Fn::If": ["LLMEnable", "TRUE", "FALSE"]
              },
              "LLM_QA_ENABLE": {"Fn::If": ["LLMEnable", "TRUE", "FALSE"]},
              "LLM_GENERATE_QUERY_PROMPT_TEMPLATE": "Given the following conversation and a follow up question, rephrase the follow up question to be a standalone question.<br>Chat History: <br>{history}<br>Follow Up Input: {input}<br>Standalone question:",
              "LLM_QA_PROMPT_TEMPLATE": "Use the following pieces of context to answer the question at the end. If you don't know the answer, just say that you don't know, don't try to make up an answer. Write the answer in up to 5 complete sentences.<br><br>{context}<br><br>Question: {query}<br>Helpful Answer:",
              "LLM_GENERATE_QUERY_MODEL_PARAMS": "{\\\"temperature\\\":0.01, \\\"return_full_text\\\":false, \\\"max_new_tokens\\\": 150}",
              "LLM_QA_MODEL_PARAMS": "{\\\"temperature\\\":0.01, \\\"return_full_text\\\":false, \\\"max_new_tokens\\\": 150}"
            }
          ]
        }
      }
    },
    "CustomQnABotSettings": {
      "Type": "AWS::SSM::Parameter",
      "Properties": {
        "Description": "Custom QnABot Settings - Modify to override defaults, or to add new settings",
        "Type": "String",
        "Value": "{}"
      }
    },
    "UsersTable": {
      "Type": "AWS::DynamoDB::Table",
      "Properties": {
        "BillingMode": "PAY_PER_REQUEST",
        "PointInTimeRecoverySpecification": {
          "PointInTimeRecoveryEnabled": true
        },
        "AttributeDefinitions": [
          {"AttributeName": "UserId", "AttributeType": "S"}
        ],
        "KeySchema": [{"AttributeName": "UserId", "KeyType": "HASH"}]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W74",
              "reason": "This DynamoDB table does not require CMK encryption store in KMS"
            }
          ]
        }
      }
    },
    "OpensearchDomain": {
      "Type": "AWS::OpenSearchService::Domain",
      "DependsOn": ["PreUpgradeExport"],
      "Condition": "CreateDomain",
      "Properties": {
        "CognitoOptions": {
          "Enabled": true,
          "IdentityPoolId": {"Ref": "KibanaIdPool"},
          "RoleArn": {"Fn::GetAtt": ["ESCognitoRole", "Arn"]},
          "UserPoolId": {"Ref": "UserPool"}
        },
        "ClusterConfig": {
          "DedicatedMasterEnabled": false,
          "InstanceCount": {"Ref": "ElasticSearchNodeCount"},
          "InstanceType": {
            "Fn::If": ["Encrypted", "m6g.large.search", "t3.small.search"]
          },
          "ZoneAwarenessEnabled": {"Fn::If": ["SingleNode", false, true]}
        },
        "EBSOptions": {
          "EBSEnabled": true,
          "VolumeSize": {"Ref": "ElasticSearchEBSVolumeSize"},
          "VolumeType": "gp2"
        },
        "EngineVersion": "OpenSearch_1.3",
        "SnapshotOptions": {"AutomatedSnapshotStartHour": "0"},
        "AdvancedOptions": {"rest.action.multi.allow_explicit_index": "true"},
        "EncryptionAtRestOptions": {
          "Enabled": {"Fn::If": ["Encrypted", true, false]}
        },
        "NodeToNodeEncryptionOptions": {
          "Enabled": {"Fn::If": ["Encrypted", true, false]}
        },
        "DomainEndpointOptions": {
          "EnforceHTTPS": {"Fn::If": ["Encrypted", true, false]}
        },
        "VPCOptions": {
          "Fn::If": [
            "VPCEnabled",
            {
              "SubnetIds": [{"Ref": "AWS::NoValue"}],
              "SecurityGroupIds": [{"Ref": "AWS::NoValue"}]
            },
            {"Ref": "AWS::NoValue"}
          ]
        }
      }
    },
    "ESCognitoRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {"Service": "es.amazonaws.com"},
              "Action": "sts:AssumeRole"
            }
          ]
        },
        "Path": "/",
        "Policies": [
          {
            "PolicyName": "AWSQnaBotESCognitoAccess",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "cognito-idp:DescribeUserPool",
                    "cognito-idp:CreateUserPoolClient",
                    "cognito-idp:DeleteUserPoolClient",
                    "cognito-idp:DescribeUserPoolClient",
                    "cognito-idp:AdminInitiateAuth",
                    "cognito-idp:AdminUserGlobalSignOut",
                    "cognito-idp:ListUserPoolClients"
                  ],
                  "Resource": [{"Fn::GetAtt": ["UserPool", "Arn"]}]
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "cognito-identity:DescribeIdentityPool",
                    "cognito-identity:UpdateIdentityPool",
                    "cognito-identity:GetIdentityPoolRoles"
                  ],
                  "Resource": [
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:cognito-identity:${AWS::Region}:${AWS::AccountId}:identitypool/*"
                    }
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": ["cognito-identity:SetIdentityPoolRoles"],
                  "Resource": "*"
                },
                {
                  "Effect": "Allow",
                  "Action": "iam:PassRole",
                  "Resource": [
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/${AWS::StackName}-*"
                    }
                  ],
                  "Condition": {
                    "StringLike": {
                      "iam:PassedToService": "cognito-identity.amazonaws.com"
                    }
                  }
                }
              ]
            }
          }
        ]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W11",
              "reason": "This IAM role requires to have * resource on its permission policy"
            },
            {
              "id": "W12",
              "reason": "Lambda needs the following minimum required permissions to send trace data to X-Ray"
            },
            {
              "id": "F38",
              "reason": "This role policy is required to have * action in its policy with PassRole action"
            }
          ]
        }
      }
    },
    "ESInfo": {
      "Type": "Custom::ESProxy",
      "Condition": "DontCreateDomain",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["ESProxyLambda", "Arn"]},
        "name": "EMPTY"
      }
    },
    "ESInfoLambda": {
      "Type": "AWS::Lambda::Function",
      "Condition": "DontCreateDomain",
      "Properties": {
        "Code": {
          "ZipFile": "var aws=require('aws-sdk')\naws.config.region=process.env.AWS_REGION\nvar es=new aws.ES()\n\nexports.handler = function(event, context) {\n    console.log(JSON.stringify(event,null,2))\n\n    if(event.RequestType!==\"Delete\"){\n        es.describeElasticsearchDomain({\n            DomainName:event.ResourceProperties.name\n        }).promise()\n        .then(info=>{\n            send(event, context, SUCCESS,{\n                Name:DomainStatus.DomainName,\n                Arn:DomainStatus.ARN,\n                Endpoint:DomainStatus.Endpoints\n            })\n        })\n        .catch(x=>{\n            console.log(x)\n            send(event, context, FAILED)\n        })\n       \n    }else{\n        send(event, context, SUCCESS)\n    }\n}\n\n\nconst SUCCESS = \"SUCCESS\";\nconst FAILED = \"FAILED\";\n\nfunction send(event, context, responseStatus, responseData, physicalResourceId, noEcho) {\n\n    var responseBody = JSON.stringify({\n        Status: responseStatus,\n        Reason: \"See the details in CloudWatch Log Stream: \" + context.logStreamName,\n        PhysicalResourceId: physicalResourceId || context.logStreamName,\n        StackId: event.StackId,\n        RequestId: event.RequestId,\n        LogicalResourceId: event.LogicalResourceId,\n        NoEcho: noEcho || false,\n        Data: responseData\n    });\n\n    console.log(\"Response body:\\n\", responseBody);\n\n    var https = require(\"https\");\n    var url = require(\"url\");\n\n    var parsedUrl = url.parse(event.ResponseURL);\n    var options = {\n        hostname: parsedUrl.hostname,\n        port: 443,\n        path: parsedUrl.path,\n        method: \"PUT\",\n        headers: {\n            \"content-type\": \"\",\n            \"content-length\": responseBody.length\n        }\n    };\n\n    var request = https.request(options, function(response) {\n        console.log(\"Status code: \" + response.statusCode);\n        console.log(\"Status message: \" + response.statusMessage);\n        context.done();\n    });\n\n    request.on(\"error\", function(error) {\n        console.log(\"send(..) failed executing https.request(..): \" + error);\n        context.done();\n    });\n\n    request.write(responseBody);\n    request.end();\n}\n"
        },
        "Handler": "index.handler",
        "MemorySize": "128",
        "Role": {"Fn::GetAtt": ["ESProxyLambdaRole", "Arn"]},
        "Runtime": "nodejs18.x",
        "Timeout": 300,
        "VpcConfig": {
          "Fn::If": [
            "VPCEnabled",
            {
              "SubnetIds": [{"Ref": "AWS::NoValue"}],
              "SecurityGroupIds": [{"Ref": "AWS::NoValue"}]
            },
            {"Ref": "AWS::NoValue"}
          ]
        },
        "TracingConfig": {
          "Fn::If": ["XRAYEnabled", {"Mode": "Active"}, {"Ref": "AWS::NoValue"}]
        },
        "Layers": [{"Ref": "AwsSdkLayerLambdaLayer"}],
        "Tags": [{"Key": "Type", "Value": "CustomResource"}]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W92",
              "reason": "This lambda function does not require to have ReservedConcurrentExecutions"
            }
          ]
        }
      }
    },
    "FeedbackFirehose": {
      "Type": "AWS::KinesisFirehose::DeliveryStream",
      "Properties": {
        "DeliveryStreamType": "DirectPut",
        "DeliveryStreamEncryptionConfigurationInput": {
          "KeyType": "AWS_OWNED_CMK"
        },
        "ElasticsearchDestinationConfiguration": {
          "BufferingHints": {"IntervalInSeconds": 60, "SizeInMBs": 5},
          "DomainARN": {"Fn::GetAtt": ["ESVar", "ESArn"]},
          "IndexName": {"Fn::Sub": "${Var.FeedbackIndex}"},
          "IndexRotationPeriod": "NoRotation",
          "RetryOptions": {"DurationInSeconds": 300},
          "RoleARN": {"Fn::GetAtt": ["FirehoseESS3Role", "Arn"]},
          "S3BackupMode": "AllDocuments",
          "S3Configuration": {
            "BucketARN": {"Fn::GetAtt": ["MetricsBucket", "Arn"]},
            "BufferingHints": {"IntervalInSeconds": 60, "SizeInMBs": 5},
            "Prefix": "feedback/",
            "CompressionFormat": "UNCOMPRESSED",
            "RoleARN": {"Fn::GetAtt": ["FirehoseESS3Role", "Arn"]}
          },
          "TypeName": "",
          "VpcConfiguration": {
            "Fn::If": [
              "VPCEnabled",
              {
                "RoleARN": {"Fn::GetAtt": ["FirehoseESS3Role", "Arn"]},
                "SubnetIds": [{"Ref": "AWS::NoValue"}],
                "SecurityGroupIds": [{"Ref": "AWS::NoValue"}]
              },
              {"Ref": "AWS::NoValue"}
            ]
          }
        }
      }
    },
    "GeneralFirehose": {
      "Type": "AWS::KinesisFirehose::DeliveryStream",
      "Properties": {
        "DeliveryStreamType": "DirectPut",
        "DeliveryStreamEncryptionConfigurationInput": {
          "KeyType": "AWS_OWNED_CMK"
        },
        "ElasticsearchDestinationConfiguration": {
          "BufferingHints": {"IntervalInSeconds": 60, "SizeInMBs": 5},
          "DomainARN": {"Fn::GetAtt": ["ESVar", "ESArn"]},
          "IndexName": {"Fn::Sub": "${Var.MetricsIndex}"},
          "IndexRotationPeriod": "NoRotation",
          "RetryOptions": {"DurationInSeconds": 300},
          "RoleARN": {"Fn::GetAtt": ["FirehoseESS3Role", "Arn"]},
          "S3BackupMode": "AllDocuments",
          "S3Configuration": {
            "BucketARN": {"Fn::GetAtt": ["MetricsBucket", "Arn"]},
            "Prefix": "metrics/",
            "BufferingHints": {"IntervalInSeconds": 60, "SizeInMBs": 5},
            "CompressionFormat": "UNCOMPRESSED",
            "RoleARN": {"Fn::GetAtt": ["FirehoseESS3Role", "Arn"]}
          },
          "TypeName": "",
          "VpcConfiguration": {
            "Fn::If": [
              "VPCEnabled",
              {
                "RoleARN": {"Fn::GetAtt": ["FirehoseESS3Role", "Arn"]},
                "SubnetIds": [{"Ref": "AWS::NoValue"}],
                "SecurityGroupIds": [{"Ref": "AWS::NoValue"}]
              },
              {"Ref": "AWS::NoValue"}
            ]
          }
        }
      }
    },
    "MetricsBucket": {
      "Type": "AWS::S3::Bucket",
      "DeletionPolicy": "Delete",
      "Properties": {
        "BucketEncryption": {
          "Fn::If": [
            "Encrypted",
            {
              "ServerSideEncryptionConfiguration": [
                {"ServerSideEncryptionByDefault": {"SSEAlgorithm": "AES256"}}
              ]
            },
            {"Ref": "AWS::NoValue"}
          ]
        },
        "PublicAccessBlockConfiguration": {
          "BlockPublicAcls": true,
          "BlockPublicPolicy": true,
          "IgnorePublicAcls": true,
          "RestrictPublicBuckets": true
        },
        "Tags": [{"Key": "Use", "Value": "Metrics"}]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W35",
              "reason": "Access logging is not required for this Bucket."
            }
          ]
        }
      }
    },
    "HTTPSOnlyMetricBucketsPolicy": {
      "Type": "AWS::S3::BucketPolicy",
      "Properties": {
        "Bucket": {"Ref": "MetricsBucket"},
        "PolicyDocument": {
          "Statement": [
            {
              "Action": "*",
              "Condition": {"Bool": {"aws:SecureTransport": "false"}},
              "Effect": "Deny",
              "Principal": "*",
              "Resource": {
                "Fn::Join": [
                  "",
                  [{"Fn::GetAtt": ["MetricsBucket", "Arn"]}, "/*"]
                ]
              },
              "Sid": "HttpsOnly"
            }
          ],
          "Version": "2012-10-17"
        }
      }
    },
    "MetricsBucketClear": {
      "Type": "Custom::S3Clear",
      "DependsOn": ["CFNInvokePolicy"],
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "Bucket": {"Ref": "MetricsBucket"}
      }
    },
    "FirehoseESS3Role": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {"Service": "firehose.amazonaws.com"},
              "Action": "sts:AssumeRole"
            }
          ]
        },
        "Path": "/",
        "Policies": [
          {
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Sid": "",
                  "Effect": "Allow",
                  "Action": [
                    "s3:AbortMultipartUpload",
                    "s3:GetBucketLocation",
                    "s3:GetObject",
                    "s3:ListBucket",
                    "s3:ListBucketMultipartUploads",
                    "s3:PutObject"
                  ],
                  "Resource": [
                    {"Fn::GetAtt": ["MetricsBucket", "Arn"]},
                    {
                      "Fn::Join": [
                        "",
                        [{"Fn::GetAtt": ["MetricsBucket", "Arn"]}, "/*"]
                      ]
                    }
                  ]
                },
                {
                  "Sid": "",
                  "Effect": "Allow",
                  "Action": [
                    "lambda:InvokeFunction",
                    "lambda:GetFunctionConfiguration"
                  ],
                  "Resource": [
                    {
                      "Fn::Join": [
                        "",
                        [
                          "arn:aws:lambda:",
                          {"Ref": "AWS::Region"},
                          ":",
                          {"Ref": "AWS::AccountId"},
                          ":function:%FIREHOSE_DEFAULT_FUNCTION%:%FIREHOSE_DEFAULT_VERSION%"
                        ]
                      ]
                    }
                  ]
                },
                {
                  "Sid": "",
                  "Effect": "Allow",
                  "Action": [
                    "es:DescribeElasticsearchDomain",
                    "es:DescribeElasticsearchDomains",
                    "es:DescribeElasticsearchDomainConfig",
                    "es:ESHttpPost",
                    "es:ESHttpPut",
                    "es:ESHttpGet"
                  ],
                  "Resource": [
                    {"Fn::GetAtt": ["ESVar", "ESArn"]},
                    {
                      "Fn::Join": [
                        "",
                        [{"Fn::GetAtt": ["ESVar", "ESArn"]}, "/*"]
                      ]
                    }
                  ]
                },
                {
                  "Sid": "",
                  "Effect": "Allow",
                  "Action": ["logs:PutLogEvents"],
                  "Resource": [
                    {
                      "Fn::Join": [
                        "",
                        [
                          "arn:aws:logs:",
                          {"Ref": "AWS::Region"},
                          ":",
                          {"Ref": "AWS::AccountId"},
                          ":log-group:/aws/kinesisfirehose/*"
                        ]
                      ]
                    }
                  ]
                },
                {
                  "Sid": "",
                  "Effect": "Allow",
                  "Action": [
                    "ec2:DescribeVpcs",
                    "ec2:DescribeVpcAttribute",
                    "ec2:DescribeSubnets",
                    "ec2:DescribeSecurityGroups",
                    "ec2:DescribeNetworkInterfaces",
                    "ec2:CreateNetworkInterface",
                    "ec2:CreateNetworkInterfacePermission",
                    "ec2:DeleteNetworkInterface"
                  ],
                  "Resource": "*"
                }
              ]
            },
            "PolicyName": "QnAFirehose"
          }
        ]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W11",
              "reason": "This IAM role requires to have * resource on its permission policy"
            }
          ]
        }
      }
    },
    "ESCFNProxyLambda": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Code": {
          "S3Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
          "S3Key": {"Fn::Sub": "qnabot-on-aws/v5.4.0/lambda/proxy-es.zip"},
          "S3ObjectVersion": {"Ref": "ESProxyCodeVersion"}
        },
        "Environment": {
          "Variables": {
            "DEFAULT_SETTINGS_PARAM": {"Ref": "DefaultQnABotSettings"},
            "CUSTOM_SETTINGS_PARAM": {"Ref": "CustomQnABotSettings"}
          }
        },
        "Layers": [
          {"Ref": "AwsSdkLayerLambdaLayer"},
          {"Ref": "CommonModulesLambdaLayer"},
          {"Ref": "CfnLambdaLayer"},
          {"Ref": "EsProxyLambdaLayer"},
          {"Ref": "QnABotCommonLambdaLayer"}
        ],
        "Handler": "resource.handler",
        "MemorySize": "1408",
        "Role": {"Fn::GetAtt": ["ESProxyLambdaRole", "Arn"]},
        "Runtime": "nodejs18.x",
        "Timeout": 300,
        "VpcConfig": {
          "Fn::If": [
            "VPCEnabled",
            {
              "SubnetIds": [{"Ref": "AWS::NoValue"}],
              "SecurityGroupIds": [{"Ref": "AWS::NoValue"}]
            },
            {"Ref": "AWS::NoValue"}
          ]
        },
        "TracingConfig": {
          "Fn::If": ["XRAYEnabled", {"Mode": "Active"}, {"Ref": "AWS::NoValue"}]
        },
        "Tags": [{"Key": "Type", "Value": "CustomResource"}]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W92",
              "reason": "This lambda function does not require to have ReservedConcurrentExecutions"
            }
          ]
        }
      }
    },
    "MetricsIndex": {
      "Type": "Custom::ESProxy",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["ESCFNProxyLambda", "Arn"]},
        "create": {
          "index": {"Fn::Sub": "${Var.MetricsIndex}"},
          "endpoint": {"Fn::GetAtt": ["ESVar", "ESAddress"]},
          "body": {
            "Fn::Sub": "{\"settings\":{\"index.mapping.total_fields.limit\":2000}}"
          }
        }
      }
    },
    "FeedbackIndex": {
      "Type": "Custom::ESProxy",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["ESCFNProxyLambda", "Arn"]},
        "create": {
          "index": {"Fn::Sub": "${Var.FeedbackIndex}"},
          "endpoint": {"Fn::GetAtt": ["ESVar", "ESAddress"]},
          "body": {"Fn::Sub": "{\"settings\":{}}"}
        }
      }
    },
    "Index": {
      "Type": "Custom::ESProxy",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["ESCFNProxyLambda", "Arn"]},
        "create": {
          "index": {"Fn::Sub": "${Var.QnaIndex}"},
          "endpoint": {"Fn::GetAtt": ["ESVar", "ESAddress"]},
          "body": {
            "Fn::Sub": [
              "{\"settings\":{\"number_of_shards\":\"1\",\"index.knn\":true,\"analysis\":{\"filter\":{\"english_stop\":{\"type\":\"stop\",\"stopwords\":[\"a\",\"an\",\"and\",\"are\",\"as\",\"at\",\"be\",\"but\",\"by\",\"for\",\"if\",\"in\",\"into\",\"is\",\"it\",\"not\",\"of\",\"on\",\"or\",\"such\",\"that\",\"the\",\"their\",\"then\",\"there\",\"these\",\"they\",\"this\",\"to\",\"was\",\"will\",\"with\"]},\"english_keywords\":{\"type\":\"keyword_marker\",\"keywords\":[\"example\"]},\"english_stemmer\":{\"type\":\"stemmer\",\"language\":\"english\"},\"english_possessive_stemmer\":{\"type\":\"stemmer\",\"language\":\"possessive_english\"}},\"analyzer\":{\"custom_english\":{\"type\":\"custom\",\"tokenizer\":\"standard\",\"filter\":[\"english_possessive_stemmer\",\"lowercase\",\"english_stop\",\"english_keywords\",\"english_stemmer\"]},\"custom_english_unique\":{\"type\":\"custom\",\"tokenizer\":\"standard\",\"filter\":[\"english_possessive_stemmer\",\"lowercase\",\"english_stop\",\"english_keywords\",\"english_stemmer\",\"unique\"]}}}},\"mappings\":{\"properties\":{\"qid\":{\"type\":\"keyword\"},\"quniqueterms\":{\"type\":\"text\",\"analyzer\":\"custom_english_unique\"},\"questions\":{\"type\":\"nested\",\"properties\":{\"q\":{\"type\":\"text\",\"analyzer\":\"custom_english\"},\"q_vector\":{\"type\":\"knn_vector\",\"dimension\":\"${EmbeddingsDimensions}\",\"method\":{\"name\":\"hnsw\",\"space_type\":\"cosinesimil\",\"engine\":\"nmslib\"}}}},\"a\":{\"type\":\"text\",\"analyzer\":\"custom_english\"},\"a_vector\":{\"type\":\"knn_vector\",\"dimension\":\"${EmbeddingsDimensions}\",\"method\":{\"name\":\"hnsw\",\"space_type\":\"cosinesimil\",\"engine\":\"nmslib\"}},\"t\":{\"type\":\"text\",\"analyzer\":\"whitespace\"},\"r\":{\"properties\":{\"imageUrl\":{\"type\":\"keyword\"},\"title\":{\"type\":\"text\"}}},\"l\":{\"type\":\"keyword\"},\"passage\":{\"type\":\"text\",\"analyzer\":\"custom_english\"},\"passage_vector\":{\"type\":\"knn_vector\",\"dimension\":\"${EmbeddingsDimensions}\",\"method\":{\"name\":\"hnsw\",\"space_type\":\"cosinesimil\",\"engine\":\"nmslib\"}},\"question\":{\"type\":\"text\",\"analyzer\":\"custom_english\"},\"incorrectAnswers\":{\"type\":\"text\",\"analyzer\":\"custom_english\"},\"correctAnswers\":{\"type\":\"text\",\"analyzer\":\"custom_english\"}}}}",
              {
                "EmbeddingsDimensions": {
                  "Fn::If": [
                    "EmbeddingsEnable",
                    {
                      "Fn::If": [
                        "EmbeddingsSagemaker",
                        "1024",
                        {
                          "Fn::If": [
                            "EmbeddingsLambda",
                            {"Ref": "EmbeddingsLambdaDimensions"},
                            "INVALID EMBEDDINGS API - Cannot determine dimensions"
                          ]
                        }
                      ]
                    },
                    "1"
                  ]
                }
              }
            ]
          }
        }
      }
    },
    "KibanaDashboards": {
      "Type": "Custom::ESProxy",
      "DependsOn": ["Index"],
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["ESCFNProxyLambda", "Arn"]},
        "create": {
          "endpoint": {"Fn::GetAtt": ["ESVar", "ESAddress"]},
          "path": "/_dashboards/api/opensearch-dashboards/dashboards/import?force=true",
          "method": "POST",
          "headers": {"osd-xsrf": "true"},
          "body": {
            "version": "1.3.0",
            "objects": [
              {
                "id": "052b1350-a37d-11ea-8370-0f1df276cae1",
                "type": "dashboard",
                "namespaces": ["default"],
                "updated_at": "2022-12-04T21:21:27.535Z",
                "version": "WzAsMV0=",
                "attributes": {
                  "hits": "0",
                  "timeFrom": "now/w",
                  "timeTo": "now/w",
                  "refreshInterval": {"value": "0", "pause": "true"},
                  "description": "Visualize QnABot usage, see what your users are asking, and use the \"No Hits\" and \"Feedback\" charts to assess where you should add or tune QnABot content to make the bot smarter. ",
                  "title": "QnABot Dashboard",
                  "timeRestore": "false",
                  "version": "1",
                  "panelsJSON": "[{\"embeddableConfig\":{\"legendOpen\":false,\"vis\":{\"legendOpen\":true}},\"gridData\":{\"h\":15,\"i\":\"fb115451-3b8a-436f-b916-8a04db4e9d70\",\"w\":17,\"x\":0,\"y\":0},\"panelIndex\":\"fb115451-3b8a-436f-b916-8a04db4e9d70\",\"version\":\"7.9.1\",\"panelRefName\":\"panel_0\"},{\"embeddableConfig\":{},\"gridData\":{\"h\":15,\"i\":\"5e25d094-b045-4afe-953d-2d619b05b716\",\"w\":14,\"x\":34,\"y\":0},\"panelIndex\":\"5e25d094-b045-4afe-953d-2d619b05b716\",\"version\":\"7.9.1\",\"panelRefName\":\"panel_1\"},{\"embeddableConfig\":{\"legendOpen\":false,\"vis\":{\"legendOpen\":true}},\"gridData\":{\"h\":15,\"i\":\"cf017f39-a5a3-4d3a-9561-862f4c2eb3c5\",\"w\":17,\"x\":17,\"y\":0},\"panelIndex\":\"cf017f39-a5a3-4d3a-9561-862f4c2eb3c5\",\"version\":\"7.9.1\",\"panelRefName\":\"panel_2\"},{\"embeddableConfig\":{},\"gridData\":{\"h\":15,\"i\":\"b9b730b1-b3de-42f9-a4de-69197d934a93\",\"w\":24,\"x\":0,\"y\":15},\"panelIndex\":\"b9b730b1-b3de-42f9-a4de-69197d934a93\",\"version\":\"7.9.1\",\"panelRefName\":\"panel_3\"},{\"embeddableConfig\":{},\"gridData\":{\"h\":15,\"i\":\"472ff8b6-83bf-4e4d-a8a5-44ce8f7e3dac\",\"w\":24,\"x\":24,\"y\":15},\"panelIndex\":\"472ff8b6-83bf-4e4d-a8a5-44ce8f7e3dac\",\"version\":\"7.9.1\",\"panelRefName\":\"panel_4\"},{\"embeddableConfig\":{},\"gridData\":{\"h\":15,\"i\":\"92e5cbb2-fa56-4f15-b7b1-72c11e0bebfc\",\"w\":24,\"x\":0,\"y\":30},\"panelIndex\":\"92e5cbb2-fa56-4f15-b7b1-72c11e0bebfc\",\"version\":\"7.9.1\",\"panelRefName\":\"panel_5\"},{\"embeddableConfig\":{},\"gridData\":{\"h\":15,\"i\":\"7ca7cdb0-2472-4eb0-bf7e-ae90f238f869\",\"w\":24,\"x\":24,\"y\":30},\"panelIndex\":\"7ca7cdb0-2472-4eb0-bf7e-ae90f238f869\",\"version\":\"7.9.1\",\"panelRefName\":\"panel_6\"},{\"embeddableConfig\":{},\"gridData\":{\"h\":8,\"i\":\"cba70b74-3264-4153-87d2-68c24b552efa\",\"w\":10,\"x\":0,\"y\":45},\"panelIndex\":\"cba70b74-3264-4153-87d2-68c24b552efa\",\"version\":\"7.9.1\",\"panelRefName\":\"panel_7\"},{\"embeddableConfig\":{},\"gridData\":{\"h\":15,\"i\":\"4fd7e920-26dd-4d02-8235-bcdff5725991\",\"w\":24,\"x\":10,\"y\":45},\"panelIndex\":\"4fd7e920-26dd-4d02-8235-bcdff5725991\",\"version\":\"7.9.1\",\"panelRefName\":\"panel_8\"}]",
                  "optionsJSON": "{\"hidePanelTitles\":false,\"useMargins\":true}",
                  "kibanaSavedObjectMeta": {
                    "searchSourceJSON": "{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[]}"
                  }
                },
                "references": [
                  {
                    "name": "panel_0",
                    "id": "a66d5ed0-a378-11ea-8370-0f1df276cae1",
                    "type": "visualization"
                  },
                  {
                    "name": "panel_1",
                    "id": "d905b930-a37a-11ea-a346-0f81312f0c3c",
                    "type": "visualization"
                  },
                  {
                    "name": "panel_2",
                    "id": "12d24870-e16c-11ea-b423-5f0e2ad2220e",
                    "type": "visualization"
                  },
                  {
                    "name": "panel_3",
                    "id": "68d7c450-a37a-11ea-8370-0f1df276cae1",
                    "type": "visualization"
                  },
                  {
                    "name": "panel_4",
                    "id": "d68ac390-a379-11ea-8370-0f1df276cae1",
                    "type": "visualization"
                  },
                  {
                    "name": "panel_5",
                    "id": "6759e170-a37b-11ea-8370-0f1df276cae1",
                    "type": "visualization"
                  },
                  {
                    "name": "panel_6",
                    "id": "985eb570-a37b-11ea-8370-0f1df276cae1",
                    "type": "visualization"
                  },
                  {
                    "name": "panel_7",
                    "id": "2031f610-a4c1-11ea-a012-c353d737e5ec",
                    "type": "visualization"
                  },
                  {
                    "name": "panel_8",
                    "id": "49e34620-9198-11eb-ab91-adc4ba11519d",
                    "type": "visualization"
                  }
                ],
                "migrationVersion": {"dashboard": "7.9.3"}
              },
              {
                "id": "a66d5ed0-a378-11ea-8370-0f1df276cae1",
                "type": "visualization",
                "namespaces": ["default"],
                "updated_at": "2022-12-04T21:21:27.535Z",
                "version": "WzEsMV0=",
                "attributes": {
                  "description": "",
                  "uiStateJSON": "{}",
                  "title": "Requests",
                  "version": "1",
                  "kibanaSavedObjectMeta": {
                    "searchSourceJSON": "{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
                  },
                  "visState": "{\"title\":\"Requests\",\"type\":\"histogram\",\"params\":{\"addLegend\":true,\"addTimeMarker\":false,\"addTooltip\":true,\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"labels\":{\"filter\":true,\"show\":true,\"truncate\":100},\"position\":\"bottom\",\"scale\":{\"type\":\"linear\"},\"show\":true,\"style\":{},\"title\":{},\"type\":\"category\"}],\"dimensions\":{\"x\":{\"accessor\":0,\"format\":{\"id\":\"date\",\"params\":{\"pattern\":\"HH:mm:ss\"}},\"params\":{\"date\":true,\"interval\":\"PT30S\",\"format\":\"HH:mm:ss\",\"bounds\":{\"min\":\"2020-07-06T21:55:15.220Z\",\"max\":\"2020-07-06T22:25:15.220Z\"}},\"aggType\":\"date_histogram\"},\"y\":[{\"accessor\":1,\"format\":{\"id\":\"number\"},\"params\":{},\"aggType\":\"cardinality\"}]},\"grid\":{\"categoryLines\":false},\"labels\":{\"show\":false},\"legendPosition\":\"right\",\"seriesParams\":[{\"data\":{\"id\":\"1\",\"label\":\"Count\"},\"drawLinesBetweenPoints\":true,\"mode\":\"stacked\",\"show\":\"true\",\"showCircles\":true,\"type\":\"histogram\",\"valueAxis\":\"ValueAxis-1\"}],\"thresholdLine\":{\"color\":\"#34130C\",\"show\":false,\"style\":\"full\",\"value\":10,\"width\":1},\"times\":[],\"type\":\"histogram\",\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"labels\":{\"filter\":false,\"rotate\":0,\"show\":true,\"truncate\":100},\"name\":\"LeftAxis-1\",\"position\":\"left\",\"scale\":{\"mode\":\"normal\",\"type\":\"linear\"},\"show\":true,\"style\":{},\"title\":{\"text\":\"Count\"},\"type\":\"value\"}]},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"datetime\",\"timeRange\":{\"from\":\"now-30m\",\"to\":\"now\"},\"useNormalizedEsInterval\":true,\"interval\":\"auto\",\"drop_partials\":false,\"min_doc_count\":1,\"extended_bounds\":{},\"customLabel\":\"Requests\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"entireRequest.sentiment.keyword\",\"orderBy\":\"1\",\"order\":\"desc\",\"size\":5,\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"customLabel\":\"Sentiment\"}}]}"
                },
                "references": [
                  {
                    "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
                    "id": "Metrics",
                    "type": "index-pattern"
                  }
                ],
                "migrationVersion": {"visualization": "7.10.0"}
              },
              {
                "id": "d905b930-a37a-11ea-a346-0f81312f0c3c",
                "type": "visualization",
                "namespaces": ["default"],
                "updated_at": "2022-12-04T21:21:27.535Z",
                "version": "WzIsMV0=",
                "attributes": {
                  "description": "",
                  "uiStateJSON": "{}",
                  "title": "Client Types",
                  "version": "1",
                  "kibanaSavedObjectMeta": {
                    "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
                  },
                  "visState": "{\"title\":\"Client Types\",\"type\":\"pie\",\"params\":{\"type\":\"pie\",\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"isDonut\":false,\"labels\":{\"show\":false,\"values\":true,\"last_level\":true,\"truncate\":100},\"dimensions\":{\"metric\":{\"accessor\":1,\"format\":{\"id\":\"number\"},\"params\":{},\"aggType\":\"count\"},\"buckets\":[{\"accessor\":0,\"format\":{\"id\":\"terms\",\"params\":{\"id\":\"string\",\"otherBucketLabel\":\"Other\",\"missingBucketLabel\":\"Missing\"}},\"params\":{},\"aggType\":\"terms\"}]}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"clientType.keyword\",\"orderBy\":\"1\",\"order\":\"desc\",\"size\":5,\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"customLabel\":\"Client Types\"}}]}"
                },
                "references": [
                  {
                    "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
                    "id": "Metrics",
                    "type": "index-pattern"
                  }
                ],
                "migrationVersion": {"visualization": "7.10.0"}
              },
              {
                "id": "12d24870-e16c-11ea-b423-5f0e2ad2220e",
                "type": "visualization",
                "namespaces": ["default"],
                "updated_at": "2022-12-04T21:21:27.535Z",
                "version": "WzMsMV0=",
                "attributes": {
                  "description": "",
                  "uiStateJSON": "{}",
                  "title": "Requests AnswerSource",
                  "version": "1",
                  "kibanaSavedObjectMeta": {
                    "searchSourceJSON": "{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
                  },
                  "visState": "{\"type\":\"histogram\",\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"datetime\",\"timeRange\":{\"from\":\"2020-08-18T15:44:48.334Z\",\"to\":\"2020-08-18T15:59:17.582Z\"},\"useNormalizedEsInterval\":true,\"scaleMetricValues\":false,\"interval\":\"auto\",\"drop_partials\":false,\"min_doc_count\":1,\"extended_bounds\":{},\"customLabel\":\"Requests\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"entireResponse.answerSource.keyword\",\"orderBy\":\"1\",\"order\":\"desc\",\"size\":5,\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"customLabel\":\"Source\"}}],\"params\":{\"addLegend\":true,\"addTimeMarker\":false,\"addTooltip\":true,\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"labels\":{\"filter\":true,\"show\":true,\"truncate\":100},\"position\":\"bottom\",\"scale\":{\"type\":\"linear\"},\"show\":true,\"style\":{},\"title\":{},\"type\":\"category\"}],\"dimensions\":{\"x\":{\"accessor\":0,\"aggType\":\"date_histogram\",\"format\":{\"id\":\"date\",\"params\":{\"pattern\":\"HH:mm:ss\"}},\"params\":{\"bounds\":{\"max\":\"2020-07-06T22:25:15.220Z\",\"min\":\"2020-07-06T21:55:15.220Z\"},\"date\":true,\"format\":\"HH:mm:ss\",\"interval\":\"PT30S\"}},\"y\":[{\"accessor\":1,\"aggType\":\"cardinality\",\"format\":{\"id\":\"number\"},\"params\":{}}]},\"grid\":{\"categoryLines\":false},\"labels\":{\"show\":false},\"legendPosition\":\"right\",\"seriesParams\":[{\"data\":{\"id\":\"1\",\"label\":\"Count\"},\"drawLinesBetweenPoints\":true,\"mode\":\"stacked\",\"show\":\"true\",\"showCircles\":true,\"type\":\"histogram\",\"valueAxis\":\"ValueAxis-1\"}],\"thresholdLine\":{\"color\":\"#34130C\",\"show\":false,\"style\":\"full\",\"value\":10,\"width\":1},\"times\":[],\"type\":\"histogram\",\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"labels\":{\"filter\":false,\"rotate\":0,\"show\":true,\"truncate\":100},\"name\":\"LeftAxis-1\",\"position\":\"left\",\"scale\":{\"mode\":\"normal\",\"type\":\"linear\"},\"show\":true,\"style\":{},\"title\":{\"text\":\"Count\"},\"type\":\"value\"}]},\"title\":\"Requests AnswerSource\"}"
                },
                "references": [
                  {
                    "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
                    "id": "Metrics",
                    "type": "index-pattern"
                  }
                ],
                "migrationVersion": {"visualization": "7.10.0"}
              },
              {
                "id": "68d7c450-a37a-11ea-8370-0f1df276cae1",
                "type": "visualization",
                "namespaces": ["default"],
                "updated_at": "2022-12-04T21:21:27.535Z",
                "version": "WzQsMV0=",
                "attributes": {
                  "description": "",
                  "uiStateJSON": "{}",
                  "title": "Logged Utterances",
                  "version": "1",
                  "kibanaSavedObjectMeta": {
                    "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
                  },
                  "visState": "{\"title\":\"Logged Utterances\",\"type\":\"tagcloud\",\"params\":{\"scale\":\"linear\",\"orientation\":\"single\",\"minFontSize\":18,\"maxFontSize\":72,\"showLabel\":true,\"metric\":{\"type\":\"vis_dimension\",\"accessor\":0,\"format\":{\"id\":\"string\",\"params\":{}}}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"utterance.keyword\",\"orderBy\":\"1\",\"order\":\"desc\",\"size\":1000,\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"customLabel\":\"Logged Utterances\"}}]}"
                },
                "references": [
                  {
                    "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
                    "id": "Metrics",
                    "type": "index-pattern"
                  }
                ],
                "migrationVersion": {"visualization": "7.10.0"}
              },
              {
                "id": "d68ac390-a379-11ea-8370-0f1df276cae1",
                "type": "visualization",
                "namespaces": ["default"],
                "updated_at": "2022-12-04T21:21:27.535Z",
                "version": "WzUsMV0=",
                "attributes": {
                  "description": "",
                  "uiStateJSON": "{}",
                  "title": "No Hits",
                  "version": "1",
                  "kibanaSavedObjectMeta": {
                    "searchSourceJSON": "{\"query\":{\"query\":\"entireResponse.got_hits:0\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
                  },
                  "visState": "{\"title\":\"No Hits\",\"type\":\"tagcloud\",\"params\":{\"scale\":\"linear\",\"orientation\":\"single\",\"minFontSize\":18,\"maxFontSize\":72,\"showLabel\":true,\"metric\":{\"type\":\"vis_dimension\",\"accessor\":0,\"format\":{\"id\":\"string\",\"params\":{}}}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"utterance.keyword\",\"orderBy\":\"1\",\"order\":\"desc\",\"size\":1000,\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"customLabel\":\"No Hits\"}}]}"
                },
                "references": [
                  {
                    "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
                    "id": "Metrics",
                    "type": "index-pattern"
                  }
                ],
                "migrationVersion": {"visualization": "7.10.0"}
              },
              {
                "id": "6759e170-a37b-11ea-8370-0f1df276cae1",
                "type": "visualization",
                "namespaces": ["default"],
                "updated_at": "2022-12-04T21:21:27.535Z",
                "version": "WzYsMV0=",
                "attributes": {
                  "description": "",
                  "uiStateJSON": "{}",
                  "title": "Positive Feedback",
                  "version": "1",
                  "kibanaSavedObjectMeta": {
                    "searchSourceJSON": "{\"query\":{\"query\":\"feedback=correct\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
                  },
                  "visState": "{\"title\":\"Positive Feedback\",\"type\":\"tagcloud\",\"params\":{\"scale\":\"linear\",\"orientation\":\"single\",\"minFontSize\":18,\"maxFontSize\":72,\"showLabel\":true,\"metric\":{\"type\":\"vis_dimension\",\"accessor\":0,\"format\":{\"id\":\"string\",\"params\":{}}}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"utterance.keyword\",\"orderBy\":\"1\",\"order\":\"desc\",\"size\":100,\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"customLabel\":\"Thumbs Up\"}}]}"
                },
                "references": [
                  {
                    "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
                    "id": "Feedback",
                    "type": "index-pattern"
                  }
                ],
                "migrationVersion": {"visualization": "7.10.0"}
              },
              {
                "id": "985eb570-a37b-11ea-8370-0f1df276cae1",
                "type": "visualization",
                "namespaces": ["default"],
                "updated_at": "2022-12-04T21:21:27.535Z",
                "version": "WzcsMV0=",
                "attributes": {
                  "description": "",
                  "uiStateJSON": "{}",
                  "title": "Negative Feedback",
                  "version": "1",
                  "kibanaSavedObjectMeta": {
                    "searchSourceJSON": "{\"query\":{\"query\":\"feedback=incorrect\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
                  },
                  "visState": "{\"title\":\"Negative Feedback\",\"type\":\"tagcloud\",\"params\":{\"scale\":\"linear\",\"orientation\":\"single\",\"minFontSize\":18,\"maxFontSize\":72,\"showLabel\":true,\"metric\":{\"type\":\"vis_dimension\",\"accessor\":1,\"format\":{\"id\":\"string\",\"params\":{}}},\"bucket\":{\"type\":\"vis_dimension\",\"accessor\":0,\"format\":{\"id\":\"terms\",\"params\":{\"id\":\"string\",\"otherBucketLabel\":\"Other\",\"missingBucketLabel\":\"Missing\"}}}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"utterance.keyword\",\"orderBy\":\"1\",\"order\":\"desc\",\"size\":100,\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"customLabel\":\"Thumbs Down\"}}]}"
                },
                "references": [
                  {
                    "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
                    "id": "Feedback",
                    "type": "index-pattern"
                  }
                ],
                "migrationVersion": {"visualization": "7.10.0"}
              },
              {
                "id": "2031f610-a4c1-11ea-a012-c353d737e5ec",
                "type": "visualization",
                "namespaces": ["default"],
                "updated_at": "2022-12-04T21:21:27.535Z",
                "version": "WzgsMV0=",
                "attributes": {
                  "description": "",
                  "uiStateJSON": "{}",
                  "title": "QnAItemCount",
                  "version": "1",
                  "kibanaSavedObjectMeta": {
                    "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
                  },
                  "visState": "{\"title\":\"QnAItemCount\",\"type\":\"metric\",\"params\":{\"metric\":{\"percentageMode\":false,\"useRanges\":false,\"colorSchema\":\"Green to Red\",\"metricColorMode\":\"None\",\"colorsRange\":[{\"type\":\"range\",\"from\":0,\"to\":10000}],\"labels\":{\"show\":true},\"invertColors\":false,\"style\":{\"bgFill\":\"#000\",\"bgColor\":false,\"labelColor\":false,\"subText\":\"\",\"fontSize\":60}},\"dimensions\":{\"metrics\":[{\"type\":\"vis_dimension\",\"accessor\":0,\"format\":{\"id\":\"number\",\"params\":{}}}]},\"addTooltip\":true,\"addLegend\":false,\"type\":\"metric\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{\"customLabel\":\"QnA Item Count\"}}]}"
                },
                "references": [
                  {
                    "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
                    "id": "QnaItems",
                    "type": "index-pattern"
                  }
                ],
                "migrationVersion": {"visualization": "7.10.0"}
              },
              {
                "id": "49e34620-9198-11eb-ab91-adc4ba11519d",
                "type": "visualization",
                "namespaces": ["default"],
                "updated_at": "2022-12-04T21:21:27.535Z",
                "version": "WzksMV0=",
                "attributes": {
                  "description": "",
                  "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":0,\"direction\":\"asc\"}}}}",
                  "title": "Answer Sources",
                  "version": "1",
                  "kibanaSavedObjectMeta": {
                    "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
                  },
                  "visState": "{\"title\":\"Answer Sources\",\"type\":\"table\",\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"params\":{},\"schema\":\"metric\"},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"params\":{\"field\":\"entireResponse.result.answersource.keyword\",\"orderBy\":\"1\",\"order\":\"desc\",\"size\":5,\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"customLabel\":\"Answer Source\"},\"schema\":\"bucket\"}],\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMetricsAtAllLevels\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"showTotal\":false,\"totalFunc\":\"sum\",\"percentageCol\":\"\"}}"
                },
                "references": [
                  {
                    "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
                    "id": "Metrics",
                    "type": "index-pattern"
                  }
                ],
                "migrationVersion": {"visualization": "7.10.0"}
              },
              {
                "id": "Metrics",
                "type": "index-pattern",
                "namespaces": ["default"],
                "updated_at": "2022-12-04T21:21:27.535Z",
                "version": "WzEwLDFd",
                "attributes": {
                  "timeFieldName": "datetime",
                  "fields": "[{\"name\":\"_id\",\"type\":\"string\",\"esTypes\":[\"_id\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_index\",\"type\":\"string\",\"esTypes\":[\"_index\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_score\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_source\",\"type\":\"_source\",\"esTypes\":[\"_source\"],\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_type\",\"type\":\"string\",\"esTypes\":[\"_type\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"answer\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"answer.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"answer\"}}},{\"name\":\"clientType\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"clientType.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"clientType\"}}},{\"name\":\"datetime\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireRequest._clientType\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._clientType.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._clientType\"}}},{\"name\":\"entireRequest._event.bot.alias\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._event.bot.alias.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._event.bot.alias\"}}},{\"name\":\"entireRequest._event.bot.name\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._event.bot.name.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._event.bot.name\"}}},{\"name\":\"entireRequest._event.bot.version\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._event.bot.version.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._event.bot.version\"}}},{\"name\":\"entireRequest._event.currentIntent.confirmationStatus\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._event.currentIntent.confirmationStatus.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._event.currentIntent.confirmationStatus\"}}},{\"name\":\"entireRequest._event.currentIntent.name\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._event.currentIntent.name.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._event.currentIntent.name\"}}},{\"name\":\"entireRequest._event.currentIntent.slotDetails.slot.originalValue\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._event.currentIntent.slotDetails.slot.originalValue.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._event.currentIntent.slotDetails.slot.originalValue\"}}},{\"name\":\"entireRequest._event.currentIntent.slotDetails.slot.resolutions.value\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._event.currentIntent.slotDetails.slot.resolutions.value.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._event.currentIntent.slotDetails.slot.resolutions.value\"}}},{\"name\":\"entireRequest._event.currentIntent.slots.slot\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._event.currentIntent.slots.slot.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._event.currentIntent.slots.slot\"}}},{\"name\":\"entireRequest._event.errorFound\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireRequest._event.inputTranscript\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._event.inputTranscript.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._event.inputTranscript\"}}},{\"name\":\"entireRequest._event.invocationSource\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._event.invocationSource.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._event.invocationSource\"}}},{\"name\":\"entireRequest._event.messageVersion\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._event.messageVersion.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._event.messageVersion\"}}},{\"name\":\"entireRequest._event.outputDialogMode\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._event.outputDialogMode.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._event.outputDialogMode\"}}},{\"name\":\"entireRequest._event.recentIntentSummaryView.confirmationStatus\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._event.recentIntentSummaryView.confirmationStatus.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._event.recentIntentSummaryView.confirmationStatus\"}}},{\"name\":\"entireRequest._event.recentIntentSummaryView.dialogActionType\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._event.recentIntentSummaryView.dialogActionType.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._event.recentIntentSummaryView.dialogActionType\"}}},{\"name\":\"entireRequest._event.recentIntentSummaryView.fulfillmentState\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._event.recentIntentSummaryView.fulfillmentState.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._event.recentIntentSummaryView.fulfillmentState\"}}},{\"name\":\"entireRequest._event.recentIntentSummaryView.intentName\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._event.recentIntentSummaryView.intentName.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._event.recentIntentSummaryView.intentName\"}}},{\"name\":\"entireRequest._event.recentIntentSummaryView.slots.slot\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._event.recentIntentSummaryView.slots.slot.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._event.recentIntentSummaryView.slots.slot\"}}},{\"name\":\"entireRequest._event.sessionAttributes.qnabot_gotanswer\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._event.sessionAttributes.qnabot_gotanswer.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._event.sessionAttributes.qnabot_gotanswer\"}}},{\"name\":\"entireRequest._event.sessionAttributes.qnabot_qid\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._event.sessionAttributes.qnabot_qid.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._event.sessionAttributes.qnabot_qid\"}}},{\"name\":\"entireRequest._event.sessionAttributes.qnabotcontext\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._event.sessionAttributes.qnabotcontext.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._event.sessionAttributes.qnabotcontext\"}}},{\"name\":\"entireRequest._event.userId\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._event.userId.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._event.userId\"}}},{\"name\":\"entireRequest._info.es.address\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._info.es.address.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._info.es.address\"}}},{\"name\":\"entireRequest._info.es.index\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._info.es.index.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._info.es.index\"}}},{\"name\":\"entireRequest._info.es.service.proxy\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._info.es.service.proxy.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._info.es.service.proxy\"}}},{\"name\":\"entireRequest._info.es.service.qid\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._info.es.service.qid.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._info.es.service.qid\"}}},{\"name\":\"entireRequest._info.es.type\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._info.es.type.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._info.es.type\"}}},{\"name\":\"entireRequest._preferredResponseType\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._preferredResponseType.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._preferredResponseType\"}}},{\"name\":\"entireRequest._settings.ALT_SEARCH_KENDRA_INDEXES\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._settings.ALT_SEARCH_KENDRA_INDEXES.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._settings.ALT_SEARCH_KENDRA_INDEXES\"}}},{\"name\":\"entireRequest._settings.DEFAULT_ALEXA_LAUNCH_MESSAGE\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._settings.DEFAULT_ALEXA_LAUNCH_MESSAGE.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._settings.DEFAULT_ALEXA_LAUNCH_MESSAGE\"}}},{\"name\":\"entireRequest._settings.DEFAULT_ALEXA_STOP_MESSAGE\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._settings.DEFAULT_ALEXA_STOP_MESSAGE.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._settings.DEFAULT_ALEXA_STOP_MESSAGE\"}}},{\"name\":\"entireRequest._settings.DEFAULT_USER_POOL_JWKS_URL\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._settings.DEFAULT_USER_POOL_JWKS_URL.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._settings.DEFAULT_USER_POOL_JWKS_URL\"}}},{\"name\":\"entireRequest._settings.ELICIT_RESPONSE_BOT_FAILURE_MESSAGE\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._settings.ELICIT_RESPONSE_BOT_FAILURE_MESSAGE.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._settings.ELICIT_RESPONSE_BOT_FAILURE_MESSAGE\"}}},{\"name\":\"entireRequest._settings.ELICIT_RESPONSE_DEFAULT_MSG\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._settings.ELICIT_RESPONSE_DEFAULT_MSG.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._settings.ELICIT_RESPONSE_DEFAULT_MSG\"}}},{\"name\":\"entireRequest._settings.ELICIT_RESPONSE_MAX_RETRIES\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireRequest._settings.ELICIT_RESPONSE_RETRY_MESSAGE\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._settings.ELICIT_RESPONSE_RETRY_MESSAGE.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._settings.ELICIT_RESPONSE_RETRY_MESSAGE\"}}},{\"name\":\"entireRequest._settings.EMPTYMESSAGE\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._settings.EMPTYMESSAGE.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._settings.EMPTYMESSAGE\"}}},{\"name\":\"entireRequest._settings.ENABLE_DEBUG_RESPONSES\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireRequest._settings.ENABLE_MULTI_LANGUAGE_SUPPORT\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireRequest._settings.ENABLE_REDACTING\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireRequest._settings.ENABLE_SENTIMENT_SUPPORT\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireRequest._settings.ENFORCE_VERIFIED_IDENTITY\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireRequest._settings.ERRORMESSAGE\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._settings.ERRORMESSAGE.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._settings.ERRORMESSAGE\"}}},{\"name\":\"entireRequest._settings.ES_KEYWORD_SYNTAX_TYPES\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._settings.ES_KEYWORD_SYNTAX_TYPES.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._settings.ES_KEYWORD_SYNTAX_TYPES\"}}},{\"name\":\"entireRequest._settings.ES_MINIMUM_SHOULD_MATCH\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._settings.ES_MINIMUM_SHOULD_MATCH.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._settings.ES_MINIMUM_SHOULD_MATCH\"}}},{\"name\":\"entireRequest._settings.ES_NO_HITS_QUESTION\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._settings.ES_NO_HITS_QUESTION.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._settings.ES_NO_HITS_QUESTION\"}}},{\"name\":\"entireRequest._settings.ES_PHRASE_BOOST\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._settings.ES_PHRASE_BOOST.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._settings.ES_PHRASE_BOOST\"}}},{\"name\":\"entireRequest._settings.ES_SCORE_ANSWER_FIELD\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireRequest._settings.ES_SYNTAX_CONFIDENCE_LIMIT\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._settings.ES_SYNTAX_CONFIDENCE_LIMIT.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._settings.ES_SYNTAX_CONFIDENCE_LIMIT\"}}},{\"name\":\"entireRequest._settings.ES_USE_FUZZY_MATCH\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireRequest._settings.ES_USE_KEYWORD_FILTERS\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireRequest._settings.KENDRA_FAQ_CONFIG_MAX_RETRIES\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireRequest._settings.KENDRA_FAQ_CONFIG_RETRY_DELAY\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireRequest._settings.KENDRA_FAQ_ES_FALLBACK\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireRequest._settings.KENDRA_FAQ_INDEX\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._settings.KENDRA_FAQ_INDEX.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._settings.KENDRA_FAQ_INDEX\"}}},{\"name\":\"entireRequest._settings.MINIMUM_CONFIDENCE_SCORE\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireRequest._settings.NO_VERIFIED_IDENTITY_QUESTION\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._settings.NO_VERIFIED_IDENTITY_QUESTION.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._settings.NO_VERIFIED_IDENTITY_QUESTION\"}}},{\"name\":\"entireRequest._settings.REDACTING_REGEX\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._settings.REDACTING_REGEX.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._settings.REDACTING_REGEX\"}}},{\"name\":\"entireRequest._settings.SMS_HINT_REMINDER\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._settings.SMS_HINT_REMINDER.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._settings.SMS_HINT_REMINDER\"}}},{\"name\":\"entireRequest._settings.SMS_HINT_REMINDER_ENABLE\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireRequest._settings.SMS_HINT_REMINDER_INTERVAL_HRS\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._settings.SMS_HINT_REMINDER_INTERVAL_HRS.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._settings.SMS_HINT_REMINDER_INTERVAL_HRS\"}}},{\"name\":\"entireRequest._type\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._type.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._type\"}}},{\"name\":\"entireRequest._userId\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._userId.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._userId\"}}},{\"name\":\"entireRequest._userInfo.FirstSeen\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._userInfo.FirstSeen.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._userInfo.FirstSeen\"}}},{\"name\":\"entireRequest._userInfo.InteractionCount\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireRequest._userInfo.LastSeen\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._userInfo.LastSeen.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._userInfo.LastSeen\"}}},{\"name\":\"entireRequest._userInfo.TimeSinceLastInteraction\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireRequest._userInfo.UserId\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._userInfo.UserId.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._userInfo.UserId\"}}},{\"name\":\"entireRequest._userInfo.isVerifiedIdentity\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._userInfo.isVerifiedIdentity.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._userInfo.isVerifiedIdentity\"}}},{\"name\":\"entireRequest.kendraResultsCached\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest.kendraResultsCached.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest.kendraResultsCached\"}}},{\"name\":\"entireRequest.question\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest.question.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest.question\"}}},{\"name\":\"entireRequest.sentiment\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest.sentiment.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest.sentiment\"}}},{\"name\":\"entireRequest.session.qnabot_gotanswer\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireRequest.session.qnabot_qid\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest.session.qnabot_qid.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest.session.qnabot_qid\"}}},{\"name\":\"entireRequest.session.qnabotcontext.kendra.kendraIndexId\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest.session.qnabotcontext.kendra.kendraIndexId.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest.session.qnabotcontext.kendra.kendraIndexId\"}}},{\"name\":\"entireRequest.session.qnabotcontext.kendra.kendraQueryId\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest.session.qnabotcontext.kendra.kendraQueryId.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest.session.qnabotcontext.kendra.kendraQueryId\"}}},{\"name\":\"entireRequest.session.qnabotcontext.kendra.kendraResponsibleQid\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest.session.qnabotcontext.kendra.kendraResponsibleQid.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest.session.qnabotcontext.kendra.kendraResponsibleQid\"}}},{\"name\":\"entireRequest.session.qnabotcontext.kendra.kendraResultId\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest.session.qnabotcontext.kendra.kendraResultId.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest.session.qnabotcontext.kendra.kendraResultId\"}}},{\"name\":\"entireRequest.session.qnabotcontext.navigation.hasParent\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireRequest.session.qnabotcontext.navigation.next\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest.session.qnabotcontext.navigation.next.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest.session.qnabotcontext.navigation.next\"}}},{\"name\":\"entireRequest.session.qnabotcontext.previous.a\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest.session.qnabotcontext.previous.a.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest.session.qnabotcontext.previous.a\"}}},{\"name\":\"entireRequest.session.qnabotcontext.previous.q\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest.session.qnabotcontext.previous.q.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest.session.qnabotcontext.previous.q\"}}},{\"name\":\"entireRequest.session.qnabotcontext.previous.qid\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest.session.qnabotcontext.previous.qid.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest.session.qnabotcontext.previous.qid\"}}},{\"name\":\"entireResponse._userInfo.FirstSeen\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse._userInfo.FirstSeen.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse._userInfo.FirstSeen\"}}},{\"name\":\"entireResponse._userInfo.InteractionCount\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireResponse._userInfo.LastSeen\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse._userInfo.LastSeen.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse._userInfo.LastSeen\"}}},{\"name\":\"entireResponse._userInfo.TimeSinceLastInteraction\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireResponse._userInfo.UserId\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse._userInfo.UserId.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse._userInfo.UserId\"}}},{\"name\":\"entireResponse._userInfo.isVerifiedIdentity\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse._userInfo.isVerifiedIdentity.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse._userInfo.isVerifiedIdentity\"}}},{\"name\":\"entireResponse.answerSource\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.answerSource.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.answerSource\"}}},{\"name\":\"entireResponse.card.send\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireResponse.card.text\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.card.text.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.card.text\"}}},{\"name\":\"entireResponse.card.title\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.card.title.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.card.title\"}}},{\"name\":\"entireResponse.card.url\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.card.url.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.card.url\"}}},{\"name\":\"entireResponse.got_hits\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireResponse.kendraResultsCached.QueryId\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.kendraResultsCached.QueryId.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.kendraResultsCached.QueryId\"}}},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.AdditionalAttributes.Key\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.AdditionalAttributes.Key.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.kendraResultsCached.ResultItems.AdditionalAttributes.Key\"}}},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.AdditionalAttributes.Value.TextWithHighlightsValue.Highlights.BeginOffset\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.AdditionalAttributes.Value.TextWithHighlightsValue.Highlights.EndOffset\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.AdditionalAttributes.Value.TextWithHighlightsValue.Highlights.TopAnswer\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.AdditionalAttributes.Value.TextWithHighlightsValue.Text\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.AdditionalAttributes.Value.TextWithHighlightsValue.Text.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.kendraResultsCached.ResultItems.AdditionalAttributes.Value.TextWithHighlightsValue.Text\"}}},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.AdditionalAttributes.ValueType\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.AdditionalAttributes.ValueType.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.kendraResultsCached.ResultItems.AdditionalAttributes.ValueType\"}}},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.DocumentAttributes.Key\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.DocumentAttributes.Key.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.kendraResultsCached.ResultItems.DocumentAttributes.Key\"}}},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.DocumentAttributes.Value.StringValue\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.DocumentAttributes.Value.StringValue.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.kendraResultsCached.ResultItems.DocumentAttributes.Value.StringValue\"}}},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.DocumentExcerpt.Highlights.BeginOffset\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.DocumentExcerpt.Highlights.EndOffset\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.DocumentExcerpt.Highlights.TopAnswer\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.DocumentExcerpt.Text\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.DocumentExcerpt.Text.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.kendraResultsCached.ResultItems.DocumentExcerpt.Text\"}}},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.DocumentId\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.DocumentId.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.kendraResultsCached.ResultItems.DocumentId\"}}},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.DocumentTitle.Highlights.BeginOffset\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.DocumentTitle.Highlights.EndOffset\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.DocumentTitle.Highlights.TopAnswer\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.DocumentTitle.Text\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.DocumentTitle.Text.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.kendraResultsCached.ResultItems.DocumentTitle.Text\"}}},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.DocumentURI\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.DocumentURI.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.kendraResultsCached.ResultItems.DocumentURI\"}}},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.Id\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.Id.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.kendraResultsCached.ResultItems.Id\"}}},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.Type\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.Type.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.kendraResultsCached.ResultItems.Type\"}}},{\"name\":\"entireResponse.kendraResultsCached.TotalNumberOfResults\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireResponse.kendraResultsCached.originalKendraIndexId\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.kendraResultsCached.originalKendraIndexId.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.kendraResultsCached.originalKendraIndexId\"}}},{\"name\":\"entireResponse.message\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.message.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.message\"}}},{\"name\":\"entireResponse.plainMessage\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.plainMessage.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.plainMessage\"}}},{\"name\":\"entireResponse.result.a\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.result.a.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.result.a\"}}},{\"name\":\"entireResponse.result.answersource\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.result.answersource.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.result.answersource\"}}},{\"name\":\"entireResponse.result.autotranslate.a\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireResponse.result.l\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.result.l.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.result.l\"}}},{\"name\":\"entireResponse.result.q\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.result.q.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.result.q\"}}},{\"name\":\"entireResponse.result.qid\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.result.qid.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.result.qid\"}}},{\"name\":\"entireResponse.result.questions.q\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.result.questions.q.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.result.questions.q\"}}},{\"name\":\"entireResponse.result.quniqueterms\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.result.quniqueterms.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.result.quniqueterms\"}}},{\"name\":\"entireResponse.result.type\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.result.type.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.result.type\"}}},{\"name\":\"entireResponse.session.appContext\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.session.appContext.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.session.appContext\"}}},{\"name\":\"entireResponse.session.qnabot_gotanswer\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.session.qnabot_gotanswer.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.session.qnabot_gotanswer\"}}},{\"name\":\"entireResponse.session.qnabot_qid\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.session.qnabot_qid.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.session.qnabot_qid\"}}},{\"name\":\"entireResponse.session.qnabotcontext\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.session.qnabotcontext.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.session.qnabotcontext\"}}},{\"name\":\"entireResponse.type\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.type.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.type\"}}},{\"name\":\"qid\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"qid.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"qid\"}}},{\"name\":\"topic\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"topic.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"topic\"}}},{\"name\":\"utterance\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"utterance.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"utterance\"}}}]",
                  "title": "<INDEX_METRICS>"
                },
                "references": [],
                "migrationVersion": {"index-pattern": "7.6.0"}
              },
              {
                "id": "Feedback",
                "type": "index-pattern",
                "namespaces": ["default"],
                "updated_at": "2022-12-04T21:21:27.535Z",
                "version": "WzExLDFd",
                "attributes": {
                  "timeFieldName": "datetime",
                  "fields": "[{\"name\":\"_id\",\"type\":\"string\",\"esTypes\":[\"_id\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_index\",\"type\":\"string\",\"esTypes\":[\"_index\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_score\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_source\",\"type\":\"_source\",\"esTypes\":[\"_source\"],\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_type\",\"type\":\"string\",\"esTypes\":[\"_type\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"alternate\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"alternate.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"alternate\"}}},{\"name\":\"answer\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"answer.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"answer\"}}},{\"name\":\"datetime\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"feedback\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"feedback.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"feedback\"}}},{\"name\":\"qid\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"qid.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"qid\"}}},{\"name\":\"utterance\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"utterance.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"utterance\"}}}]",
                  "title": "<INDEX_FEEDBACK>"
                },
                "references": [],
                "migrationVersion": {"index-pattern": "7.6.0"}
              },
              {
                "id": "QnaItems",
                "type": "index-pattern",
                "namespaces": ["default"],
                "updated_at": "2022-12-04T21:21:27.535Z",
                "version": "WzEyLDFd",
                "attributes": {
                  "fields": "[{\"name\":\"_id\",\"type\":\"string\",\"esTypes\":[\"_id\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_index\",\"type\":\"string\",\"esTypes\":[\"_index\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_score\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_source\",\"type\":\"_source\",\"esTypes\":[\"_source\"],\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_type\",\"type\":\"string\",\"esTypes\":[\"_type\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"a\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"alt.markdown\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"alt.markdown.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"alt.markdown\"}}},{\"name\":\"alt.ssml\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"alt.ssml.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"alt.ssml\"}}},{\"name\":\"args\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"args.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"args\"}}},{\"name\":\"conditionalChaining\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"conditionalChaining.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"conditionalChaining\"}}},{\"name\":\"correctAnswers\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"elicitResponse.response_sessionattr_namespace\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"elicitResponse.response_sessionattr_namespace.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"elicitResponse.response_sessionattr_namespace\"}}},{\"name\":\"elicitResponse.responsebot_hook\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"elicitResponse.responsebot_hook.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"elicitResponse.responsebot_hook\"}}},{\"name\":\"incorrectAnswers\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"l\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"next\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"next.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"next\"}}},{\"name\":\"qid\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"question\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"questions.q\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"quiz\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"quiz.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"quiz\"}}},{\"name\":\"quniqueterms\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"r.buttons.text\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"r.buttons.text.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"r.buttons.text\"}}},{\"name\":\"r.buttons.value\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"r.buttons.value.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"r.buttons.value\"}}},{\"name\":\"r.imageUrl\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"r.subTitle\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"r.subTitle.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"r.subTitle\"}}},{\"name\":\"r.text\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"r.text.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"r.text\"}}},{\"name\":\"r.title\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"r.url\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"r.url.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"r.url\"}}},{\"name\":\"responses.correct\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"responses.correct.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"responses.correct\"}}},{\"name\":\"responses.end\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"responses.end.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"responses.end\"}}},{\"name\":\"responses.incorrect\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"responses.incorrect.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"responses.incorrect\"}}},{\"name\":\"selected\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"t\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"type\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"type.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"type\"}}}]",
                  "title": "<INDEX_QNA>"
                },
                "references": [],
                "migrationVersion": {"index-pattern": "7.6.0"}
              }
            ]
          },
          "replaceTokenInBody": [
            {"f": "<INDEX_QNA>", "r": {"Fn::Sub": "${Var.QnaIndex}"}},
            {"f": "<INDEX_METRICS>", "r": {"Fn::Sub": "${Var.MetricsIndex}"}},
            {"f": "<INDEX_FEEDBACK>", "r": {"Fn::Sub": "${Var.FeedbackIndex}"}}
          ]
        }
      }
    },
    "ExamplesStack": {
      "Type": "AWS::CloudFormation::Stack",
      "Condition": "BuildExamples",
      "Properties": {
        "TemplateURL": {
          "Fn::Sub": "https://solutions-${AWS::Region}.s3.${AWS::Region}.amazonaws.com/qnabot-on-aws/v5.4.0/templates/examples.json"
        },
        "Parameters": {
          "QnAType": {"Fn::GetAtt": ["Var", "QnAType"]},
          "QuizType": {"Fn::GetAtt": ["Var", "QuizType"]},
          "Index": {"Fn::GetAtt": ["Var", "QnaIndex"]},
          "ESAddress": {"Fn::GetAtt": ["ESVar", "ESAddress"]},
          "BootstrapBucket": {"Fn::Sub": "solutions-${AWS::Region}"},
          "BootstrapPrefix": "qnabot-on-aws/v5.4.0",
          "FeedbackFirehose": {"Fn::GetAtt": ["FeedbackFirehose", "Arn"]},
          "FeedbackFirehoseName": {"Ref": "FeedbackFirehose"},
          "CFNLambda": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
          "CFNLambdaRole": {"Fn::GetAtt": ["CFNLambdaRole", "Arn"]},
          "ApiUrlName": {"Fn::GetAtt": ["ApiUrl", "Name"]},
          "AssetBucket": {"Ref": "AssetBucket"},
          "FulfillmentLambdaRole": {"Ref": "FulfillmentLambdaRole"},
          "QIDLambdaArn": {"Fn::GetAtt": ["ESQidLambda", "Arn"]},
          "VPCSubnetIdList": {"Fn::Join": [",", [{"Ref": "AWS::NoValue"}]]},
          "VPCSecurityGroupIdList": {
            "Fn::Join": [",", [{"Ref": "AWS::NoValue"}]]
          },
          "LexBotVersion": {"Ref": "LexBotVersion"},
          "XraySetting": {"Ref": "XraySetting"},
          "DefaultQnABotSettings": {"Ref": "DefaultQnABotSettings"},
          "InstallLexResponseBots": {"Ref": "InstallLexResponseBots"},
          "AwsSdkLayerLambdaLayer": {"Ref": "AwsSdkLayerLambdaLayer"}
        }
      }
    },
    "ExportStack": {
      "Type": "AWS::CloudFormation::Stack",
      "Properties": {
        "TemplateURL": {
          "Fn::Sub": "https://solutions-${AWS::Region}.s3.${AWS::Region}.amazonaws.com/qnabot-on-aws/v5.4.0/templates/export.json"
        },
        "Parameters": {
          "CFNLambda": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
          "CFNInvokePolicy": {"Ref": "CFNInvokePolicy"},
          "BootstrapBucket": {"Fn::Sub": "solutions-${AWS::Region}"},
          "BootstrapPrefix": "qnabot-on-aws/v5.4.0",
          "VarIndex": {"Fn::GetAtt": ["Var", "QnaIndex"]},
          "EsEndpoint": {"Fn::GetAtt": ["ESVar", "ESAddress"]},
          "EsProxyLambda": {"Fn::GetAtt": ["ESProxyLambda", "Arn"]},
          "ExportBucket": {"Ref": "ExportBucket"},
          "VPCSubnetIdList": {"Fn::Join": [",", [{"Ref": "AWS::NoValue"}]]},
          "VPCSecurityGroupIdList": {
            "Fn::Join": [",", [{"Ref": "AWS::NoValue"}]]
          },
          "XraySetting": {"Ref": "XraySetting"},
          "Api": {"Ref": "API"},
          "ApiRootResourceId": {"Fn::GetAtt": ["API", "RootResourceId"]},
          "Encryption": {"Ref": "Encryption"},
          "Stage": {"Ref": "Stage"},
          "ApiDeploymentId": {"Ref": "Deployment"},
          "KendraCrawlerSnsTopic": {"Ref": "KendraCrawlerSnsTopic"},
          "DefaultQnABotSettings": {"Ref": "DefaultQnABotSettings"},
          "CustomQnABotSettings": {"Ref": "CustomQnABotSettings"},
          "AwsSdkLayerLambdaLayer": {"Ref": "AwsSdkLayerLambdaLayer"},
          "QnABotCommonLambdaLayer": {"Ref": "QnABotCommonLambdaLayer"},
          "LexVersion": {"Fn::If": ["CreateLexV1Bots", "V1", "V2"]},
          "FallbackIntent": {
            "Fn::If": [
              "CreateLexV1Bots",
              {"Ref": "IntentFallback"},
              "LexV2Only_Mode"
            ]
          },
          "Intent": {
            "Fn::If": ["CreateLexV1Bots", {"Ref": "Intent"}, "LexV2Only_Mode"]
          },
          "BotName": {
            "Fn::If": ["CreateLexV1Bots", {"Ref": "LexBot"}, "LexV2Only_Mode"]
          },
          "LexV2BotName": {"Fn::GetAtt": ["LexV2Bot", "botName"]},
          "LexV2BotId": {"Fn::GetAtt": ["LexV2Bot", "botId"]},
          "LexV2BotAlias": {"Fn::GetAtt": ["LexV2Bot", "botAlias"]},
          "LexV2BotAliasId": {"Fn::GetAtt": ["LexV2Bot", "botAliasId"]},
          "LexV2BotLocaleIds": {"Fn::GetAtt": ["LexV2Bot", "botLocaleIds"]}
        }
      }
    },
    "ImportStack": {
      "Type": "AWS::CloudFormation::Stack",
      "DependsOn": ["PreUpgradeExport"],
      "Properties": {
        "TemplateURL": {
          "Fn::Sub": "https://solutions-${AWS::Region}.s3.${AWS::Region}.amazonaws.com/qnabot-on-aws/v5.4.0/templates/import.json"
        },
        "Parameters": {
          "CFNLambda": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
          "CFNInvokePolicy": {"Ref": "CFNInvokePolicy"},
          "BootstrapBucket": {"Fn::Sub": "solutions-${AWS::Region}"},
          "BootstrapPrefix": "qnabot-on-aws/v5.4.0",
          "EsEndpoint": {"Fn::GetAtt": ["ESVar", "ESAddress"]},
          "EsArn": {"Fn::GetAtt": ["ESVar", "ESArn"]},
          "EsProxyLambda": {"Fn::GetAtt": ["ESProxyLambda", "Arn"]},
          "ImportBucket": {"Ref": "ImportBucket"},
          "ExportBucket": {"Ref": "ExportBucket"},
          "VarIndex": {"Fn::GetAtt": ["Var", "QnaIndex"]},
          "MetricsIndex": {"Fn::GetAtt": ["Var", "MetricsIndex"]},
          "FeedbackIndex": {"Fn::GetAtt": ["Var", "FeedbackIndex"]},
          "DefaultQnABotSettings": {"Ref": "DefaultQnABotSettings"},
          "CustomQnABotSettings": {"Ref": "CustomQnABotSettings"},
          "Encryption": {"Ref": "Encryption"},
          "VPCSubnetIdList": {"Fn::Join": [",", [{"Ref": "AWS::NoValue"}]]},
          "VPCSecurityGroupIdList": {
            "Fn::Join": [",", [{"Ref": "AWS::NoValue"}]]
          },
          "XraySetting": {"Ref": "XraySetting"},
          "AwsSdkLayerLambdaLayer": {"Ref": "AwsSdkLayerLambdaLayer"},
          "CommonModulesLambdaLayer": {"Ref": "CommonModulesLambdaLayer"},
          "EsProxyLambdaLayer": {"Ref": "EsProxyLambdaLayer"},
          "QnABotCommonLambdaLayer": {"Ref": "QnABotCommonLambdaLayer"},
          "EmbeddingsLambdaArn": {"Ref": "EmbeddingsLambdaArn"},
          "EmbeddingsApi": {"Ref": "EmbeddingsApi"},
          "EmbeddingsLambdaDimensions": {"Ref": "EmbeddingsLambdaDimensions"},
          "EmbeddingsSagemakerEndpoint": {
            "Fn::If": [
              "EmbeddingsSagemaker",
              {
                "Fn::GetAtt": [
                  "SagemakerEmbeddingsStack",
                  "Outputs.EmbeddingsSagemakerEndpoint"
                ]
              },
              ""
            ]
          },
          "EmbeddingsSagemakerEndpointArn": {
            "Fn::If": [
              "EmbeddingsSagemaker",
              {
                "Fn::GetAtt": [
                  "SagemakerEmbeddingsStack",
                  "Outputs.EmbeddingsSagemakerEndpointArn"
                ]
              },
              ""
            ]
          }
        }
      }
    },
    "KendraCrawlerSnsTopic": {
      "Type": "AWS::SNS::Topic",
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W47",
              "reason": "This SNS Topic does not need KmsMasterKeyId property."
            }
          ]
        }
      }
    },
    "CommonModulesLayerCodeVersion": {
      "Type": "Custom::S3Version",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
        "Key": {
          "Fn::Sub": "qnabot-on-aws/v5.4.0/lambda/common-modules-layer.zip"
        },
        "BuildDate": "2023-07-27T21:25:42.075Z"
      }
    },
    "CommonModulesLambdaLayer": {
      "Type": "AWS::Lambda::LayerVersion",
      "Properties": {
        "LayerName": {
          "Fn::Join": [
            "-",
            [
              "CommonModules",
              {
                "Fn::Select": [
                  2,
                  {"Fn::Split": ["-", {"Ref": "DefaultQnABotSettings"}]}
                ]
              }
            ]
          ]
        },
        "Content": {
          "S3Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
          "S3Key": {
            "Fn::Sub": "qnabot-on-aws/v5.4.0/lambda/common-modules-layer.zip"
          },
          "S3ObjectVersion": {"Ref": "CommonModulesLayerCodeVersion"}
        },
        "CompatibleRuntimes": ["nodejs18.x"]
      }
    },
    "QnABotCommonLayerCodeVersion": {
      "Type": "Custom::S3Version",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
        "Key": {
          "Fn::Sub": "qnabot-on-aws/v5.4.0/lambda/qnabot-common-layer.zip"
        },
        "BuildDate": "2023-07-27T21:25:42.075Z"
      }
    },
    "QnABotCommonLambdaLayer": {
      "Type": "AWS::Lambda::LayerVersion",
      "Properties": {
        "LayerName": {
          "Fn::Join": [
            "-",
            [
              "QnABotCommon",
              {
                "Fn::Select": [
                  2,
                  {"Fn::Split": ["-", {"Ref": "DefaultQnABotSettings"}]}
                ]
              }
            ]
          ]
        },
        "Content": {
          "S3Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
          "S3Key": {
            "Fn::Sub": "qnabot-on-aws/v5.4.0/lambda/qnabot-common-layer.zip"
          },
          "S3ObjectVersion": {"Ref": "QnABotCommonLayerCodeVersion"}
        },
        "CompatibleRuntimes": ["nodejs18.x"]
      }
    },
    "AwsSdkLayerCodeVersion": {
      "Type": "Custom::S3Version",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
        "Key": {"Fn::Sub": "qnabot-on-aws/v5.4.0/lambda/aws-sdk-layer.zip"},
        "BuildDate": "2023-07-27T21:25:42.075Z"
      }
    },
    "AwsSdkLayerLambdaLayer": {
      "Type": "AWS::Lambda::LayerVersion",
      "Properties": {
        "Content": {
          "S3Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
          "S3Key": {"Fn::Sub": "qnabot-on-aws/v5.4.0/lambda/aws-sdk-layer.zip"},
          "S3ObjectVersion": {"Ref": "AwsSdkLayerCodeVersion"}
        },
        "LayerName": {
          "Fn::Join": [
            "-",
            [
              "AwsSdk",
              {
                "Fn::Select": [
                  2,
                  {"Fn::Split": ["-", {"Ref": "DefaultQnABotSettings"}]}
                ]
              }
            ]
          ]
        },
        "CompatibleRuntimes": ["nodejs18.x"]
      }
    },
    "CfnLambdaLayerCodeVersion": {
      "Type": "Custom::S3Version",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
        "Key": {"Fn::Sub": "qnabot-on-aws/v5.4.0/lambda/cfn-lambda-layer.zip"},
        "BuildDate": "2023-07-27T21:25:42.075Z"
      }
    },
    "CfnLambdaLayer": {
      "Type": "AWS::Lambda::LayerVersion",
      "Properties": {
        "LayerName": {
          "Fn::Join": [
            "-",
            [
              "CfnLambdaModule",
              {
                "Fn::Select": [
                  2,
                  {"Fn::Split": ["-", {"Ref": "DefaultQnABotSettings"}]}
                ]
              }
            ]
          ]
        },
        "Content": {
          "S3Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
          "S3Key": {
            "Fn::Sub": "qnabot-on-aws/v5.4.0/lambda/cfn-lambda-layer.zip"
          },
          "S3ObjectVersion": {"Ref": "CfnLambdaLayerCodeVersion"}
        },
        "CompatibleRuntimes": ["nodejs18.x"]
      }
    },
    "EsProxyLayerCodeVersion": {
      "Type": "Custom::S3Version",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
        "Key": {"Fn::Sub": "qnabot-on-aws/v5.4.0/lambda/es-proxy-layer.zip"},
        "BuildDate": "2023-07-27T21:25:42.075Z"
      }
    },
    "EsProxyLambdaLayer": {
      "Type": "AWS::Lambda::LayerVersion",
      "Properties": {
        "LayerName": {
          "Fn::Join": [
            "-",
            [
              "EsProxy",
              {
                "Fn::Select": [
                  2,
                  {"Fn::Split": ["-", {"Ref": "DefaultQnABotSettings"}]}
                ]
              }
            ]
          ]
        },
        "Content": {
          "S3Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
          "S3Key": {
            "Fn::Sub": "qnabot-on-aws/v5.4.0/lambda/es-proxy-layer.zip"
          },
          "S3ObjectVersion": {"Ref": "EsProxyLayerCodeVersion"}
        },
        "CompatibleRuntimes": ["nodejs18.x"]
      }
    },
    "QNAInvokePermission": {
      "Type": "AWS::Lambda::Permission",
      "DependsOn": "FulfillmentLambdaAliaslive",
      "Properties": {
        "Action": "lambda:InvokeFunction",
        "FunctionName": {
          "Fn::Join": [
            ":",
            [{"Fn::GetAtt": ["FulfillmentLambda", "Arn"]}, "live"]
          ]
        },
        "Principal": "lex.amazonaws.com"
      }
    },
    "SlotType": {
      "Type": "Custom::LexSlotType",
      "Condition": "CreateLexV1Bots",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "createVersion": true,
        "description": "custom slot type 5.4.0 - v1",
        "enumerationValues": [{"value": "dummy utterance"}]
      }
    },
    "Intent": {
      "Type": "Custom::LexIntent",
      "Condition": "CreateLexV1Bots",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "prefix": "fulfilment",
        "description": "custom intent 5.4.0 - v1",
        "createVersion": true,
        "sampleUtterances": ["{slot}"],
        "slots": [
          {
            "name": "slot",
            "slotType": {"Ref": "SlotType"},
            "slotConstraint": "Optional",
            "slotTypeVersion": "QNABOT-AUTO-ASSIGNED",
            "priority": 1
          }
        ],
        "fulfillmentActivity": {
          "type": "CodeHook",
          "codeHook": {
            "uri": {
              "Fn::Join": [
                ":",
                [{"Fn::GetAtt": ["FulfillmentLambda", "Arn"]}, "live"]
              ]
            },
            "messageVersion": "1.0"
          }
        }
      },
      "DependsOn": "QNAInvokePermission"
    },
    "IntentFallback": {
      "Type": "Custom::LexIntent",
      "Condition": "CreateLexV1Bots",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "prefix": "qnabotfallbackfulfilment",
        "description": "custom fallback intent 5.4.0 - v1",
        "createVersion": true,
        "fulfillmentActivity": {
          "type": "CodeHook",
          "codeHook": {
            "uri": {
              "Fn::Join": [
                ":",
                [{"Fn::GetAtt": ["FulfillmentLambda", "Arn"]}, "live"]
              ]
            },
            "messageVersion": "1.0"
          }
        },
        "parentIntentSignature": "AMAZON.FallbackIntent"
      },
      "DependsOn": "QNAInvokePermission"
    },
    "LexBot": {
      "Type": "Custom::LexBot",
      "Condition": "CreateLexV1Bots",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "name": {"Fn::Sub": "${AWS::StackName}-Bot"},
        "description": "QnABot primary bot 5.4.0 - v1",
        "locale": "en-US",
        "voiceId": "Joanna",
        "childDirected": false,
        "createVersion": true,
        "intents": [
          {"intentName": {"Ref": "Intent"}},
          {"intentName": {"Ref": "IntentFallback"}}
        ],
        "abortStatement": {
          "messages": [
            {
              "content": "Sorry, I did not understand that",
              "contentType": "PlainText"
            }
          ]
        }
      }
    },
    "VersionAlias": {
      "Type": "Custom::LexAlias",
      "Condition": "CreateLexV1Bots",
      "DependsOn": "LexBot",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "botName": {"Ref": "LexBot"},
        "name": "live",
        "description": "QnABot live alias 5.4.0 - v1"
      }
    },
    "LexV2Bot": {
      "Type": "Custom::LexV2Bot",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["Lexv2BotLambda", "Arn"]},
        "description": "QnABot LexV2 Bot5.4.0 - v1",
        "BuildDate": "2023-07-27T21:25:42.076Z",
        "localIds": {"Ref": "LexV2BotLocaleIds"},
        "utterances": ["dummy utterance"]
      }
    },
    "Alexa": {
      "Type": "AWS::Lambda::Permission",
      "DependsOn": "FulfillmentLambdaAliaslive",
      "Properties": {
        "Action": "lambda:InvokeFunction",
        "FunctionName": {
          "Fn::Join": [
            ":",
            [{"Fn::GetAtt": ["FulfillmentLambda", "Arn"]}, "live"]
          ]
        },
        "Principal": "alexa-appkit.amazon.com"
      }
    },
    "FulfillmentCodeVersion": {
      "Type": "Custom::S3Version",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
        "Key": {"Fn::Sub": "qnabot-on-aws/v5.4.0/lambda/fulfillment.zip"},
        "BuildDate": "2023-07-27T21:25:42.093Z"
      }
    },
    "FulfillmentLambda": {
      "Type": "AWS::Lambda::Function",
      "DependsOn": "FulfillmentCodeVersion",
      "Properties": {
        "Code": {
          "S3Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
          "S3Key": {"Fn::Sub": "qnabot-on-aws/v5.4.0/lambda/fulfillment.zip"},
          "S3ObjectVersion": {"Ref": "FulfillmentCodeVersion"}
        },
        "Environment": {
          "Variables": {
            "ES_TYPE": {"Fn::GetAtt": ["Var", "QnAType"]},
            "ES_INDEX": {"Fn::GetAtt": ["Var", "QnaIndex"]},
            "ES_ADDRESS": {"Fn::GetAtt": ["ESVar", "ESAddress"]},
            "LAMBDA_DEFAULT_QUERY": {"Ref": "ESQueryLambda"},
            "LAMBDA_LOG": {"Ref": "ESLoggingLambda"},
            "ES_SERVICE_QID": {"Ref": "ESQidLambda"},
            "ES_SERVICE_PROXY": {"Ref": "ESProxyLambda"},
            "DYNAMODB_USERSTABLE": {"Ref": "UsersTable"},
            "DEFAULT_USER_POOL_JWKS_PARAM": {"Ref": "DefaultUserPoolJwksUrl"},
            "DEFAULT_SETTINGS_PARAM": {"Ref": "DefaultQnABotSettings"},
            "CUSTOM_SETTINGS_PARAM": {"Ref": "CustomQnABotSettings"},
            "EMBEDDINGS_API": {"Ref": "EmbeddingsApi"},
            "EMBEDDINGS_SAGEMAKER_ENDPOINT": {
              "Fn::If": [
                "EmbeddingsSagemaker",
                {
                  "Fn::GetAtt": [
                    "SagemakerEmbeddingsStack",
                    "Outputs.EmbeddingsSagemakerEndpoint"
                  ]
                },
                ""
              ]
            },
            "EMBEDDINGS_SAGEMAKER_INSTANCECOUNT": {
              "Ref": "SagemakerInitialInstanceCount"
            },
            "EMBEDDINGS_LAMBDA_ARN": {"Ref": "EmbeddingsLambdaArn"},
            "LLM_API": {"Ref": "LLMApi"},
            "LLM_SAGEMAKERENDPOINT": {
              "Fn::If": [
                "LLMSagemaker",
                {
                  "Fn::GetAtt": [
                    "SageMakerQASummarizeLLMStack",
                    "Outputs.LLMSagemakerEndpoint"
                  ]
                },
                ""
              ]
            },
            "LLM_SAGEMAKERINSTANCECOUNT": {
              "Ref": "LLMSagemakerInitialInstanceCount"
            },
            "LLM_LAMBDA_ARN": {"Ref": "LLMLambdaArn"},
            "ExampleJSLambdaQuiz": {
              "Fn::GetAtt": ["ExamplesStack", "Outputs.ExampleJSLambdaQuiz"]
            },
            "ExampleJSLambdahook": {
              "Fn::GetAtt": ["ExamplesStack", "Outputs.ExampleJSLambdahook"]
            },
            "ExamplePYTHONLambdaBotBroker": {
              "Fn::GetAtt": [
                "ExamplesStack",
                "Outputs.ExamplePYTHONLambdaBotBroker"
              ]
            },
            "ExamplePYTHONLambdaConnectCallback": {
              "Fn::GetAtt": [
                "ExamplesStack",
                "Outputs.ExamplePYTHONLambdaConnectCallback"
              ]
            },
            "ExamplePYTHONLambdaFeedback": {
              "Fn::GetAtt": [
                "ExamplesStack",
                "Outputs.ExamplePYTHONLambdaFeedback"
              ]
            },
            "ExamplePYTHONLambdaNext": {
              "Fn::GetAtt": ["ExamplesStack", "Outputs.ExamplePYTHONLambdaNext"]
            },
            "ExamplePYTHONLambdaPrevious": {
              "Fn::GetAtt": [
                "ExamplesStack",
                "Outputs.ExamplePYTHONLambdaPrevious"
              ]
            },
            "ExamplePYTHONLambdahello": {
              "Fn::GetAtt": [
                "ExamplesStack",
                "Outputs.ExamplePYTHONLambdahello"
              ]
            },
            "EXTCreateRecentTopicsResponse": {
              "Fn::GetAtt": [
                "ExamplesStack",
                "Outputs.EXTCreateRecentTopicsResponse"
              ]
            },
            "EXTCustomJSHook": {
              "Fn::GetAtt": ["ExamplesStack", "Outputs.EXTCustomJSHook"]
            },
            "EXTCanvasLMSHook": {
              "Fn::GetAtt": ["ExamplesStack", "Outputs.EXTCanvasLMSHook"]
            },
            "EXTCustomPYHook": {
              "Fn::GetAtt": ["ExamplesStack", "Outputs.EXTCustomPYHook"]
            },
            "QNAWage": {"Fn::GetAtt": ["ExamplesStack", "Outputs.QNAWage"]},
            "QNASocialSecurity": {
              "Fn::GetAtt": ["ExamplesStack", "Outputs.QNASocialSecurity"]
            },
            "QNAPinNoConfirm": {
              "Fn::GetAtt": ["ExamplesStack", "Outputs.QNAPinNoConfirm"]
            },
            "QNAPin": {"Fn::GetAtt": ["ExamplesStack", "Outputs.QNAPin"]},
            "QNAYesNo": {"Fn::GetAtt": ["ExamplesStack", "Outputs.QNAYesNo"]},
            "QNAYesNoExit": {
              "Fn::GetAtt": ["ExamplesStack", "Outputs.QNAYesNoExit"]
            },
            "QNADate": {"Fn::GetAtt": ["ExamplesStack", "Outputs.QNADate"]},
            "QNADateNoConfirm": {
              "Fn::GetAtt": ["ExamplesStack", "Outputs.QNADateNoConfirm"]
            },
            "QNADayOfWeek": {
              "Fn::GetAtt": ["ExamplesStack", "Outputs.QNADayOfWeek"]
            },
            "QNAMonth": {"Fn::GetAtt": ["ExamplesStack", "Outputs.QNAMonth"]},
            "QNAMonthNoConfirm": {
              "Fn::GetAtt": ["ExamplesStack", "Outputs.QNAMonthNoConfirm"]
            },
            "QNANumber": {"Fn::GetAtt": ["ExamplesStack", "Outputs.QNANumber"]},
            "QNANumberNoConfirm": {
              "Fn::GetAtt": ["ExamplesStack", "Outputs.QNANumberNoConfirm"]
            },
            "QNAAge": {"Fn::GetAtt": ["ExamplesStack", "Outputs.QNAAge"]},
            "QNAAgeNoConfirm": {
              "Fn::GetAtt": ["ExamplesStack", "Outputs.QNAAgeNoConfirm"]
            },
            "QNAPhoneNumber": {
              "Fn::GetAtt": ["ExamplesStack", "Outputs.QNAPhoneNumber"]
            },
            "QNAPhoneNumberNoConfirm": {
              "Fn::GetAtt": ["ExamplesStack", "Outputs.QNAPhoneNumberNoConfirm"]
            },
            "QNATime": {"Fn::GetAtt": ["ExamplesStack", "Outputs.QNATime"]},
            "QNAEmailAddress": {
              "Fn::GetAtt": ["ExamplesStack", "Outputs.QNAEmailAddress"]
            },
            "QNAName": {"Fn::GetAtt": ["ExamplesStack", "Outputs.QNAName"]}
          }
        },
        "Handler": "index.handler",
        "Layers": [
          {"Ref": "AwsSdkLayerLambdaLayer"},
          {"Ref": "CommonModulesLambdaLayer"},
          {"Ref": "EsProxyLambdaLayer"},
          {"Ref": "QnABotCommonLambdaLayer"}
        ],
        "MemorySize": 1408,
        "Role": {"Fn::GetAtt": ["FulfillmentLambdaRole", "Arn"]},
        "Runtime": "nodejs18.x",
        "Timeout": 300,
        "TracingConfig": {
          "Mode": {"Fn::If": ["XRAYEnabled", "Active", "PassThrough"]}
        },
        "Tags": [{"Key": "Type", "Value": "Fulfillment"}],
        "VpcConfig": {
          "Fn::If": [
            "VPCEnabled",
            {
              "SubnetIds": [{"Ref": "AWS::NoValue"}],
              "SecurityGroupIds": [{"Ref": "AWS::NoValue"}]
            },
            {"Ref": "AWS::NoValue"}
          ]
        }
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W89",
              "reason": "This Lambda Function is not required to be inside VPC"
            },
            {
              "id": "W92",
              "reason": "This lambda function does not require to have ReservedConcurrentExecutions"
            }
          ]
        }
      }
    },
    "FulfillmentLambdaVersionGenerator": {
      "Type": "Custom::LambdaVersion",
      "DeletionPolicy": "Retain",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "FunctionName": {"Ref": "FulfillmentLambda"},
        "Triggers": {
          "FulfillmentCodeVersionTrigger": [{"Ref": "FulfillmentCodeVersion"}],
          "LayersTrigger": [
            {"Ref": "AwsSdkLayerLambdaLayer"},
            {"Ref": "CommonModulesLambdaLayer"},
            {"Ref": "EsProxyLambdaLayer"},
            {"Ref": "QnABotCommonLambdaLayer"}
          ],
          "EmbeddingsTrigger": [
            {"Ref": "EmbeddingsApi"},
            {"Ref": "SagemakerInitialInstanceCount"},
            {
              "Fn::If": [
                "EmbeddingsSagemaker",
                {
                  "Fn::GetAtt": [
                    "SagemakerEmbeddingsStack",
                    "Outputs.EmbeddingsSagemakerEndpoint"
                  ]
                },
                ""
              ]
            },
            {"Ref": "EmbeddingsLambdaArn"}
          ],
          "QASummarizeTrigger": [
            {"Ref": "LLMApi"},
            {"Ref": "SagemakerInitialInstanceCount"},
            {
              "Fn::If": [
                "LLMSagemaker",
                {
                  "Fn::GetAtt": [
                    "SageMakerQASummarizeLLMStack",
                    "Outputs.LLMSagemakerEndpoint"
                  ]
                },
                ""
              ]
            },
            {"Ref": "LLMLambdaArn"}
          ]
        }
      }
    },
    "FulfillmentLambdaAliaslive": {
      "Type": "AWS::Lambda::Alias",
      "DependsOn": "FulfillmentLambdaVersionGenerator",
      "Properties": {
        "FunctionName": {"Ref": "FulfillmentLambda"},
        "FunctionVersion": {
          "Fn::GetAtt": ["FulfillmentLambdaVersionGenerator", "Version"]
        },
        "Name": "live",
        "ProvisionedConcurrencyConfig": {
          "Fn::If": [
            "CreateConcurrency",
            {
              "ProvisionedConcurrentExecutions": {
                "Ref": "FulfillmentConcurrency"
              }
            },
            {"Ref": "AWS::NoValue"}
          ]
        }
      }
    },
    "InvokePolicy": {
      "Type": "AWS::IAM::ManagedPolicy",
      "Properties": {
        "PolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Action": ["lambda:InvokeFunction"],
              "Resource": [
                "arn:aws:lambda:*:*:function:qna-*",
                "arn:aws:lambda:*:*:function:QNA-*",
                {"Fn::GetAtt": ["ESQueryLambda", "Arn"]},
                {"Fn::GetAtt": ["ESProxyLambda", "Arn"]},
                {"Fn::GetAtt": ["ESLoggingLambda", "Arn"]},
                {"Fn::GetAtt": ["ESQidLambda", "Arn"]},
                {
                  "Fn::If": [
                    "EmbeddingsLambdaArn",
                    {"Ref": "EmbeddingsLambdaArn"},
                    {"Ref": "AWS::NoValue"}
                  ]
                },
                {
                  "Fn::If": [
                    "LLMLambdaArn",
                    {"Ref": "LLMLambdaArn"},
                    {"Ref": "AWS::NoValue"}
                  ]
                },
                {
                  "Fn::GetAtt": ["ExamplesStack", "Outputs.ExampleJSLambdaQuiz"]
                },
                {
                  "Fn::GetAtt": ["ExamplesStack", "Outputs.ExampleJSLambdahook"]
                },
                {
                  "Fn::GetAtt": [
                    "ExamplesStack",
                    "Outputs.ExamplePYTHONLambdaBotBroker"
                  ]
                },
                {
                  "Fn::GetAtt": [
                    "ExamplesStack",
                    "Outputs.ExamplePYTHONLambdaConnectCallback"
                  ]
                },
                {
                  "Fn::GetAtt": [
                    "ExamplesStack",
                    "Outputs.ExamplePYTHONLambdaFeedback"
                  ]
                },
                {
                  "Fn::GetAtt": [
                    "ExamplesStack",
                    "Outputs.ExamplePYTHONLambdaNext"
                  ]
                },
                {
                  "Fn::GetAtt": [
                    "ExamplesStack",
                    "Outputs.ExamplePYTHONLambdaPrevious"
                  ]
                },
                {
                  "Fn::GetAtt": [
                    "ExamplesStack",
                    "Outputs.ExamplePYTHONLambdahello"
                  ]
                },
                {
                  "Fn::GetAtt": [
                    "ExamplesStack",
                    "Outputs.EXTCreateRecentTopicsResponse"
                  ]
                },
                {"Fn::GetAtt": ["ExamplesStack", "Outputs.EXTCustomJSHook"]},
                {"Fn::GetAtt": ["ExamplesStack", "Outputs.EXTCanvasLMSHook"]},
                {"Fn::GetAtt": ["ExamplesStack", "Outputs.EXTCustomPYHook"]}
              ]
            }
          ]
        },
        "Roles": [{"Ref": "FulfillmentLambdaRole"}]
      }
    },
    "LexBotPolicy": {
      "Type": "AWS::IAM::ManagedPolicy",
      "Properties": {
        "PolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Action": ["lex:PostText", "lex:RecognizeText"],
              "Resource": ["arn:aws:lex:*:*:bot:QNA*", "arn:aws:lex:*:*:bot*"]
            }
          ]
        },
        "Roles": [{"Ref": "FulfillmentLambdaRole"}]
      }
    },
    "FulfillmentLambdaRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {"Service": "lambda.amazonaws.com"},
              "Action": "sts:AssumeRole"
            }
          ]
        },
        "Path": "/",
        "ManagedPolicyArns": [{"Ref": "QueryPolicy"}],
        "Policies": [
          {
            "PolicyDocument": {
              "Statement": [
                {
                  "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                  ],
                  "Effect": "Allow",
                  "Resource": {
                    "Fn::Join": [
                      "",
                      [
                        "arn:",
                        {"Ref": "AWS::Partition"},
                        ":logs:",
                        {"Ref": "AWS::Region"},
                        ":",
                        {"Ref": "AWS::AccountId"},
                        ":log-group:/aws/lambda/*"
                      ]
                    ]
                  }
                }
              ],
              "Version": "2012-10-17"
            },
            "PolicyName": "LambdaFunctionServiceRolePolicy"
          },
          {
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                  ],
                  "Resource": {
                    "Fn::Join": [
                      "",
                      [
                        "arn:",
                        {"Ref": "AWS::Partition"},
                        ":logs:",
                        {"Ref": "AWS::Region"},
                        ":",
                        {"Ref": "AWS::AccountId"},
                        ":log-group:/aws/lambda/*"
                      ]
                    ]
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "ec2:CreateNetworkInterface",
                    "ec2:AssignPrivateIpAddresses",
                    "ec2:UnassignPrivateIpAddresses",
                    "ec2:DescribeNetworkInterfaces",
                    "ec2:DeleteNetworkInterface"
                  ],
                  "Resource": "*"
                }
              ]
            },
            "PolicyName": "lambdaVPCAccessExecutionRole"
          },
          {
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "xray:PutTraceSegments",
                    "xray:PutTelemetryRecords",
                    "xray:GetSamplingRules",
                    "xray:GetSamplingTargets",
                    "xray:GetSamplingStatisticSummaries"
                  ],
                  "Resource": ["*"]
                }
              ]
            },
            "PolicyName": "xrayDaemonWriteAccess"
          },
          {
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Action": [
                    "translate:TranslateText",
                    "translate:GetTerminology",
                    "translate:ListTerminologies",
                    "comprehend:DetectDominantLanguage",
                    "cloudwatch:GetMetricStatistics",
                    "cloudwatch:ListMetrics"
                  ],
                  "Effect": "Allow",
                  "Resource": "*"
                }
              ]
            },
            "PolicyName": "translateReadOnly"
          },
          {
            "PolicyName": "AWSQnaBotComprehendReadOnly",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "comprehend:DetectDominantLanguage",
                    "comprehend:DetectEntities",
                    "comprehend:DetectKeyPhrases",
                    "comprehend:DetectPiiEntities",
                    "comprehend:ContainsPiiEntities",
                    "comprehend:DetectSentiment",
                    "comprehend:DetectSyntax",
                    "comprehend:DescribeEntityRecognizer",
                    "comprehend:ListEntityRecognizers"
                  ],
                  "Resource": "*"
                }
              ]
            }
          },
          {
            "PolicyName": "ParamStorePolicy",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": ["ssm:GetParameter", "ssm:GetParameters"],
                  "Resource": [
                    {
                      "Fn::Join": [
                        "",
                        [
                          "arn:aws:ssm:",
                          {"Fn::Sub": "${AWS::Region}:"},
                          {"Fn::Sub": "${AWS::AccountId}:"},
                          "parameter/",
                          {"Ref": "DefaultQnABotSettings"}
                        ]
                      ]
                    },
                    {
                      "Fn::Join": [
                        "",
                        [
                          "arn:aws:ssm:",
                          {"Fn::Sub": "${AWS::Region}:"},
                          {"Fn::Sub": "${AWS::AccountId}:"},
                          "parameter/",
                          {"Ref": "CustomQnABotSettings"}
                        ]
                      ]
                    },
                    {
                      "Fn::Join": [
                        "",
                        [
                          "arn:aws:ssm:",
                          {"Fn::Sub": "${AWS::Region}:"},
                          {"Fn::Sub": "${AWS::AccountId}:"},
                          "parameter/",
                          {"Ref": "DefaultUserPoolJwksUrl"}
                        ]
                      ]
                    }
                  ]
                }
              ]
            }
          },
          {
            "PolicyName": "DynamoDBPolicy",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": ["dynamodb:GetItem", "dynamodb:PutItem"],
                  "Resource": [{"Fn::GetAtt": ["UsersTable", "Arn"]}]
                }
              ]
            }
          },
          {
            "Fn::If": [
              "EmbeddingsSagemaker",
              {
                "PolicyName": "EmbeddingsSagemakerInvokeEndpointAccess",
                "PolicyDocument": {
                  "Version": "2012-10-17",
                  "Statement": [
                    {
                      "Effect": "Allow",
                      "Action": ["sagemaker:InvokeEndpoint"],
                      "Resource": {
                        "Fn::GetAtt": [
                          "SagemakerEmbeddingsStack",
                          "Outputs.EmbeddingsSagemakerEndpointArn"
                        ]
                      }
                    }
                  ]
                }
              },
              {"Ref": "AWS::NoValue"}
            ]
          },
          {
            "Fn::If": [
              "LLMSagemaker",
              {
                "PolicyName": "LLMSagemakerInvokeEndpointAccess",
                "PolicyDocument": {
                  "Version": "2012-10-17",
                  "Statement": [
                    {
                      "Effect": "Allow",
                      "Action": ["sagemaker:InvokeEndpoint"],
                      "Resource": {
                        "Fn::GetAtt": [
                          "SageMakerQASummarizeLLMStack",
                          "Outputs.LLMSagemakerEndpointArn"
                        ]
                      }
                    }
                  ]
                }
              },
              {"Ref": "AWS::NoValue"}
            ]
          },
          {
            "PolicyName": "S3QNABucketReadAccess",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": ["s3:GetObject"],
                  "Resource": ["arn:aws:s3:::QNA*/*", "arn:aws:s3:::qna*/*"]
                }
              ]
            }
          }
        ]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W11",
              "reason": "This IAM role requires to have * resource on its permission policy"
            },
            {
              "id": "W12",
              "reason": "Lambda needs the following minimum required permissions to send trace data to X-Ray"
            }
          ]
        }
      }
    },
    "ESWarmerLambda": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Code": {
          "S3Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
          "S3Key": {"Fn::Sub": "qnabot-on-aws/v5.4.0/lambda/fulfillment.zip"},
          "S3ObjectVersion": {"Ref": "FulfillmentCodeVersion"}
        },
        "Environment": {
          "Variables": {
            "REPEAT_COUNT": "4",
            "TARGET_PATH": "_search",
            "TARGET_INDEX": {"Fn::GetAtt": ["Var", "QnaIndex"]},
            "TARGET_URL": {"Fn::GetAtt": ["ESVar", "ESAddress"]},
            "DEFAULT_SETTINGS_PARAM": {"Ref": "DefaultQnABotSettings"},
            "CUSTOM_SETTINGS_PARAM": {"Ref": "CustomQnABotSettings"}
          }
        },
        "Handler": "index.warmer",
        "MemorySize": "512",
        "Role": {"Fn::GetAtt": ["WarmerLambdaRole", "Arn"]},
        "Runtime": "nodejs18.x",
        "Timeout": 300,
        "Layers": [
          {"Ref": "AwsSdkLayerLambdaLayer"},
          {"Ref": "CommonModulesLambdaLayer"},
          {"Ref": "EsProxyLambdaLayer"},
          {"Ref": "QnABotCommonLambdaLayer"}
        ],
        "VpcConfig": {
          "Fn::If": [
            "VPCEnabled",
            {
              "SubnetIds": [{"Ref": "AWS::NoValue"}],
              "SecurityGroupIds": [{"Ref": "AWS::NoValue"}]
            },
            {"Ref": "AWS::NoValue"}
          ]
        },
        "TracingConfig": {
          "Fn::If": ["XRAYEnabled", {"Mode": "Active"}, {"Ref": "AWS::NoValue"}]
        },
        "Tags": [{"Key": "Type", "Value": "Warmer"}]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W92",
              "reason": "This lambda function does not require to have ReservedConcurrentExecutions"
            }
          ]
        }
      }
    },
    "WarmerLambdaRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {"Service": "lambda.amazonaws.com"},
              "Action": "sts:AssumeRole"
            }
          ]
        },
        "Path": "/",
        "Policies": [
          {
            "PolicyDocument": {
              "Statement": [
                {
                  "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                  ],
                  "Effect": "Allow",
                  "Resource": {
                    "Fn::Join": [
                      "",
                      [
                        "arn:",
                        {"Ref": "AWS::Partition"},
                        ":logs:",
                        {"Ref": "AWS::Region"},
                        ":",
                        {"Ref": "AWS::AccountId"},
                        ":log-group:/aws/lambda/*"
                      ]
                    ]
                  }
                }
              ],
              "Version": "2012-10-17"
            },
            "PolicyName": "LambdaFunctionServiceRolePolicy"
          },
          {
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                  ],
                  "Resource": {
                    "Fn::Join": [
                      "",
                      [
                        "arn:",
                        {"Ref": "AWS::Partition"},
                        ":logs:",
                        {"Ref": "AWS::Region"},
                        ":",
                        {"Ref": "AWS::AccountId"},
                        ":log-group:/aws/lambda/*"
                      ]
                    ]
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "ec2:CreateNetworkInterface",
                    "ec2:AssignPrivateIpAddresses",
                    "ec2:UnassignPrivateIpAddresses",
                    "ec2:DescribeNetworkInterfaces",
                    "ec2:DeleteNetworkInterface"
                  ],
                  "Resource": "*"
                }
              ]
            },
            "PolicyName": "lambdaVPCAccessExecutionRole"
          },
          {
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "xray:PutTraceSegments",
                    "xray:PutTelemetryRecords",
                    "xray:GetSamplingRules",
                    "xray:GetSamplingTargets",
                    "xray:GetSamplingStatisticSummaries"
                  ],
                  "Resource": ["*"]
                }
              ]
            },
            "PolicyName": "xrayDaemonWriteAccess"
          },
          {
            "PolicyName": "ParamStorePolicy",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": ["ssm:GetParameter", "ssm:GetParameters"],
                  "Resource": [
                    {
                      "Fn::Join": [
                        "",
                        [
                          "arn:aws:ssm:",
                          {"Fn::Sub": "${AWS::Region}:"},
                          {"Fn::Sub": "${AWS::AccountId}:"},
                          "parameter/",
                          {"Ref": "DefaultQnABotSettings"}
                        ]
                      ]
                    },
                    {
                      "Fn::Join": [
                        "",
                        [
                          "arn:aws:ssm:",
                          {"Fn::Sub": "${AWS::Region}:"},
                          {"Fn::Sub": "${AWS::AccountId}:"},
                          "parameter/",
                          {"Ref": "CustomQnABotSettings"}
                        ]
                      ]
                    }
                  ]
                },
                {
                  "Sid": "AllowES",
                  "Effect": "Allow",
                  "Action": ["es:ESHttpGet"],
                  "Resource": ["*"]
                }
              ]
            }
          }
        ]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W11",
              "reason": "This IAM role requires to have * resource on its permission policy"
            },
            {
              "id": "W12",
              "reason": "Lambda needs the following minimum required permissions to send trace data to X-Ray"
            }
          ]
        }
      }
    },
    "ESWarmerRule": {
      "Type": "AWS::Events::Rule",
      "Properties": {
        "ScheduleExpression": "rate(1 minute)",
        "Targets": [
          {
            "Id": "ESWarmerScheduler",
            "Arn": {"Fn::GetAtt": ["ESWarmerLambda", "Arn"]}
          }
        ]
      }
    },
    "ESWarmerRuleInvokeLambdaPermission": {
      "Type": "AWS::Lambda::Permission",
      "Properties": {
        "FunctionName": {"Fn::GetAtt": ["ESWarmerLambda", "Arn"]},
        "Action": "lambda:InvokeFunction",
        "Principal": "events.amazonaws.com",
        "SourceArn": {"Fn::GetAtt": ["ESWarmerRule", "Arn"]}
      }
    },
    "LexBuildLambda": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Code": {
          "S3Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
          "S3Key": {"Fn::Sub": "qnabot-on-aws/v5.4.0/lambda/lex-build.zip"},
          "S3ObjectVersion": {"Ref": "LexBuildCodeVersion"}
        },
        "Environment": {
          "Variables": {
            "UTTERANCE_BUCKET": {"Ref": "AssetBucket"},
            "UTTERANCE_KEY": "default-utterances.json",
            "POLL_LAMBDA": {"Fn::GetAtt": ["LexBuildLambdaPoll", "Arn"]},
            "STATUS_BUCKET": {"Ref": "BuildStatusBucket"},
            "STATUS_KEY": {
              "Fn::If": [
                "CreateLexV1Bots",
                "status.json",
                {"Ref": "AWS::NoValue"}
              ]
            },
            "LEXV2_STATUS_KEY": "lexV2status.json",
            "BOTNAME": {
              "Fn::If": [
                "CreateLexV1Bots",
                {"Ref": "LexBot"},
                {"Ref": "AWS::NoValue"}
              ]
            },
            "BOTALIAS": {
              "Fn::If": [
                "CreateLexV1Bots",
                {"Ref": "VersionAlias"},
                {"Ref": "AWS::NoValue"}
              ]
            },
            "SLOTTYPE": {
              "Fn::If": [
                "CreateLexV1Bots",
                {"Ref": "SlotType"},
                {"Ref": "AWS::NoValue"}
              ]
            },
            "INTENT": {
              "Fn::If": [
                "CreateLexV1Bots",
                {"Ref": "Intent"},
                {"Ref": "AWS::NoValue"}
              ]
            },
            "INTENTFALLBACK": {
              "Fn::If": [
                "CreateLexV1Bots",
                {"Ref": "IntentFallback"},
                {"Ref": "AWS::NoValue"}
              ]
            },
            "LEXV2_BUILD_LAMBDA": {"Ref": "Lexv2BotLambda"},
            "ADDRESS": {
              "Fn::Join": [
                "",
                ["https://", {"Fn::GetAtt": ["ESVar", "ESAddress"]}]
              ]
            },
            "INDEX": {"Fn::GetAtt": ["Var", "index"]}
          }
        },
        "Handler": "index.handler",
        "MemorySize": "1024",
        "Role": {"Fn::GetAtt": ["LexBuildLambdaRole", "Arn"]},
        "Runtime": "nodejs18.x",
        "Timeout": 900,
        "VpcConfig": {
          "Fn::If": [
            "VPCEnabled",
            {
              "SubnetIds": [{"Ref": "AWS::NoValue"}],
              "SecurityGroupIds": [{"Ref": "AWS::NoValue"}]
            },
            {"Ref": "AWS::NoValue"}
          ]
        },
        "TracingConfig": {
          "Fn::If": ["XRAYEnabled", {"Mode": "Active"}, {"Ref": "AWS::NoValue"}]
        },
        "Layers": [{"Ref": "AwsSdkLayerLambdaLayer"}],
        "Tags": [{"Key": "Type", "Value": "Api"}]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W92",
              "reason": "This lambda function does not require to have ReservedConcurrentExecutions"
            }
          ]
        }
      }
    },
    "LexBuildLambdaStart": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Code": {
          "ZipFile": "var aws=require('aws-sdk')\naws.config.region=process.env.AWS_REGION\nvar lambda=new aws.Lambda()\nvar s3=new aws.S3()\nvar crypto=require('crypto')\n\nexports.handler=async function(event,context,callback){\n    var token=crypto.randomBytes(16).toString('base64');\n    var bucket=process.env.STATUS_BUCKET;\n    var lexV1StatusFile=process.env.STATUS_KEY;\n    var lexV2StatusFile=process.env.LEXV2_STATUS_KEY;\n    var functionName=process.env.BUILD_FUNCTION;\n    var body=JSON.stringify({status:\"Starting\",token:token});\n\n    if (lexV1StatusFile) {\n        console.log(\"Initializing \", bucket, lexV1StatusFile);\n        await s3.putObject({\n            Bucket:bucket,\n            Key:lexV1StatusFile,\n            Body:body\n        }).promise();\n    }\n\n    console.log(\"Initializing \", bucket, lexV2StatusFile);\n    await s3.putObject({\n        Bucket:bucket,\n        Key:lexV2StatusFile,\n        Body:body\n    }).promise();\n\n    // The BUILD_FUNCTION takes care of rebuilding Lex V2 bot, and (unless QnABot is set to V2 only) Lex V1 bot\n    console.log(\"Invoking \", functionName);\n    await lambda.invoke({\n       FunctionName:functionName,\n       InvocationType:\"Event\",\n       Payload:\"{}\"\n    }).promise();\n    \n    callback(null,{token});\n};\n\n\n"
        },
        "Environment": {
          "Variables": {
            "STATUS_BUCKET": {"Ref": "BuildStatusBucket"},
            "STATUS_KEY": {
              "Fn::If": [
                "CreateLexV1Bots",
                "status.json",
                {"Ref": "AWS::NoValue"}
              ]
            },
            "LEXV2_STATUS_KEY": "lexV2status.json",
            "BUILD_FUNCTION": {"Fn::GetAtt": ["LexBuildLambda", "Arn"]}
          }
        },
        "Handler": "index.handler",
        "MemorySize": "1024",
        "Role": {"Fn::GetAtt": ["LexBuildLambdaRole", "Arn"]},
        "Runtime": "nodejs18.x",
        "Timeout": 900,
        "VpcConfig": {
          "Fn::If": [
            "VPCEnabled",
            {
              "SubnetIds": [{"Ref": "AWS::NoValue"}],
              "SecurityGroupIds": [{"Ref": "AWS::NoValue"}]
            },
            {"Ref": "AWS::NoValue"}
          ]
        },
        "TracingConfig": {
          "Fn::If": ["XRAYEnabled", {"Mode": "Active"}, {"Ref": "AWS::NoValue"}]
        },
        "Layers": [{"Ref": "AwsSdkLayerLambdaLayer"}],
        "Tags": [{"Key": "Type", "Value": "Api"}]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W92",
              "reason": "This lambda function does not require to have ReservedConcurrentExecutions"
            }
          ]
        }
      }
    },
    "LexBuildLambdaPoll": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Code": {
          "ZipFile": "var aws=require('aws-sdk')\naws.config.region=process.env.AWS_REGION\nvar lambda=new aws.Lambda()\nvar lex=new aws.LexModelBuildingService\nvar s3=new aws.S3()\nvar crypto=require('crypto')\n\nexports.handler=function(event,context,callback){\n    return s3.getObject({\n        Bucket:process.env.STATUS_BUCKET,\n        Key:process.env.STATUS_KEY\n    }).promise()\n    .then(x=>JSON.parse(x.Body.toString()))\n    .then(status=>{\n        return lex.getBot({\n            name:process.env.BOT_NAME,\n            versionOrAlias:\"$LATEST\"\n        }).promise()\n        .then(result=>{\n            status.status=result.status\n            if(result.status===\"BUILDING\"){\n                return new Promise(function(res,rej){\n                    setTimeout(()=>{\n                        lambda.invoke({\n                           FunctionName:process.env.AWS_LAMBDA_FUNCTION_NAME,\n                           InvocationType:\"Event\",\n                           Payload:JSON.stringify(event)\n                        }).promise()\n                        .then(res).catch(rej)\n                    },2*1000    \n                    )\n                })\n            }else{\n                return s3.putObject({\n                    Bucket:process.env.STATUS_BUCKET,\n                    Key:process.env.STATUS_KEY,\n                    Body:JSON.stringify(status)\n                }).promise()\n            }\n        })\n    })\n    .then(()=>callback(null))\n    .catch(callback)\n}\n"
        },
        "Environment": {
          "Variables": {
            "STATUS_KEY": {
              "Fn::If": [
                "CreateLexV1Bots",
                "status.json",
                {"Ref": "AWS::NoValue"}
              ]
            },
            "STATUS_BUCKET": {"Ref": "BuildStatusBucket"},
            "BOT_NAME": {
              "Fn::If": [
                "CreateLexV1Bots",
                {"Ref": "LexBot"},
                {"Ref": "AWS::NoValue"}
              ]
            }
          }
        },
        "Handler": "index.handler",
        "MemorySize": "1024",
        "Role": {"Fn::GetAtt": ["LexBuildLambdaRole", "Arn"]},
        "Runtime": "nodejs18.x",
        "Timeout": 900,
        "VpcConfig": {
          "Fn::If": [
            "VPCEnabled",
            {
              "SubnetIds": [{"Ref": "AWS::NoValue"}],
              "SecurityGroupIds": [{"Ref": "AWS::NoValue"}]
            },
            {"Ref": "AWS::NoValue"}
          ]
        },
        "TracingConfig": {
          "Fn::If": ["XRAYEnabled", {"Mode": "Active"}, {"Ref": "AWS::NoValue"}]
        },
        "Layers": [{"Ref": "AwsSdkLayerLambdaLayer"}],
        "Tags": [{"Key": "Type", "Value": "Api"}]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W92",
              "reason": "This lambda function does not require to have ReservedConcurrentExecutions"
            }
          ]
        }
      }
    },
    "LexBuildCodeVersion": {
      "Type": "Custom::S3Version",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
        "Key": {"Fn::Sub": "qnabot-on-aws/v5.4.0/lambda/lex-build.zip"},
        "BuildDate": "2023-07-27T21:25:42.094Z"
      }
    },
    "LexBuildInvokePolicy": {
      "Type": "AWS::IAM::ManagedPolicy",
      "Properties": {
        "PolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Action": ["lambda:InvokeFunction"],
              "Resource": [
                {"Fn::GetAtt": ["LexBuildLambda", "Arn"]},
                {"Fn::GetAtt": ["LexBuildLambdaPoll", "Arn"]},
                {"Fn::GetAtt": ["Lexv2BotLambda", "Arn"]}
              ]
            }
          ]
        },
        "Roles": [{"Ref": "LexBuildLambdaRole"}]
      }
    },
    "LexBuildLambdaRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {"Service": "lambda.amazonaws.com"},
              "Action": "sts:AssumeRole"
            }
          ]
        },
        "Policies": [
          {
            "PolicyDocument": {
              "Statement": [
                {
                  "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                  ],
                  "Effect": "Allow",
                  "Resource": {
                    "Fn::Join": [
                      "",
                      [
                        "arn:",
                        {"Ref": "AWS::Partition"},
                        ":logs:",
                        {"Ref": "AWS::Region"},
                        ":",
                        {"Ref": "AWS::AccountId"},
                        ":log-group:/aws/lambda/*"
                      ]
                    ]
                  }
                }
              ],
              "Version": "2012-10-17"
            },
            "PolicyName": "LambdaFunctionServiceRolePolicy"
          },
          {
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                  ],
                  "Resource": {
                    "Fn::Join": [
                      "",
                      [
                        "arn:",
                        {"Ref": "AWS::Partition"},
                        ":logs:",
                        {"Ref": "AWS::Region"},
                        ":",
                        {"Ref": "AWS::AccountId"},
                        ":log-group:/aws/lambda/*"
                      ]
                    ]
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "ec2:CreateNetworkInterface",
                    "ec2:AssignPrivateIpAddresses",
                    "ec2:UnassignPrivateIpAddresses",
                    "ec2:DescribeNetworkInterfaces",
                    "ec2:DeleteNetworkInterface"
                  ],
                  "Resource": "*"
                }
              ]
            },
            "PolicyName": "lambdaVPCAccessExecutionRole"
          },
          {
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "xray:PutTraceSegments",
                    "xray:PutTelemetryRecords",
                    "xray:GetSamplingRules",
                    "xray:GetSamplingTargets",
                    "xray:GetSamplingStatisticSummaries"
                  ],
                  "Resource": ["*"]
                }
              ]
            },
            "PolicyName": "xrayDaemonWriteAccess"
          },
          {
            "PolicyName": "AWSQnaBotLexFullAccess",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "polly:SynthesizeSpeech",
                    "logs:DescribeLogGroups",
                    "cloudwatch:DescribeAlarms",
                    "kms:DescribeKey",
                    "s3:GetBucketLocation",
                    "lambda:GetPolicy"
                  ],
                  "Resource": [
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:kms:${AWS::Region}:${AWS::AccountId}:key/*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:polly:${AWS::Region}:${AWS::AccountId}:lexicon/*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:cloudwatch:${AWS::Region}:${AWS::AccountId}:alarm:*"
                    },
                    {"Fn::Sub": "arn:${AWS::Partition}:s3:::*"}
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "s3:ListAllMyBuckets",
                    "lambda:ListFunctions",
                    "cloudwatch:DescribeAlarmsForMetric",
                    "kms:ListAliases",
                    "iam:ListRoles",
                    "cloudwatch:GetMetricStatistics",
                    "kendra:ListIndices",
                    "polly:DescribeVoices"
                  ],
                  "Resource": "*"
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "lex:GetBuiltinIntent",
                    "lex:GetIntents",
                    "lex:GetBots",
                    "lex:GetSlotTypes",
                    "lex:GetBotAliases",
                    "lex:StartImport",
                    "lex:GetMigration",
                    "lex:GetBuiltinSlotTypes",
                    "lex:GetBuiltinIntents",
                    "lex:GetImport",
                    "lex:GetMigrations"
                  ],
                  "Resource": "*"
                },
                {
                  "Effect": "Allow",
                  "Action": "lex:*",
                  "Resource": [
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:intent:*:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:slottype:*:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot:*:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot-channel:*:*"
                    }
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "lex:CreateUploadUrl",
                    "lex:ListBuiltInSlotTypes",
                    "lex:ListBots",
                    "lex:ListBuiltInIntents",
                    "lex:ListImports",
                    "lex:ListExports"
                  ],
                  "Resource": "*"
                },
                {
                  "Effect": "Allow",
                  "Action": "lex:*",
                  "Resource": [
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot-alias/*/*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot-alias/*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot/*"
                    }
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "lex:GetBuiltinIntent",
                    "lex:GetIntents",
                    "lex:GetBots",
                    "lex:GetSlotTypes",
                    "lex:GetBotAliases",
                    "lex:StartImport",
                    "lex:GetMigration",
                    "lex:GetBuiltinSlotTypes",
                    "lex:GetBuiltinIntents",
                    "lex:GetImport",
                    "lex:GetMigrations"
                  ],
                  "Resource": "*"
                },
                {
                  "Effect": "Allow",
                  "Action": "lex:*",
                  "Resource": [
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:intent:*:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:slottype:*:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot:*:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot-channel:*:*"
                    }
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "lex:CreateUploadUrl",
                    "lex:ListBuiltInSlotTypes",
                    "lex:ListBots",
                    "lex:ListBuiltInIntents",
                    "lex:ListImports",
                    "lex:ListExports"
                  ],
                  "Resource": "*"
                },
                {
                  "Effect": "Allow",
                  "Action": "lex:*",
                  "Resource": [
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot-alias/*/*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot/*"
                    }
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": ["lambda:AddPermission", "lambda:RemovePermission"],
                  "Resource": {
                    "Fn::Sub": "arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:AmazonLex*"
                  },
                  "Condition": {
                    "StringEquals": {"lambda:Principal": "lex.amazonaws.com"}
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:GetRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/lex.amazonaws.com/AWSServiceRoleForLexBots",
                    "arn:aws:iam::*:role/aws-service-role/channels.lex.amazonaws.com/AWSServiceRoleForLexChannels",
                    "arn:aws:iam::*:role/aws-service-role/lexv2.amazonaws.com/AWSServiceRoleForLexV2Bots*",
                    "arn:aws:iam::*:role/aws-service-role/channels.lexv2.amazonaws.com/AWSServiceRoleForLexV2Channels*"
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:CreateServiceLinkedRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/lex.amazonaws.com/AWSServiceRoleForLexBots"
                  ],
                  "Condition": {
                    "StringEquals": {"iam:AWSServiceName": "lex.amazonaws.com"}
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:CreateServiceLinkedRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/channels.lex.amazonaws.com/AWSServiceRoleForLexChannels"
                  ],
                  "Condition": {
                    "StringEquals": {
                      "iam:AWSServiceName": "channels.lex.amazonaws.com"
                    }
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:CreateServiceLinkedRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/lexv2.amazonaws.com/AWSServiceRoleForLexV2Bots*"
                  ],
                  "Condition": {
                    "StringEquals": {
                      "iam:AWSServiceName": "lexv2.amazonaws.com"
                    }
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:CreateServiceLinkedRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/channels.lexv2.amazonaws.com/AWSServiceRoleForLexV2Channels*"
                  ],
                  "Condition": {
                    "StringEquals": {
                      "iam:AWSServiceName": "channels.lexv2.amazonaws.com"
                    }
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "iam:DeleteServiceLinkedRole",
                    "iam:GetServiceLinkedRoleDeletionStatus"
                  ],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/lex.amazonaws.com/AWSServiceRoleForLexBots",
                    "arn:aws:iam::*:role/aws-service-role/channels.lex.amazonaws.com/AWSServiceRoleForLexChannels",
                    "arn:aws:iam::*:role/aws-service-role/lexv2.amazonaws.com/AWSServiceRoleForLexV2Bots*",
                    "arn:aws:iam::*:role/aws-service-role/channels.lexv2.amazonaws.com/AWSServiceRoleForLexV2Channels*"
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:PassRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/lex.amazonaws.com/AWSServiceRoleForLexBots"
                  ],
                  "Condition": {
                    "StringEquals": {
                      "iam:PassedToService": ["lex.amazonaws.com"]
                    }
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:PassRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/lexv2.amazonaws.com/AWSServiceRoleForLexV2Bots*"
                  ],
                  "Condition": {
                    "StringEquals": {
                      "iam:PassedToService": ["lexv2.amazonaws.com"]
                    }
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:PassRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/channels.lexv2.amazonaws.com/AWSServiceRoleForLexV2Channels*"
                  ],
                  "Condition": {
                    "StringEquals": {
                      "iam:PassedToService": ["channels.lexv2.amazonaws.com"]
                    }
                  }
                }
              ]
            }
          },
          {
            "PolicyName": "AssetBucketAccess",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": ["s3:Get*"],
                  "Resource": [
                    {"Fn::Sub": "arn:aws:s3:::${AssetBucket}*"},
                    {"Fn::Sub": "arn:aws:s3:::${BuildStatusBucket}*"}
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": ["s3:Put*"],
                  "Resource": [
                    {"Fn::Sub": "arn:aws:s3:::${BuildStatusBucket}*"}
                  ]
                }
              ]
            }
          }
        ],
        "Path": "/",
        "ManagedPolicyArns": [{"Ref": "QueryPolicy"}]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W11",
              "reason": "This IAM role requires to have * resource on its permission policy"
            },
            {
              "id": "W12",
              "reason": "Lambda needs the following minimum required permissions to send trace data to X-Ray"
            },
            {"id": "W76", "reason": "This role is required to have high SPCM"},
            {
              "id": "F3",
              "reason": "This role policy is required to have * action in its policy"
            }
          ]
        }
      }
    },
    "BuildStatusBucket": {
      "Type": "AWS::S3::Bucket",
      "Properties": {
        "LifecycleConfiguration": {
          "Rules": [
            {"NoncurrentVersionExpirationInDays": 1, "Status": "Enabled"},
            {
              "AbortIncompleteMultipartUpload": {"DaysAfterInitiation": 1},
              "Status": "Enabled"
            }
          ]
        },
        "VersioningConfiguration": {"Status": "Enabled"},
        "PublicAccessBlockConfiguration": {
          "BlockPublicAcls": true,
          "BlockPublicPolicy": true,
          "IgnorePublicAcls": true,
          "RestrictPublicBuckets": true
        },
        "BucketEncryption": {
          "Fn::If": [
            "Encrypted",
            {
              "ServerSideEncryptionConfiguration": [
                {"ServerSideEncryptionByDefault": {"SSEAlgorithm": "AES256"}}
              ]
            },
            {"Ref": "AWS::NoValue"}
          ]
        }
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W35",
              "reason": "Access logging is not required for this Bucket."
            }
          ]
        }
      }
    },
    "HTTPSOnlyBuildStatusBucketPolicy": {
      "Type": "AWS::S3::BucketPolicy",
      "Properties": {
        "Bucket": {"Ref": "BuildStatusBucket"},
        "PolicyDocument": {
          "Statement": [
            {
              "Action": "*",
              "Condition": {"Bool": {"aws:SecureTransport": "false"}},
              "Effect": "Deny",
              "Principal": "*",
              "Resource": {
                "Fn::Join": [
                  "",
                  [{"Fn::GetAtt": ["BuildStatusBucket", "Arn"]}, "/*"]
                ]
              },
              "Sid": "HttpsOnly"
            }
          ],
          "Version": "2012-10-17"
        }
      },
      "Metadata": {
        "aws:cdk:path": "serverless-bot-framework/CloudfrontStaticWebsite/CloudFrontToS3/S3LoggingBucket/Policy/Resource"
      }
    },
    "BuildStatusClear": {
      "Type": "Custom::S3Clear",
      "DependsOn": ["CFNInvokePolicy"],
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "Bucket": {"Ref": "BuildStatusBucket"}
      }
    },
    "Lexv2BotLambda": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Code": {
          "S3Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
          "S3Key": {"Fn::Sub": "qnabot-on-aws/v5.4.0/lambda/lexv2-build.zip"},
          "S3ObjectVersion": {"Ref": "Lexv2BotCodeVersion"}
        },
        "Environment": {
          "Variables": {
            "STACKNAME": {"Ref": "AWS::StackName"},
            "FULFILLMENT_LAMBDA_ARN": {
              "Fn::Join": [
                ":",
                [{"Fn::GetAtt": ["FulfillmentLambda", "Arn"]}, "live"]
              ]
            },
            "LOCALES": {"Ref": "LexV2BotLocaleIds"},
            "PYTHONPATH": "/var/task/py_modules:/var/runtime:/opt/python"
          }
        },
        "Handler": "handler.handler",
        "MemorySize": "1024",
        "Role": {"Fn::GetAtt": ["Lexv2BotLambdaRole", "Arn"]},
        "Runtime": "python3.10",
        "Timeout": 900,
        "VpcConfig": {
          "Fn::If": [
            "VPCEnabled",
            {
              "SubnetIds": [{"Ref": "AWS::NoValue"}],
              "SecurityGroupIds": [{"Ref": "AWS::NoValue"}]
            },
            {"Ref": "AWS::NoValue"}
          ]
        },
        "TracingConfig": {
          "Fn::If": ["XRAYEnabled", {"Mode": "Active"}, {"Ref": "AWS::NoValue"}]
        },
        "Tags": [{"Key": "Type", "Value": "Api"}]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W92",
              "reason": "This lambda function does not require to have ReservedConcurrentExecutions"
            }
          ]
        }
      }
    },
    "Lexv2BotCodeVersion": {
      "Type": "Custom::S3Version",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
        "Key": {"Fn::Sub": "qnabot-on-aws/v5.4.0/lambda/lexv2-build.zip"},
        "BuildDate": "2023-07-27T21:25:42.095Z"
      }
    },
    "Lexv2BotLambdaRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {"Service": "lambda.amazonaws.com"},
              "Action": "sts:AssumeRole"
            }
          ]
        },
        "Policies": [
          {
            "PolicyDocument": {
              "Statement": [
                {
                  "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                  ],
                  "Effect": "Allow",
                  "Resource": {
                    "Fn::Join": [
                      "",
                      [
                        "arn:",
                        {"Ref": "AWS::Partition"},
                        ":logs:",
                        {"Ref": "AWS::Region"},
                        ":",
                        {"Ref": "AWS::AccountId"},
                        ":log-group:/aws/lambda/*"
                      ]
                    ]
                  }
                }
              ],
              "Version": "2012-10-17"
            },
            "PolicyName": "LambdaFunctionServiceRolePolicy"
          },
          {
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                  ],
                  "Resource": {
                    "Fn::Join": [
                      "",
                      [
                        "arn:",
                        {"Ref": "AWS::Partition"},
                        ":logs:",
                        {"Ref": "AWS::Region"},
                        ":",
                        {"Ref": "AWS::AccountId"},
                        ":log-group:/aws/lambda/*"
                      ]
                    ]
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "ec2:CreateNetworkInterface",
                    "ec2:AssignPrivateIpAddresses",
                    "ec2:UnassignPrivateIpAddresses",
                    "ec2:DescribeNetworkInterfaces",
                    "ec2:DeleteNetworkInterface"
                  ],
                  "Resource": "*"
                }
              ]
            },
            "PolicyName": "lambdaVPCAccessExecutionRole"
          },
          {
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "xray:PutTraceSegments",
                    "xray:PutTelemetryRecords",
                    "xray:GetSamplingRules",
                    "xray:GetSamplingTargets",
                    "xray:GetSamplingStatisticSummaries"
                  ],
                  "Resource": ["*"]
                }
              ]
            },
            "PolicyName": "xrayDaemonWriteAccess"
          },
          {
            "PolicyName": "AWSQnaBotLexFullAccess",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "polly:SynthesizeSpeech",
                    "logs:DescribeLogGroups",
                    "cloudwatch:DescribeAlarms",
                    "kms:DescribeKey",
                    "s3:GetBucketLocation",
                    "lambda:GetPolicy"
                  ],
                  "Resource": [
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:kms:${AWS::Region}:${AWS::AccountId}:key/*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:polly:${AWS::Region}:${AWS::AccountId}:lexicon/*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:cloudwatch:${AWS::Region}:${AWS::AccountId}:alarm:*"
                    },
                    {"Fn::Sub": "arn:${AWS::Partition}:s3:::*"}
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "s3:ListAllMyBuckets",
                    "lambda:ListFunctions",
                    "cloudwatch:DescribeAlarmsForMetric",
                    "kms:ListAliases",
                    "iam:ListRoles",
                    "cloudwatch:GetMetricStatistics",
                    "kendra:ListIndices",
                    "polly:DescribeVoices"
                  ],
                  "Resource": "*"
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "lex:GetBuiltinIntent",
                    "lex:GetIntents",
                    "lex:GetBots",
                    "lex:GetSlotTypes",
                    "lex:GetBotAliases",
                    "lex:StartImport",
                    "lex:GetMigration",
                    "lex:GetBuiltinSlotTypes",
                    "lex:GetBuiltinIntents",
                    "lex:GetImport",
                    "lex:GetMigrations"
                  ],
                  "Resource": "*"
                },
                {
                  "Effect": "Allow",
                  "Action": "lex:*",
                  "Resource": [
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:intent:*:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:slottype:*:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot:*:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot-channel:*:*"
                    }
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "lex:CreateUploadUrl",
                    "lex:ListBuiltInSlotTypes",
                    "lex:ListBots",
                    "lex:ListBuiltInIntents",
                    "lex:ListImports",
                    "lex:ListExports"
                  ],
                  "Resource": "*"
                },
                {
                  "Effect": "Allow",
                  "Action": "lex:*",
                  "Resource": [
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot-alias/*/*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot-alias/*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot/*"
                    }
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "lex:GetBuiltinIntent",
                    "lex:GetIntents",
                    "lex:GetBots",
                    "lex:GetSlotTypes",
                    "lex:GetBotAliases",
                    "lex:StartImport",
                    "lex:GetMigration",
                    "lex:GetBuiltinSlotTypes",
                    "lex:GetBuiltinIntents",
                    "lex:GetImport",
                    "lex:GetMigrations"
                  ],
                  "Resource": "*"
                },
                {
                  "Effect": "Allow",
                  "Action": "lex:*",
                  "Resource": [
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:intent:*:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:slottype:*:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot:*:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot-channel:*:*"
                    }
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "lex:CreateUploadUrl",
                    "lex:ListBuiltInSlotTypes",
                    "lex:ListBots",
                    "lex:ListBuiltInIntents",
                    "lex:ListImports",
                    "lex:ListExports"
                  ],
                  "Resource": "*"
                },
                {
                  "Effect": "Allow",
                  "Action": "lex:*",
                  "Resource": [
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot-alias/*/*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot/*"
                    }
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": ["lambda:AddPermission", "lambda:RemovePermission"],
                  "Resource": {
                    "Fn::Sub": "arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:AmazonLex*"
                  },
                  "Condition": {
                    "StringEquals": {"lambda:Principal": "lex.amazonaws.com"}
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:GetRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/lex.amazonaws.com/AWSServiceRoleForLexBots",
                    "arn:aws:iam::*:role/aws-service-role/channels.lex.amazonaws.com/AWSServiceRoleForLexChannels",
                    "arn:aws:iam::*:role/aws-service-role/lexv2.amazonaws.com/AWSServiceRoleForLexV2Bots*",
                    "arn:aws:iam::*:role/aws-service-role/channels.lexv2.amazonaws.com/AWSServiceRoleForLexV2Channels*"
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:CreateServiceLinkedRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/lex.amazonaws.com/AWSServiceRoleForLexBots"
                  ],
                  "Condition": {
                    "StringEquals": {"iam:AWSServiceName": "lex.amazonaws.com"}
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:CreateServiceLinkedRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/channels.lex.amazonaws.com/AWSServiceRoleForLexChannels"
                  ],
                  "Condition": {
                    "StringEquals": {
                      "iam:AWSServiceName": "channels.lex.amazonaws.com"
                    }
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:CreateServiceLinkedRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/lexv2.amazonaws.com/AWSServiceRoleForLexV2Bots*"
                  ],
                  "Condition": {
                    "StringEquals": {
                      "iam:AWSServiceName": "lexv2.amazonaws.com"
                    }
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:CreateServiceLinkedRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/channels.lexv2.amazonaws.com/AWSServiceRoleForLexV2Channels*"
                  ],
                  "Condition": {
                    "StringEquals": {
                      "iam:AWSServiceName": "channels.lexv2.amazonaws.com"
                    }
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "iam:DeleteServiceLinkedRole",
                    "iam:GetServiceLinkedRoleDeletionStatus"
                  ],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/lex.amazonaws.com/AWSServiceRoleForLexBots",
                    "arn:aws:iam::*:role/aws-service-role/channels.lex.amazonaws.com/AWSServiceRoleForLexChannels",
                    "arn:aws:iam::*:role/aws-service-role/lexv2.amazonaws.com/AWSServiceRoleForLexV2Bots*",
                    "arn:aws:iam::*:role/aws-service-role/channels.lexv2.amazonaws.com/AWSServiceRoleForLexV2Channels*"
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:PassRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/lex.amazonaws.com/AWSServiceRoleForLexBots"
                  ],
                  "Condition": {
                    "StringEquals": {
                      "iam:PassedToService": ["lex.amazonaws.com"]
                    }
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:PassRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/lexv2.amazonaws.com/AWSServiceRoleForLexV2Bots*"
                  ],
                  "Condition": {
                    "StringEquals": {
                      "iam:PassedToService": ["lexv2.amazonaws.com"]
                    }
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:PassRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/channels.lexv2.amazonaws.com/AWSServiceRoleForLexV2Channels*"
                  ],
                  "Condition": {
                    "StringEquals": {
                      "iam:PassedToService": ["channels.lexv2.amazonaws.com"]
                    }
                  }
                }
              ]
            }
          },
          {
            "PolicyName": "LexV2ServiceLinkedRole",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": ["iam:GetRole", "iam:DeleteRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/lexv2.amazonaws.com/AWSServiceRoleForLexV2Bots*"
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:CreateServiceLinkedRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/lexv2.amazonaws.com/AWSServiceRoleForLexV2Bots*"
                  ],
                  "Condition": {
                    "StringLike": {"iam:AWSServiceName": "lexv2.amazonaws.com"}
                  }
                },
                {
                  "Action": ["iam:PassRole"],
                  "Effect": "Allow",
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/lexv2.amazonaws.com/AWSServiceRoleForLexV2Bots*"
                  ],
                  "Condition": {
                    "StringLike": {
                      "iam:PassedToService": ["lexv2.amazonaws.com"]
                    }
                  }
                },
                {
                  "Action": [
                    "translate:TranslateText",
                    "comprehend:DetectDominantLanguage"
                  ],
                  "Effect": "Allow",
                  "Resource": "*"
                }
              ]
            }
          },
          {
            "PolicyName": "BuildStatusBucketAccess",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": ["s3:Get*", "s3:Put*"],
                  "Resource": [
                    {"Fn::Sub": "arn:aws:s3:::${BuildStatusBucket}*"}
                  ]
                }
              ]
            }
          }
        ],
        "Path": "/",
        "ManagedPolicyArns": [{"Ref": "QueryPolicy"}]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W11",
              "reason": "This IAM role requires to have * resource on its permission policy"
            },
            {
              "id": "W12",
              "reason": "Lambda needs the following minimum required permissions to send trace data to X-Ray"
            },
            {"id": "W76", "reason": "This role is required to have high SPCM"},
            {
              "id": "F3",
              "reason": "This role policy is required to have * action in its policy"
            }
          ]
        }
      }
    },
    "LexAccessPolicy": {
      "Type": "AWS::IAM::ManagedPolicy",
      "Properties": {
        "PolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Action": [
                "lex:PostContent",
                "lex:PostText",
                "lex:RecognizeText",
                "lex:RecognizeUtterance"
              ],
              "Resource": ["*"]
            },
            {
              "Effect": "Allow",
              "Action": ["polly:SynthesizeSpeech"],
              "Resource": ["*"]
            }
          ]
        },
        "Roles": {
          "Fn::If": [
            "Public",
            [
              {"Ref": "AdminRole"},
              {"Ref": "UnauthenticatedRole"},
              {"Ref": "UserRole"}
            ],
            [{"Ref": "AdminRole"}, {"Ref": "UserRole"}]
          ]
        }
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W13",
              "reason": "This policy is required to have * resource"
            }
          ]
        }
      }
    },
    "ApiGatewayCloudWatchLogsRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {"Service": ["apigateway.amazonaws.com"]},
              "Action": ["sts:AssumeRole"]
            }
          ]
        },
        "Policies": [
          {
            "PolicyName": "ApiGatewayLogsPolicy",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:DescribeLogGroups",
                    "logs:DescribeLogStreams",
                    "logs:PutLogEvents",
                    "logs:GetLogEvents",
                    "logs:FilterLogEvents"
                  ],
                  "Resource": "*"
                }
              ]
            }
          }
        ]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W11",
              "reason": "This IAM role requires to have * resource on its permission policy"
            }
          ]
        }
      }
    },
    "ApiGatewayRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {"Service": ["apigateway.amazonaws.com"]},
              "Action": ["sts:AssumeRole"]
            }
          ]
        }
      }
    },
    "ESProxyCodeVersion": {
      "Type": "Custom::S3Version",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
        "Key": {"Fn::Sub": "qnabot-on-aws/v5.4.0/lambda/proxy-es.zip"},
        "BuildDate": "2023-07-27T21:25:42.096Z"
      }
    },
    "UtteranceLambda": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Code": {
          "S3Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
          "S3Key": {"Fn::Sub": "qnabot-on-aws/v5.4.0/lambda/proxy-es.zip"},
          "S3ObjectVersion": {"Ref": "ESProxyCodeVersion"}
        },
        "Layers": [
          {"Ref": "AwsSdkLayerLambdaLayer"},
          {"Ref": "CommonModulesLambdaLayer"},
          {"Ref": "EsProxyLambdaLayer"},
          {"Ref": "QnABotCommonLambdaLayer"}
        ],
        "Environment": {
          "Variables": {
            "ES_INDEX": {"Fn::GetAtt": ["Var", "QnaIndex"]},
            "ES_ADDRESS": {
              "Fn::Join": [
                "",
                ["https://", {"Fn::GetAtt": ["ESVar", "ESAddress"]}]
              ]
            },
            "UTTERANCE_BUCKET": {"Ref": "AssetBucket"},
            "UTTERANCE_KEY": "default-utterances.json"
          }
        },
        "Handler": "index.utterances",
        "MemorySize": "1408",
        "Role": {"Fn::GetAtt": ["ESProxyLambdaRole", "Arn"]},
        "Runtime": "nodejs18.x",
        "Timeout": 300,
        "VpcConfig": {
          "Fn::If": [
            "VPCEnabled",
            {
              "SubnetIds": [{"Ref": "AWS::NoValue"}],
              "SecurityGroupIds": [{"Ref": "AWS::NoValue"}]
            },
            {"Ref": "AWS::NoValue"}
          ]
        },
        "TracingConfig": {
          "Fn::If": ["XRAYEnabled", {"Mode": "Active"}, {"Ref": "AWS::NoValue"}]
        },
        "Tags": [{"Key": "Type", "Value": "Service"}]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W92",
              "reason": "This lambda function does not require to have ReservedConcurrentExecutions"
            }
          ]
        }
      }
    },
    "ESQidLambda": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Code": {
          "S3Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
          "S3Key": {"Fn::Sub": "qnabot-on-aws/v5.4.0/lambda/proxy-es.zip"},
          "S3ObjectVersion": {"Ref": "ESProxyCodeVersion"}
        },
        "Layers": [
          {"Ref": "AwsSdkLayerLambdaLayer"},
          {"Ref": "CommonModulesLambdaLayer"},
          {"Ref": "EsProxyLambdaLayer"},
          {"Ref": "QnABotCommonLambdaLayer"}
        ],
        "Environment": {
          "Variables": {
            "ES_INDEX": {"Fn::GetAtt": ["Var", "QnaIndex"]},
            "ES_ADDRESS": {"Fn::GetAtt": ["ESVar", "ESAddress"]}
          }
        },
        "Handler": "index.qid",
        "MemorySize": "1408",
        "Role": {"Fn::GetAtt": ["ESProxyLambdaRole", "Arn"]},
        "Runtime": "nodejs18.x",
        "Timeout": 300,
        "VpcConfig": {
          "Fn::If": [
            "VPCEnabled",
            {
              "SubnetIds": [{"Ref": "AWS::NoValue"}],
              "SecurityGroupIds": [{"Ref": "AWS::NoValue"}]
            },
            {"Ref": "AWS::NoValue"}
          ]
        },
        "TracingConfig": {
          "Fn::If": ["XRAYEnabled", {"Mode": "Active"}, {"Ref": "AWS::NoValue"}]
        },
        "Tags": [{"Key": "Type", "Value": "Service"}]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W92",
              "reason": "This lambda function does not require to have ReservedConcurrentExecutions"
            }
          ]
        }
      }
    },
    "ESCleaningLambda": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Code": {
          "S3Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
          "S3Key": {"Fn::Sub": "qnabot-on-aws/v5.4.0/lambda/proxy-es.zip"},
          "S3ObjectVersion": {"Ref": "ESProxyCodeVersion"}
        },
        "Layers": [
          {"Ref": "AwsSdkLayerLambdaLayer"},
          {"Ref": "CommonModulesLambdaLayer"},
          {"Ref": "EsProxyLambdaLayer"},
          {"Ref": "QnABotCommonLambdaLayer"}
        ],
        "Environment": {
          "Variables": {
            "ES_INDEX": {"Fn::GetAtt": ["Var", "QnaIndex"]},
            "ES_ADDRESS": {"Fn::GetAtt": ["ESVar", "ESAddress"]},
            "FEEDBACK_DELETE_RANGE_MINUTES": {
              "Ref": "KibanaDashboardRetentionMinutes"
            },
            "METRICS_DELETE_RANGE_MINUTES": {
              "Ref": "KibanaDashboardRetentionMinutes"
            }
          }
        },
        "Handler": "index.cleanmetrics",
        "MemorySize": "1408",
        "Role": {"Fn::GetAtt": ["ESProxyLambdaRole", "Arn"]},
        "Runtime": "nodejs18.x",
        "Timeout": 300,
        "VpcConfig": {
          "Fn::If": [
            "VPCEnabled",
            {
              "SubnetIds": [{"Ref": "AWS::NoValue"}],
              "SecurityGroupIds": [{"Ref": "AWS::NoValue"}]
            },
            {"Ref": "AWS::NoValue"}
          ]
        },
        "TracingConfig": {
          "Fn::If": ["XRAYEnabled", {"Mode": "Active"}, {"Ref": "AWS::NoValue"}]
        },
        "Tags": [{"Key": "Type", "Value": "Service"}]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W92",
              "reason": "This lambda function does not require to have ReservedConcurrentExecutions"
            }
          ]
        }
      }
    },
    "ScheduledESCleaning": {
      "Type": "AWS::Events::Rule",
      "Properties": {
        "Description": "",
        "ScheduleExpression": "rate(1 day)",
        "State": "ENABLED",
        "Targets": [
          {
            "Arn": {"Fn::GetAtt": ["ESCleaningLambda", "Arn"]},
            "Id": "ES_Cleaning_Function"
          }
        ]
      }
    },
    "PermissionForEventsToInvokeLambda": {
      "Type": "AWS::Lambda::Permission",
      "Properties": {
        "FunctionName": {"Ref": "ESCleaningLambda"},
        "Action": "lambda:InvokeFunction",
        "Principal": "events.amazonaws.com",
        "SourceArn": {"Fn::GetAtt": ["ScheduledESCleaning", "Arn"]}
      }
    },
    "ESLoggingLambda": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Code": {
          "S3Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
          "S3Key": {"Fn::Sub": "qnabot-on-aws/v5.4.0/lambda/proxy-es.zip"},
          "S3ObjectVersion": {"Ref": "ESProxyCodeVersion"}
        },
        "Layers": [
          {"Ref": "AwsSdkLayerLambdaLayer"},
          {"Ref": "CommonModulesLambdaLayer"},
          {"Ref": "EsProxyLambdaLayer"},
          {"Ref": "QnABotCommonLambdaLayer"}
        ],
        "Environment": {
          "Variables": {"FIREHOSE_NAME": {"Ref": "GeneralFirehose"}}
        },
        "Handler": "index.logging",
        "MemorySize": "1408",
        "Role": {"Fn::GetAtt": ["ESLoggingLambdaRole", "Arn"]},
        "Runtime": "nodejs18.x",
        "Timeout": 300,
        "VpcConfig": {
          "Fn::If": [
            "VPCEnabled",
            {
              "SubnetIds": [{"Ref": "AWS::NoValue"}],
              "SecurityGroupIds": [{"Ref": "AWS::NoValue"}]
            },
            {"Ref": "AWS::NoValue"}
          ]
        },
        "TracingConfig": {
          "Fn::If": ["XRAYEnabled", {"Mode": "Active"}, {"Ref": "AWS::NoValue"}]
        },
        "Tags": [{"Key": "Type", "Value": "Logging"}]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W92",
              "reason": "This lambda function does not require to have ReservedConcurrentExecutions"
            }
          ]
        }
      }
    },
    "ESQueryLambda": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Code": {
          "S3Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
          "S3Key": {"Fn::Sub": "qnabot-on-aws/v5.4.0/lambda/proxy-es.zip"},
          "S3ObjectVersion": {"Ref": "ESProxyCodeVersion"}
        },
        "Environment": {
          "Variables": {
            "DEFAULT_SETTINGS_PARAM": {"Ref": "DefaultQnABotSettings"},
            "CUSTOM_SETTINGS_PARAM": {"Ref": "CustomQnABotSettings"},
            "ExampleJSLambdaQuiz": {
              "Fn::GetAtt": ["ExamplesStack", "Outputs.ExampleJSLambdaQuiz"]
            },
            "ExampleJSLambdahook": {
              "Fn::GetAtt": ["ExamplesStack", "Outputs.ExampleJSLambdahook"]
            },
            "ExamplePYTHONLambdaBotBroker": {
              "Fn::GetAtt": [
                "ExamplesStack",
                "Outputs.ExamplePYTHONLambdaBotBroker"
              ]
            },
            "ExamplePYTHONLambdaConnectCallback": {
              "Fn::GetAtt": [
                "ExamplesStack",
                "Outputs.ExamplePYTHONLambdaConnectCallback"
              ]
            },
            "ExamplePYTHONLambdaFeedback": {
              "Fn::GetAtt": [
                "ExamplesStack",
                "Outputs.ExamplePYTHONLambdaFeedback"
              ]
            },
            "ExamplePYTHONLambdaNext": {
              "Fn::GetAtt": ["ExamplesStack", "Outputs.ExamplePYTHONLambdaNext"]
            },
            "ExamplePYTHONLambdaPrevious": {
              "Fn::GetAtt": [
                "ExamplesStack",
                "Outputs.ExamplePYTHONLambdaPrevious"
              ]
            },
            "ExamplePYTHONLambdahello": {
              "Fn::GetAtt": [
                "ExamplesStack",
                "Outputs.ExamplePYTHONLambdahello"
              ]
            },
            "EXTCreateRecentTopicsResponse": {
              "Fn::GetAtt": [
                "ExamplesStack",
                "Outputs.EXTCreateRecentTopicsResponse"
              ]
            },
            "EXTCustomJSHook": {
              "Fn::GetAtt": ["ExamplesStack", "Outputs.EXTCustomJSHook"]
            },
            "EXTCanvasLMSHook": {
              "Fn::GetAtt": ["ExamplesStack", "Outputs.EXTCanvasLMSHook"]
            },
            "EXTCustomPYHook": {
              "Fn::GetAtt": ["ExamplesStack", "Outputs.EXTCustomPYHook"]
            }
          }
        },
        "Layers": [
          {"Ref": "AwsSdkLayerLambdaLayer"},
          {"Ref": "CommonModulesLambdaLayer"},
          {"Ref": "EsProxyLambdaLayer"},
          {"Ref": "QnABotCommonLambdaLayer"}
        ],
        "Handler": "index.query",
        "MemorySize": "1408",
        "Role": {"Fn::GetAtt": ["ESProxyLambdaRole", "Arn"]},
        "Runtime": "nodejs18.x",
        "Timeout": 300,
        "VpcConfig": {
          "Fn::If": [
            "VPCEnabled",
            {
              "SubnetIds": [{"Ref": "AWS::NoValue"}],
              "SecurityGroupIds": [{"Ref": "AWS::NoValue"}]
            },
            {"Ref": "AWS::NoValue"}
          ]
        },
        "TracingConfig": {
          "Fn::If": ["XRAYEnabled", {"Mode": "Active"}, {"Ref": "AWS::NoValue"}]
        },
        "Tags": [{"Key": "Type", "Value": "Query"}]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W92",
              "reason": "This lambda function does not require to have ReservedConcurrentExecutions"
            }
          ]
        }
      }
    },
    "ESProxyLambda": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Code": {
          "S3Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
          "S3Key": {"Fn::Sub": "qnabot-on-aws/v5.4.0/lambda/proxy-es.zip"},
          "S3ObjectVersion": {"Ref": "ESProxyCodeVersion"}
        },
        "Layers": [
          {"Ref": "AwsSdkLayerLambdaLayer"},
          {"Ref": "CommonModulesLambdaLayer"},
          {"Ref": "EsProxyLambdaLayer"},
          {"Ref": "QnABotCommonLambdaLayer"}
        ],
        "Environment": {
          "Variables": {
            "ES_TYPE": {"Fn::GetAtt": ["Var", "QnAType"]},
            "ES_INDEX": {"Fn::GetAtt": ["Var", "QnaIndex"]},
            "ES_ADDRESS": {"Fn::GetAtt": ["ESVar", "ESAddress"]},
            "DEFAULT_SETTINGS_PARAM": {"Ref": "DefaultQnABotSettings"},
            "CUSTOM_SETTINGS_PARAM": {"Ref": "CustomQnABotSettings"},
            "EMBEDDINGS_API": {"Ref": "EmbeddingsApi"},
            "EMBEDDINGS_SAGEMAKER_ENDPOINT": {
              "Fn::If": [
                "EmbeddingsSagemaker",
                {
                  "Fn::GetAtt": [
                    "SagemakerEmbeddingsStack",
                    "Outputs.EmbeddingsSagemakerEndpoint"
                  ]
                },
                ""
              ]
            },
            "EMBEDDINGS_LAMBDA_ARN": {"Ref": "EmbeddingsLambdaArn"}
          }
        },
        "Handler": "index.handler",
        "MemorySize": "1408",
        "Role": {"Fn::GetAtt": ["ESProxyLambdaRole", "Arn"]},
        "Runtime": "nodejs18.x",
        "Timeout": 300,
        "VpcConfig": {
          "Fn::If": [
            "VPCEnabled",
            {
              "SubnetIds": [{"Ref": "AWS::NoValue"}],
              "SecurityGroupIds": [{"Ref": "AWS::NoValue"}]
            },
            {"Ref": "AWS::NoValue"}
          ]
        },
        "TracingConfig": {
          "Fn::If": ["XRAYEnabled", {"Mode": "Active"}, {"Ref": "AWS::NoValue"}]
        },
        "Tags": [{"Key": "Type", "Value": "Service"}]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W92",
              "reason": "This lambda function does not require to have ReservedConcurrentExecutions"
            }
          ]
        }
      }
    },
    "ESProxyLambdaRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {"Service": "lambda.amazonaws.com"},
              "Action": "sts:AssumeRole"
            }
          ]
        },
        "Path": "/",
        "ManagedPolicyArns": [{"Ref": "QueryPolicy"}],
        "Policies": [
          {
            "PolicyDocument": {
              "Statement": [
                {
                  "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                  ],
                  "Effect": "Allow",
                  "Resource": {
                    "Fn::Join": [
                      "",
                      [
                        "arn:",
                        {"Ref": "AWS::Partition"},
                        ":logs:",
                        {"Ref": "AWS::Region"},
                        ":",
                        {"Ref": "AWS::AccountId"},
                        ":log-group:/aws/lambda/*"
                      ]
                    ]
                  }
                }
              ],
              "Version": "2012-10-17"
            },
            "PolicyName": "LambdaFunctionServiceRolePolicy"
          },
          {
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                  ],
                  "Resource": {
                    "Fn::Join": [
                      "",
                      [
                        "arn:",
                        {"Ref": "AWS::Partition"},
                        ":logs:",
                        {"Ref": "AWS::Region"},
                        ":",
                        {"Ref": "AWS::AccountId"},
                        ":log-group:/aws/lambda/*"
                      ]
                    ]
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "ec2:CreateNetworkInterface",
                    "ec2:AssignPrivateIpAddresses",
                    "ec2:UnassignPrivateIpAddresses",
                    "ec2:DescribeNetworkInterfaces",
                    "ec2:DeleteNetworkInterface"
                  ],
                  "Resource": "*"
                }
              ]
            },
            "PolicyName": "lambdaVPCAccessExecutionRole"
          },
          {
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "xray:PutTraceSegments",
                    "xray:PutTelemetryRecords",
                    "xray:GetSamplingRules",
                    "xray:GetSamplingTargets",
                    "xray:GetSamplingStatisticSummaries"
                  ],
                  "Resource": ["*"]
                }
              ]
            },
            "PolicyName": "xrayDaemonWriteAccess"
          },
          {
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Action": [
                    "translate:TranslateText",
                    "translate:GetTerminology",
                    "translate:ListTerminologies",
                    "comprehend:DetectDominantLanguage",
                    "cloudwatch:GetMetricStatistics",
                    "cloudwatch:ListMetrics"
                  ],
                  "Effect": "Allow",
                  "Resource": "*"
                }
              ]
            },
            "PolicyName": "translateReadOnly"
          },
          {
            "PolicyName": "AWSQnaBotLexFullAccess",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "polly:SynthesizeSpeech",
                    "logs:DescribeLogGroups",
                    "cloudwatch:DescribeAlarms",
                    "kms:DescribeKey",
                    "s3:GetBucketLocation",
                    "lambda:GetPolicy"
                  ],
                  "Resource": [
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:kms:${AWS::Region}:${AWS::AccountId}:key/*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:polly:${AWS::Region}:${AWS::AccountId}:lexicon/*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:cloudwatch:${AWS::Region}:${AWS::AccountId}:alarm:*"
                    },
                    {"Fn::Sub": "arn:${AWS::Partition}:s3:::*"}
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "s3:ListAllMyBuckets",
                    "lambda:ListFunctions",
                    "cloudwatch:DescribeAlarmsForMetric",
                    "kms:ListAliases",
                    "iam:ListRoles",
                    "cloudwatch:GetMetricStatistics",
                    "kendra:ListIndices",
                    "polly:DescribeVoices"
                  ],
                  "Resource": "*"
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "lex:GetBuiltinIntent",
                    "lex:GetIntents",
                    "lex:GetBots",
                    "lex:GetSlotTypes",
                    "lex:GetBotAliases",
                    "lex:StartImport",
                    "lex:GetMigration",
                    "lex:GetBuiltinSlotTypes",
                    "lex:GetBuiltinIntents",
                    "lex:GetImport",
                    "lex:GetMigrations"
                  ],
                  "Resource": "*"
                },
                {
                  "Effect": "Allow",
                  "Action": "lex:*",
                  "Resource": [
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:intent:*:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:slottype:*:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot:*:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot-channel:*:*"
                    }
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "lex:CreateUploadUrl",
                    "lex:ListBuiltInSlotTypes",
                    "lex:ListBots",
                    "lex:ListBuiltInIntents",
                    "lex:ListImports",
                    "lex:ListExports"
                  ],
                  "Resource": "*"
                },
                {
                  "Effect": "Allow",
                  "Action": "lex:*",
                  "Resource": [
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot-alias/*/*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot-alias/*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot/*"
                    }
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "lex:GetBuiltinIntent",
                    "lex:GetIntents",
                    "lex:GetBots",
                    "lex:GetSlotTypes",
                    "lex:GetBotAliases",
                    "lex:StartImport",
                    "lex:GetMigration",
                    "lex:GetBuiltinSlotTypes",
                    "lex:GetBuiltinIntents",
                    "lex:GetImport",
                    "lex:GetMigrations"
                  ],
                  "Resource": "*"
                },
                {
                  "Effect": "Allow",
                  "Action": "lex:*",
                  "Resource": [
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:intent:*:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:slottype:*:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot:*:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot-channel:*:*"
                    }
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "lex:CreateUploadUrl",
                    "lex:ListBuiltInSlotTypes",
                    "lex:ListBots",
                    "lex:ListBuiltInIntents",
                    "lex:ListImports",
                    "lex:ListExports"
                  ],
                  "Resource": "*"
                },
                {
                  "Effect": "Allow",
                  "Action": "lex:*",
                  "Resource": [
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot-alias/*/*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot/*"
                    }
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": ["lambda:AddPermission", "lambda:RemovePermission"],
                  "Resource": {
                    "Fn::Sub": "arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:AmazonLex*"
                  },
                  "Condition": {
                    "StringEquals": {"lambda:Principal": "lex.amazonaws.com"}
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:GetRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/lex.amazonaws.com/AWSServiceRoleForLexBots",
                    "arn:aws:iam::*:role/aws-service-role/channels.lex.amazonaws.com/AWSServiceRoleForLexChannels",
                    "arn:aws:iam::*:role/aws-service-role/lexv2.amazonaws.com/AWSServiceRoleForLexV2Bots*",
                    "arn:aws:iam::*:role/aws-service-role/channels.lexv2.amazonaws.com/AWSServiceRoleForLexV2Channels*"
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:CreateServiceLinkedRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/lex.amazonaws.com/AWSServiceRoleForLexBots"
                  ],
                  "Condition": {
                    "StringEquals": {"iam:AWSServiceName": "lex.amazonaws.com"}
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:CreateServiceLinkedRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/channels.lex.amazonaws.com/AWSServiceRoleForLexChannels"
                  ],
                  "Condition": {
                    "StringEquals": {
                      "iam:AWSServiceName": "channels.lex.amazonaws.com"
                    }
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:CreateServiceLinkedRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/lexv2.amazonaws.com/AWSServiceRoleForLexV2Bots*"
                  ],
                  "Condition": {
                    "StringEquals": {
                      "iam:AWSServiceName": "lexv2.amazonaws.com"
                    }
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:CreateServiceLinkedRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/channels.lexv2.amazonaws.com/AWSServiceRoleForLexV2Channels*"
                  ],
                  "Condition": {
                    "StringEquals": {
                      "iam:AWSServiceName": "channels.lexv2.amazonaws.com"
                    }
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "iam:DeleteServiceLinkedRole",
                    "iam:GetServiceLinkedRoleDeletionStatus"
                  ],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/lex.amazonaws.com/AWSServiceRoleForLexBots",
                    "arn:aws:iam::*:role/aws-service-role/channels.lex.amazonaws.com/AWSServiceRoleForLexChannels",
                    "arn:aws:iam::*:role/aws-service-role/lexv2.amazonaws.com/AWSServiceRoleForLexV2Bots*",
                    "arn:aws:iam::*:role/aws-service-role/channels.lexv2.amazonaws.com/AWSServiceRoleForLexV2Channels*"
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:PassRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/lex.amazonaws.com/AWSServiceRoleForLexBots"
                  ],
                  "Condition": {
                    "StringEquals": {
                      "iam:PassedToService": ["lex.amazonaws.com"]
                    }
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:PassRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/lexv2.amazonaws.com/AWSServiceRoleForLexV2Bots*"
                  ],
                  "Condition": {
                    "StringEquals": {
                      "iam:PassedToService": ["lexv2.amazonaws.com"]
                    }
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:PassRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/channels.lexv2.amazonaws.com/AWSServiceRoleForLexV2Channels*"
                  ],
                  "Condition": {
                    "StringEquals": {
                      "iam:PassedToService": ["channels.lexv2.amazonaws.com"]
                    }
                  }
                }
              ]
            }
          },
          {
            "PolicyName": "ParamStorePolicy",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": ["ssm:GetParameter", "ssm:GetParameters"],
                  "Resource": "*"
                }
              ]
            }
          },
          {
            "Fn::If": [
              "EmbeddingsEnable",
              {
                "PolicyName": "EmbeddingsPolicy",
                "PolicyDocument": {
                  "Version": "2012-10-17",
                  "Statement": [
                    {
                      "Fn::If": [
                        "EmbeddingsSagemaker",
                        {
                          "Effect": "Allow",
                          "Action": ["sagemaker:InvokeEndpoint"],
                          "Resource": {
                            "Fn::GetAtt": [
                              "SagemakerEmbeddingsStack",
                              "Outputs.EmbeddingsSagemakerEndpointArn"
                            ]
                          }
                        },
                        {"Ref": "AWS::NoValue"}
                      ]
                    },
                    {
                      "Fn::If": [
                        "EmbeddingsLambdaArn",
                        {
                          "Effect": "Allow",
                          "Action": ["lambda:InvokeFunction"],
                          "Resource": [{"Ref": "EmbeddingsLambdaArn"}]
                        },
                        {"Ref": "AWS::NoValue"}
                      ]
                    }
                  ]
                }
              },
              {"Ref": "AWS::NoValue"}
            ]
          },
          {
            "PolicyName": "S3QNABucketReadAccess",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": ["s3:GetObject"],
                  "Resource": ["arn:aws:s3:::QNA*/*", "arn:aws:s3:::qna*/*"]
                }
              ]
            }
          }
        ]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W11",
              "reason": "This IAM role requires to have * resource on its permission policy"
            },
            {
              "id": "W12",
              "reason": "Lambda needs the following minimum required permissions to send trace data to X-Ray"
            },
            {"id": "W76", "reason": "This role is required to have high SPCM"},
            {
              "id": "F3",
              "reason": "This role policy is required to have * action in its policy"
            }
          ]
        }
      }
    },
    "QueryLambdaInvokePolicy": {
      "Type": "AWS::IAM::ManagedPolicy",
      "Properties": {
        "PolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Action": ["lambda:InvokeFunction"],
              "Resource": [
                "arn:aws:lambda:*:*:function:qna*",
                "arn:aws:lambda:*:*:function:QNA*",
                {
                  "Fn::GetAtt": ["ExamplesStack", "Outputs.ExampleJSLambdaQuiz"]
                },
                {
                  "Fn::GetAtt": ["ExamplesStack", "Outputs.ExampleJSLambdahook"]
                },
                {
                  "Fn::GetAtt": [
                    "ExamplesStack",
                    "Outputs.ExamplePYTHONLambdaBotBroker"
                  ]
                },
                {
                  "Fn::GetAtt": [
                    "ExamplesStack",
                    "Outputs.ExamplePYTHONLambdaConnectCallback"
                  ]
                },
                {
                  "Fn::GetAtt": [
                    "ExamplesStack",
                    "Outputs.ExamplePYTHONLambdaFeedback"
                  ]
                },
                {
                  "Fn::GetAtt": [
                    "ExamplesStack",
                    "Outputs.ExamplePYTHONLambdaNext"
                  ]
                },
                {
                  "Fn::GetAtt": [
                    "ExamplesStack",
                    "Outputs.ExamplePYTHONLambdaPrevious"
                  ]
                },
                {
                  "Fn::GetAtt": [
                    "ExamplesStack",
                    "Outputs.ExamplePYTHONLambdahello"
                  ]
                },
                {
                  "Fn::GetAtt": [
                    "ExamplesStack",
                    "Outputs.EXTCreateRecentTopicsResponse"
                  ]
                },
                {"Fn::GetAtt": ["ExamplesStack", "Outputs.EXTCustomJSHook"]},
                {"Fn::GetAtt": ["ExamplesStack", "Outputs.EXTCanvasLMSHook"]},
                {"Fn::GetAtt": ["ExamplesStack", "Outputs.EXTCustomPYHook"]}
              ]
            }
          ]
        },
        "Roles": [{"Ref": "ESProxyLambdaRole"}]
      }
    },
    "ESLoggingLambdaRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {"Service": "lambda.amazonaws.com"},
              "Action": "sts:AssumeRole"
            }
          ]
        },
        "Path": "/",
        "Policies": [
          {
            "PolicyDocument": {
              "Statement": [
                {
                  "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                  ],
                  "Effect": "Allow",
                  "Resource": {
                    "Fn::Join": [
                      "",
                      [
                        "arn:",
                        {"Ref": "AWS::Partition"},
                        ":logs:",
                        {"Ref": "AWS::Region"},
                        ":",
                        {"Ref": "AWS::AccountId"},
                        ":log-group:/aws/lambda/*"
                      ]
                    ]
                  }
                }
              ],
              "Version": "2012-10-17"
            },
            "PolicyName": "LambdaFunctionServiceRolePolicy"
          },
          {
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                  ],
                  "Resource": {
                    "Fn::Join": [
                      "",
                      [
                        "arn:",
                        {"Ref": "AWS::Partition"},
                        ":logs:",
                        {"Ref": "AWS::Region"},
                        ":",
                        {"Ref": "AWS::AccountId"},
                        ":log-group:/aws/lambda/*"
                      ]
                    ]
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "ec2:CreateNetworkInterface",
                    "ec2:AssignPrivateIpAddresses",
                    "ec2:UnassignPrivateIpAddresses",
                    "ec2:DescribeNetworkInterfaces",
                    "ec2:DeleteNetworkInterface"
                  ],
                  "Resource": "*"
                }
              ]
            },
            "PolicyName": "lambdaVPCAccessExecutionRole"
          },
          {
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "xray:PutTraceSegments",
                    "xray:PutTelemetryRecords",
                    "xray:GetSamplingRules",
                    "xray:GetSamplingTargets",
                    "xray:GetSamplingStatisticSummaries"
                  ],
                  "Resource": ["*"]
                }
              ]
            },
            "PolicyName": "xrayDaemonWriteAccess"
          },
          {
            "PolicyName": "LambdaGeneralFirehoseQNALambda",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": ["lambda:InvokeFunction"],
                  "Resource": [
                    {
                      "Fn::Join": [
                        "",
                        [
                          "arn:aws:lambda:",
                          {"Ref": "AWS::Region"},
                          ":",
                          {"Ref": "AWS::AccountId"},
                          ":function:qna-*"
                        ]
                      ]
                    },
                    {
                      "Fn::Join": [
                        "",
                        [
                          "arn:aws:lambda:",
                          {"Ref": "AWS::Region"},
                          ":",
                          {"Ref": "AWS::AccountId"},
                          ":function:QNA-*"
                        ]
                      ]
                    }
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": ["comprehend:DetectPiiEntities"],
                  "Resource": ["*"]
                },
                {
                  "Effect": "Allow",
                  "Action": ["firehose:PutRecord", "firehose:PutRecordBatch"],
                  "Resource": [{"Fn::GetAtt": ["GeneralFirehose", "Arn"]}]
                }
              ]
            }
          }
        ]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W11",
              "reason": "This IAM role requires to have * resource on its permission policy"
            },
            {
              "id": "W12",
              "reason": "Lambda needs the following minimum required permissions to send trace data to X-Ray"
            }
          ]
        }
      }
    },
    "QueryPolicy": {
      "Type": "AWS::IAM::ManagedPolicy",
      "Properties": {
        "PolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {"Effect": "Allow", "Action": ["es:*"], "Resource": ["*"]},
            {
              "Effect": "Allow",
              "Action": ["kendra:Query", "kendra:Retrieve"],
              "Resource": [
                {
                  "Fn::Sub": "arn:aws:kendra:${AWS::Region}:${AWS::AccountId}:index/*"
                }
              ]
            },
            {
              "Effect": "Allow",
              "Action": ["s3:Get*"],
              "Resource": [{"Fn::Sub": "arn:aws:s3:::${AssetBucket}*"}]
            },
            {
              "Effect": "Allow",
              "Action": ["comprehend:DetectSyntax"],
              "Resource": ["*"]
            }
          ]
        }
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "F5",
              "reason": "This role policy is required to have * action in its policy"
            },
            {
              "id": "W13",
              "reason": "This IAM policy requires to have * resource"
            }
          ]
        }
      }
    },
    "LexProxyLambda": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Code": {
          "ZipFile": "var aws=require('aws-sdk')\naws.config.region=process.env.AWS_REGION\nvar lex=new aws.LexModelBuildingService()\n\nexports.handler = (event, context, callback) => {\n    console.log('Received event:', JSON.stringify(event, null, 2));\n    \n    lex[event.fnc](event.params).promise()\n    .then(function(x){\n        console.log(\"Response: \"+JSON.stringify(x,null,2))\n        callback(null,x)\n    })\n    .catch(function(y){\n        console.log(\"Error: \"+y)\n        callback(JSON.stringify({\n            type:\"[InternalServiceError]\",\n            data:y\n        }))\n    })\n};\n\n"
        },
        "Handler": "index.handler",
        "MemorySize": "128",
        "Role": {"Fn::GetAtt": ["LexProxyLambdaRole", "Arn"]},
        "Runtime": "nodejs18.x",
        "Timeout": 300,
        "VpcConfig": {
          "Fn::If": [
            "VPCEnabled",
            {
              "SubnetIds": [{"Ref": "AWS::NoValue"}],
              "SecurityGroupIds": [{"Ref": "AWS::NoValue"}]
            },
            {"Ref": "AWS::NoValue"}
          ]
        },
        "TracingConfig": {
          "Fn::If": ["XRAYEnabled", {"Mode": "Active"}, {"Ref": "AWS::NoValue"}]
        },
        "Layers": [{"Ref": "AwsSdkLayerLambdaLayer"}],
        "Tags": [{"Key": "Type", "Value": "Api"}]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W92",
              "reason": "This lambda function does not require to have ReservedConcurrentExecutions"
            }
          ]
        }
      }
    },
    "LexStatusLambda": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Code": {
          "ZipFile": "var aws=require('aws-sdk')\naws.config.region=process.env.AWS_REGION\nvar s3=new aws.S3()\nconst lexv2 = new aws.LexModelsV2();\n\nexports.handler = async (event, context, callback) => {\n    console.log('Received event:', JSON.stringify(event, null, 2));\n    \n    let bucket=process.env.STATUS_BUCKET;\n    let lexV1StatusFile=process.env.STATUS_KEY;\n    let lexV2StatusFile=process.env.LEXV2_STATUS_KEY;\n    let build = {\"status\":\"READY\",\"token\":\"token\"};\n    let response;\n\n    try {\n        response = await s3.getObject({Bucket:bucket, Key:lexV2StatusFile}).promise();\n        build = JSON.parse(response.Body.toString());\n        // combine build status with v1 bot, if defined.. If both are READY then status is READY\n        if (lexV1StatusFile) {\n            response = await s3.getObject({Bucket:bucket, Key:lexV1StatusFile}).promise();\n            let v1build = JSON.parse(response.Body.toString());\n            if (v1build.status != \"READY\" || build.status != \"READY\" ) {\n                build.status = \"LEX V2: \" + build.status + \" / LEX V1: \" + v1build.status\n            }\n        }\n    } catch(e) {\n        console.log(\"Unable to read S3 lex bot status file - perhaps it doesn't yet exist. Returning READY\");\n    }\n\n    response = await lexv2.describeBot({\n            botId:process.env.LEXV2_BOT_ID,\n        }).promise() ;\n    // Match LexV1 bot status for code compatibility (Available = READY)\n    let botStatus = (response.botStatus == \"Available\") ? \"READY\" :  response.botStatus ;\n    \n    return {\n        \"lambdaArn\": process.env.FULFILLMENT_FUNCTION_ARN,\n        \"lambdaRole\":process.env.FULFILLMENT_FUNCTION_ROLE,\n        \"botversion\":\"live\",\n        \"botname\":process.env.LEXV1_BOT_NAME || \"LEX V1 Bot not installed\",\n        \"intent\":process.env.LEXV1_INTENT || \"LEX V1 Bot not installed\",\n        \"intentFallback\":process.env.LEXV1_INTENT_FALLBACK || \"LEX V1 Bot not installed\",\n        \"lexV2botname\":process.env.LEXV2_BOT_NAME || \"LEX V2 Bot not installed\",\n        \"lexV2botid\":process.env.LEXV2_BOT_ID || \"LEX V2 Bot not installed\",\n        \"lexV2botalias\":process.env.LEXV2_BOT_ALIAS || \"LEX V2 Bot not installed\",\n        \"lexV2botaliasid\":process.env.LEXV2_BOT_ALIAS_ID || \"LEX V2 Bot not installed\",\n        \"lexV2intent\":process.env.LEXV2_INTENT || \"LEX V2 Bot not installed\",\n        \"lexV2intentFallback\":process.env.LEXV2_INTENT_FALLBACK || \"LEX V2 Bot not installed\",\n        \"lexV2localeids\":process.env.LEXV2_BOT_LOCALE_IDS || \"LEX V2 Bot not installed\",\n        \"status\":botStatus,\n        \"build\":build,\n    } ;\n};\n\n\n"
        },
        "Environment": {
          "Variables": {
            "STATUS_BUCKET": {"Ref": "BuildStatusBucket"},
            "STATUS_KEY": {
              "Fn::If": [
                "CreateLexV1Bots",
                "status.json",
                {"Ref": "AWS::NoValue"}
              ]
            },
            "LEXV2_STATUS_KEY": "lexV2status.json",
            "FULFILLMENT_FUNCTION_ARN": {
              "Fn::Join": [
                ":",
                [{"Fn::GetAtt": ["FulfillmentLambda", "Arn"]}, "live"]
              ]
            },
            "FULFILLMENT_FUNCTION_ROLE": {"Ref": "FulfillmentLambdaRole"},
            "LEXV1_BOT_NAME": {
              "Fn::If": [
                "CreateLexV1Bots",
                {"Ref": "LexBot"},
                {"Ref": "AWS::NoValue"}
              ]
            },
            "LEXV1_INTENT": {
              "Fn::If": [
                "CreateLexV1Bots",
                {"Ref": "Intent"},
                {"Ref": "AWS::NoValue"}
              ]
            },
            "LEXV1_INTENT_FALLBACK": {
              "Fn::If": [
                "CreateLexV1Bots",
                {"Ref": "IntentFallback"},
                {"Ref": "AWS::NoValue"}
              ]
            },
            "LEXV2_BOT_NAME": {"Fn::GetAtt": ["LexV2Bot", "botName"]},
            "LEXV2_BOT_ID": {"Fn::GetAtt": ["LexV2Bot", "botId"]},
            "LEXV2_BOT_ALIAS": {"Fn::GetAtt": ["LexV2Bot", "botAlias"]},
            "LEXV2_BOT_ALIAS_ID": {"Fn::GetAtt": ["LexV2Bot", "botAliasId"]},
            "LEXV2_INTENT": {"Fn::GetAtt": ["LexV2Bot", "botIntent"]},
            "LEXV2_INTENT_FALLBACK": {
              "Fn::GetAtt": ["LexV2Bot", "botIntentFallback"]
            },
            "LEXV2_BOT_LOCALE_IDS": {"Fn::GetAtt": ["LexV2Bot", "botLocaleIds"]}
          }
        },
        "Handler": "index.handler",
        "MemorySize": "128",
        "Role": {"Fn::GetAtt": ["LexProxyLambdaRole", "Arn"]},
        "Runtime": "nodejs18.x",
        "Timeout": 300,
        "VpcConfig": {
          "Fn::If": [
            "VPCEnabled",
            {
              "SubnetIds": [{"Ref": "AWS::NoValue"}],
              "SecurityGroupIds": [{"Ref": "AWS::NoValue"}]
            },
            {"Ref": "AWS::NoValue"}
          ]
        },
        "TracingConfig": {
          "Fn::If": ["XRAYEnabled", {"Mode": "Active"}, {"Ref": "AWS::NoValue"}]
        },
        "Layers": [{"Ref": "AwsSdkLayerLambdaLayer"}],
        "Tags": [{"Key": "Type", "Value": "Api"}]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W92",
              "reason": "This lambda function does not require to have ReservedConcurrentExecutions"
            }
          ]
        }
      }
    },
    "LexProxyLambdaRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {"Service": "lambda.amazonaws.com"},
              "Action": "sts:AssumeRole"
            }
          ]
        },
        "Path": "/",
        "Policies": [
          {
            "PolicyDocument": {
              "Statement": [
                {
                  "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                  ],
                  "Effect": "Allow",
                  "Resource": {
                    "Fn::Join": [
                      "",
                      [
                        "arn:",
                        {"Ref": "AWS::Partition"},
                        ":logs:",
                        {"Ref": "AWS::Region"},
                        ":",
                        {"Ref": "AWS::AccountId"},
                        ":log-group:/aws/lambda/*"
                      ]
                    ]
                  }
                }
              ],
              "Version": "2012-10-17"
            },
            "PolicyName": "LambdaFunctionServiceRolePolicy"
          },
          {
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                  ],
                  "Resource": {
                    "Fn::Join": [
                      "",
                      [
                        "arn:",
                        {"Ref": "AWS::Partition"},
                        ":logs:",
                        {"Ref": "AWS::Region"},
                        ":",
                        {"Ref": "AWS::AccountId"},
                        ":log-group:/aws/lambda/*"
                      ]
                    ]
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "ec2:CreateNetworkInterface",
                    "ec2:AssignPrivateIpAddresses",
                    "ec2:UnassignPrivateIpAddresses",
                    "ec2:DescribeNetworkInterfaces",
                    "ec2:DeleteNetworkInterface"
                  ],
                  "Resource": "*"
                }
              ]
            },
            "PolicyName": "lambdaVPCAccessExecutionRole"
          },
          {
            "PolicyName": "AWSQnaBotLexFullAccess",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "polly:SynthesizeSpeech",
                    "logs:DescribeLogGroups",
                    "cloudwatch:DescribeAlarms",
                    "kms:DescribeKey",
                    "s3:GetBucketLocation",
                    "lambda:GetPolicy"
                  ],
                  "Resource": [
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:kms:${AWS::Region}:${AWS::AccountId}:key/*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:polly:${AWS::Region}:${AWS::AccountId}:lexicon/*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:cloudwatch:${AWS::Region}:${AWS::AccountId}:alarm:*"
                    },
                    {"Fn::Sub": "arn:${AWS::Partition}:s3:::*"}
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "s3:ListAllMyBuckets",
                    "lambda:ListFunctions",
                    "cloudwatch:DescribeAlarmsForMetric",
                    "kms:ListAliases",
                    "iam:ListRoles",
                    "cloudwatch:GetMetricStatistics",
                    "kendra:ListIndices",
                    "polly:DescribeVoices"
                  ],
                  "Resource": "*"
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "lex:GetBuiltinIntent",
                    "lex:GetIntents",
                    "lex:GetBots",
                    "lex:GetSlotTypes",
                    "lex:GetBotAliases",
                    "lex:StartImport",
                    "lex:GetMigration",
                    "lex:GetBuiltinSlotTypes",
                    "lex:GetBuiltinIntents",
                    "lex:GetImport",
                    "lex:GetMigrations"
                  ],
                  "Resource": "*"
                },
                {
                  "Effect": "Allow",
                  "Action": "lex:*",
                  "Resource": [
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:intent:*:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:slottype:*:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot:*:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot-channel:*:*"
                    }
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "lex:CreateUploadUrl",
                    "lex:ListBuiltInSlotTypes",
                    "lex:ListBots",
                    "lex:ListBuiltInIntents",
                    "lex:ListImports",
                    "lex:ListExports"
                  ],
                  "Resource": "*"
                },
                {
                  "Effect": "Allow",
                  "Action": "lex:*",
                  "Resource": [
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot-alias/*/*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot-alias/*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot/*"
                    }
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "lex:GetBuiltinIntent",
                    "lex:GetIntents",
                    "lex:GetBots",
                    "lex:GetSlotTypes",
                    "lex:GetBotAliases",
                    "lex:StartImport",
                    "lex:GetMigration",
                    "lex:GetBuiltinSlotTypes",
                    "lex:GetBuiltinIntents",
                    "lex:GetImport",
                    "lex:GetMigrations"
                  ],
                  "Resource": "*"
                },
                {
                  "Effect": "Allow",
                  "Action": "lex:*",
                  "Resource": [
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:intent:*:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:slottype:*:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot:*:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot-channel:*:*"
                    }
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "lex:CreateUploadUrl",
                    "lex:ListBuiltInSlotTypes",
                    "lex:ListBots",
                    "lex:ListBuiltInIntents",
                    "lex:ListImports",
                    "lex:ListExports"
                  ],
                  "Resource": "*"
                },
                {
                  "Effect": "Allow",
                  "Action": "lex:*",
                  "Resource": [
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot-alias/*/*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot/*"
                    }
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": ["lambda:AddPermission", "lambda:RemovePermission"],
                  "Resource": {
                    "Fn::Sub": "arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:AmazonLex*"
                  },
                  "Condition": {
                    "StringEquals": {"lambda:Principal": "lex.amazonaws.com"}
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:GetRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/lex.amazonaws.com/AWSServiceRoleForLexBots",
                    "arn:aws:iam::*:role/aws-service-role/channels.lex.amazonaws.com/AWSServiceRoleForLexChannels",
                    "arn:aws:iam::*:role/aws-service-role/lexv2.amazonaws.com/AWSServiceRoleForLexV2Bots*",
                    "arn:aws:iam::*:role/aws-service-role/channels.lexv2.amazonaws.com/AWSServiceRoleForLexV2Channels*"
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:CreateServiceLinkedRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/lex.amazonaws.com/AWSServiceRoleForLexBots"
                  ],
                  "Condition": {
                    "StringEquals": {"iam:AWSServiceName": "lex.amazonaws.com"}
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:CreateServiceLinkedRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/channels.lex.amazonaws.com/AWSServiceRoleForLexChannels"
                  ],
                  "Condition": {
                    "StringEquals": {
                      "iam:AWSServiceName": "channels.lex.amazonaws.com"
                    }
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:CreateServiceLinkedRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/lexv2.amazonaws.com/AWSServiceRoleForLexV2Bots*"
                  ],
                  "Condition": {
                    "StringEquals": {
                      "iam:AWSServiceName": "lexv2.amazonaws.com"
                    }
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:CreateServiceLinkedRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/channels.lexv2.amazonaws.com/AWSServiceRoleForLexV2Channels*"
                  ],
                  "Condition": {
                    "StringEquals": {
                      "iam:AWSServiceName": "channels.lexv2.amazonaws.com"
                    }
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "iam:DeleteServiceLinkedRole",
                    "iam:GetServiceLinkedRoleDeletionStatus"
                  ],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/lex.amazonaws.com/AWSServiceRoleForLexBots",
                    "arn:aws:iam::*:role/aws-service-role/channels.lex.amazonaws.com/AWSServiceRoleForLexChannels",
                    "arn:aws:iam::*:role/aws-service-role/lexv2.amazonaws.com/AWSServiceRoleForLexV2Bots*",
                    "arn:aws:iam::*:role/aws-service-role/channels.lexv2.amazonaws.com/AWSServiceRoleForLexV2Channels*"
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:PassRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/lex.amazonaws.com/AWSServiceRoleForLexBots"
                  ],
                  "Condition": {
                    "StringEquals": {
                      "iam:PassedToService": ["lex.amazonaws.com"]
                    }
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:PassRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/lexv2.amazonaws.com/AWSServiceRoleForLexV2Bots*"
                  ],
                  "Condition": {
                    "StringEquals": {
                      "iam:PassedToService": ["lexv2.amazonaws.com"]
                    }
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:PassRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/channels.lexv2.amazonaws.com/AWSServiceRoleForLexV2Channels*"
                  ],
                  "Condition": {
                    "StringEquals": {
                      "iam:PassedToService": ["channels.lexv2.amazonaws.com"]
                    }
                  }
                }
              ]
            }
          },
          {
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "xray:PutTraceSegments",
                    "xray:PutTelemetryRecords",
                    "xray:GetSamplingRules",
                    "xray:GetSamplingTargets",
                    "xray:GetSamplingStatisticSummaries"
                  ],
                  "Resource": ["*"]
                }
              ]
            },
            "PolicyName": "xrayDaemonWriteAccess"
          },
          {
            "PolicyName": "Access",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": ["s3:Get*"],
                  "Resource": [
                    {"Fn::Sub": "arn:aws:s3:::${BuildStatusBucket}*"}
                  ]
                }
              ]
            }
          }
        ]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W11",
              "reason": "This IAM role requires to have * resource on its permission policy"
            },
            {
              "id": "W12",
              "reason": "Lambda needs the following minimum required permissions to send trace data to X-Ray"
            },
            {"id": "W76", "reason": "This role is required to have high SPCM"},
            {
              "id": "F3",
              "reason": "This role policy is required to have * action in its policy"
            }
          ]
        }
      }
    },
    "KibanaRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {"Federated": "cognito-identity.amazonaws.com"},
              "Action": "sts:AssumeRoleWithWebIdentity",
              "Condition": {
                "StringEquals": {
                  "cognito-identity.amazonaws.com:aud": {"Ref": "KibanaIdPool"}
                }
              }
            }
          ]
        },
        "Path": "/",
        "Policies": [
          {
            "PolicyName": "KibanaOpenSearchAccessPolicy",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Sid": "CognitoAuth",
                  "Effect": "Allow",
                  "Action": "es:ESHttp*",
                  "Resource": {"Fn::Sub": "${ESVar.ESArn}/*"}
                }
              ]
            }
          }
        ]
      }
    },
    "AdminRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {"Federated": "cognito-identity.amazonaws.com"},
              "Action": "sts:AssumeRoleWithWebIdentity",
              "Condition": {
                "StringEquals": {
                  "cognito-identity.amazonaws.com:aud": {"Ref": "IdPool"}
                }
              }
            }
          ]
        },
        "Path": "/",
        "Policies": [
          {
            "PolicyName": "apiAccess",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": ["es:ESHttp*"],
                  "Resource": [{"Fn::GetAtt": ["ESVar", "ESArn"]}]
                },
                {
                  "Effect": "Allow",
                  "Action": ["execute-api:*"],
                  "Resource": [
                    {
                      "Fn::Sub": "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${API}/*/*/*"
                    }
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": ["s3:PutObject"],
                  "Resource": [
                    {"Fn::Sub": "arn:aws:s3:::${ImportBucket}/data/*"},
                    {"Fn::Sub": "arn:aws:s3:::${TestAllBucket}/data/*"}
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": ["s3:GetObject"],
                  "Resource": [
                    {"Fn::Sub": "arn:aws:s3:::${ExportBucket}/data/*"},
                    {"Fn::Sub": "arn:aws:s3:::${TestAllBucket}/data/*"}
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": ["ssm:GetParameters", "ssm:PutParameter"],
                  "Resource": [
                    {
                      "Fn::Sub": "arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/${DefaultQnABotSettings}"
                    },
                    {
                      "Fn::Sub": "arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/${CustomQnABotSettings}"
                    }
                  ]
                }
              ]
            }
          }
        ]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "F3",
              "reason": "This role policy is required to have * action in its policy"
            }
          ]
        }
      }
    },
    "UserRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {"Federated": "cognito-identity.amazonaws.com"},
              "Action": "sts:AssumeRoleWithWebIdentity",
              "Condition": {
                "StringEquals": {
                  "cognito-identity.amazonaws.com:aud": {"Ref": "IdPool"}
                }
              }
            }
          ]
        },
        "Path": "/"
      }
    },
    "UnauthenticatedRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {"Federated": "cognito-identity.amazonaws.com"},
              "Action": "sts:AssumeRoleWithWebIdentity",
              "Condition": {
                "StringEquals": {
                  "cognito-identity.amazonaws.com:aud": {"Ref": "IdPool"}
                }
              }
            }
          ]
        },
        "Path": "/"
      }
    },
    "CFNLambdaRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {"Service": "lambda.amazonaws.com"},
              "Action": "sts:AssumeRole"
            }
          ]
        },
        "Path": "/",
        "ManagedPolicyArns": [
          "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole",
          "arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole",
          "arn:aws:iam::aws:policy/AWSXRayDaemonWriteAccess"
        ],
        "Policies": [
          {
            "PolicyDocument": {
              "Statement": [
                {
                  "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                  ],
                  "Effect": "Allow",
                  "Resource": {
                    "Fn::Join": [
                      "",
                      [
                        "arn:",
                        {"Ref": "AWS::Partition"},
                        ":logs:",
                        {"Ref": "AWS::Region"},
                        ":",
                        {"Ref": "AWS::AccountId"},
                        ":log-group:/aws/lambda/*"
                      ]
                    ]
                  }
                }
              ],
              "Version": "2012-10-17"
            },
            "PolicyName": "LambdaFunctionServiceRolePolicy"
          },
          {
            "PolicyName": "access",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {"Effect": "Allow", "Action": ["es:*"], "Resource": ["*"]},
                {
                  "Effect": "Allow",
                  "Action": [
                    "lex:PutSlotType",
                    "lex:GetSlotType",
                    "lex:DeleteSlotType",
                    "lex:PutIntent",
                    "lex:GetIntent",
                    "lex:DeleteIntent",
                    "lex:PutBot",
                    "lex:GetBot",
                    "lex:DeleteBot",
                    "lex:PutBotAlias",
                    "lex:DeleteBotAlias",
                    "lex:GetBotAlias",
                    "lex:GetBotVersions",
                    "lex:GetIntentVersions",
                    "lex:GetSlotTypeVersions"
                  ],
                  "Resource": ["*"]
                },
                {
                  "Effect": "Allow",
                  "Action": ["apigateway:*"],
                  "Resource": ["*"]
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "cognito-identity:SetIdentityPoolRoles",
                    "cognito-identity:GetIdentityPoolRoles",
                    "iam:PassRole",
                    "iam:CreateServiceLinkedRole"
                  ],
                  "Resource": ["*"]
                },
                {
                  "Effect": "Allow",
                  "Action": ["cognito-idp:*"],
                  "Resource": ["*"]
                },
                {
                  "Sid": "CFNLambdaS3Access",
                  "Effect": "Allow",
                  "Action": [
                    "s3:ListBucketVersions",
                    "s3:PutBucketNotification",
                    "s3:PutObject",
                    "s3:GetObject",
                    "s3:DeleteObjectVersion",
                    "s3:DeleteObject",
                    "s3:GetObjectVersion"
                  ],
                  "Resource": [{"Fn::Sub": "arn:aws:s3:::*"}]
                },
                {
                  "Effect": "Allow",
                  "Action": ["lambda:PublishVersion"],
                  "Resource": [
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:*"
                    }
                  ]
                }
              ]
            }
          }
        ]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "F3",
              "reason": "This role policy is required to have * action in its policy"
            },
            {
              "id": "F38",
              "reason": "This role policy is required to have * action in its policy with PassRole action"
            },
            {
              "id": "W11",
              "reason": "This IAM role requires to have * resource on its permission policy"
            }
          ]
        }
      }
    },
    "Bot": {
      "Type": "AWS::ApiGateway::Resource",
      "Properties": {
        "ParentId": {"Fn::GetAtt": ["API", "RootResourceId"]},
        "PathPart": "bot",
        "RestApiId": {"Ref": "API"}
      }
    },
    "AlexaApi": {
      "Type": "AWS::ApiGateway::Resource",
      "Properties": {
        "ParentId": {"Ref": "Bot"},
        "PathPart": "alexa",
        "RestApiId": {"Ref": "API"}
      }
    },
    "AlexaSchema": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "GET",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "POST",
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":lambda:path/2015-03-31/functions/",
                {"Fn::GetAtt": ["UtteranceLambda", "Arn"]},
                "/invocations"
              ]
            ]
          },
          "IntegrationResponses": [
            {
              "StatusCode": 200,
              "ResponseTemplates": {
                "application/json": {
                  "Fn::Sub": "#set($inputRoot = $input.path('$'))\n#set($utterances = $inputRoot.utterances)\n\n{\n  \"interactionModel\": {\n    \"languageModel\": {\n      \"invocationName\": \"q and a\",\n      \"types\": [\n        {\n          \"name\": \"EXAMPLE_QUESTIONS\",\n          \"values\": [\n            #foreach( $utterance in $utterances)\n                {\"name\":{\n                    \"value\":\"$utterance\" \n                }}#if( $foreach.hasNext ),#end\n            #end\n          ]\n        }\n        ## {\n        ##     \"name\": \"EXAMPLE_QUESTIONS\",\n        ##     \"values\": [\n        ##         {\n        ##             \"name\": {\n        ##                 \"value\": \"this is required\"\n        ##             }\n        ##         }\n        ##     ]\n        ##   }\n      ],\n      \"intents\": [\n        {\n          \"slots\": [\n            {\n              \"name\": \"QnA_slot\",\n              \"type\": \"EXAMPLE_QUESTIONS\"\n            }\n          ],\n          \"name\": \"Qna_intent\",\n          \"samples\": [\n            \"{QnA_slot}\"\n          ]\n        },\n        {\n          \"name\": \"AMAZON.StopIntent\"\n        },\n        {\n          \"name\": \"AMAZON.RepeatIntent\"\n        },\n        {\n          \"name\": \"AMAZON.FallbackIntent\"\n        },\n        {\n          \"name\": \"AMAZON.CancelIntent\"\n        }\n      ]\n    }\n  }\n}\n"
                }
              }
            },
            {
              "SelectionPattern": ".*[InternalServiceError].*",
              "StatusCode": 500,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[BadRequest].*",
              "StatusCode": 400,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[Conflict].*",
              "StatusCode": 409,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[NotFound].*",
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            }
          ],
          "RequestTemplates": {
            "application/json": {
              "Fn::Sub": "{\n}                \n               \n\n"
            }
          }
        },
        "ResourceId": {"Ref": "AlexaApi"},
        "MethodResponses": [
          {
            "StatusCode": 200,
            "ResponseParameters": {"method.response.header.date": true}
          },
          {"StatusCode": 404},
          {"StatusCode": 500}
        ],
        "RestApiId": {"Ref": "API"}
      }
    },
    "BotPost": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "POST",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "POST",
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":lambda:path/2015-03-31/functions/",
                {"Fn::GetAtt": ["LexBuildLambdaStart", "Arn"]},
                "/invocations"
              ]
            ]
          },
          "IntegrationResponses": [
            {
              "StatusCode": 200,
              "ResponseTemplates": {
                "application/json": {
                  "Fn::Sub": "{\"token\":\"$input.path('$.token')\"}\n"
                }
              }
            },
            {
              "SelectionPattern": ".*[InternalServiceError].*",
              "StatusCode": 500,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[BadRequest].*",
              "StatusCode": 400,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[Conflict].*",
              "StatusCode": 409,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[NotFound].*",
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            }
          ]
        },
        "ResourceId": {"Ref": "Bot"},
        "MethodResponses": [
          {
            "StatusCode": 200,
            "ResponseParameters": {"method.response.header.date": true}
          },
          {"StatusCode": 404},
          {"StatusCode": 500}
        ],
        "RestApiId": {"Ref": "API"}
      }
    },
    "BotGet": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "GET",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "POST",
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":lambda:path/2015-03-31/functions/",
                {"Fn::GetAtt": ["LexStatusLambda", "Arn"]},
                "/invocations"
              ]
            ]
          },
          "IntegrationResponses": [
            {
              "StatusCode": 200,
              "ResponseTemplates": {
                "application/json": {
                  "Fn::Sub": "#set ($root=\"https://${!context.domainName}/${!context.stage}\")\n\n#set($inputRoot = $input.path('$'))\n\n{\n    \"lambdaArn\": \"$inputRoot.lambdaArn\",\n    \"lambdaRole\":\"$inputRoot.lambdaRole\",\n    \"botversion\":\"$inputRoot.botversion\",\n    \"botname\":\"$inputRoot.botname\",\n    \"intent\":\"$inputRoot.intent\",\n    \"intentFallback\":\"$inputRoot.intentFallback\",\n    \"lexV2botname\":\"$inputRoot.lexV2botname\",\n    \"lexV2botid\":\"$inputRoot.lexV2botid\",\n    \"lexV2botalias\":\"$inputRoot.lexV2botalias\",\n    \"lexV2botaliasid\":\"$inputRoot.lexV2botaliasid\",\n    \"lexV2intent\":\"$inputRoot.lexV2intent\",\n    \"lexV2intentFallback\":\"$inputRoot.lexV2intentFallback\",\n    \"lexV2localeids\":\"$inputRoot.lexV2localeids\",\n    \"status\":\"$inputRoot.status\",\n    \"build\":$input.json('$.build'),\n    \"_links\":{\n        \"alexa\":{\n            \"href\":\"$root/bot/alexa\"\n        }\n    }\n}\n\n"
                }
              }
            },
            {
              "SelectionPattern": ".*[InternalServiceError].*",
              "StatusCode": 500,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[BadRequest].*",
              "StatusCode": 400,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[Conflict].*",
              "StatusCode": 409,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[NotFound].*",
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            }
          ],
          "RequestTemplates": {
            "application/json": {
              "Fn::Sub": "{\n    \"fnc\":\"getBot\"\n}                \n               \n\n"
            }
          }
        },
        "ResourceId": {"Ref": "Bot"},
        "MethodResponses": [
          {
            "StatusCode": 200,
            "ResponseParameters": {"method.response.header.date": true}
          },
          {"StatusCode": 404},
          {"StatusCode": 500}
        ],
        "RestApiId": {"Ref": "API"}
      }
    },
    "BotDoc": {
      "Type": "AWS::ApiGateway::DocumentationPart",
      "Properties": {
        "Location": {"Type": "RESOURCE", "Path": "/bot"},
        "Properties": "{\"description\":\"\"}",
        "RestApiId": {"Ref": "API"}
      }
    },
    "Health": {
      "Type": "AWS::ApiGateway::Resource",
      "Properties": {
        "ParentId": {"Fn::GetAtt": ["API", "RootResourceId"]},
        "PathPart": "health",
        "RestApiId": {"Ref": "API"}
      }
    },
    "HealthGet": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "GET",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "POST",
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":lambda:path/2015-03-31/functions/",
                {"Fn::GetAtt": ["ESProxyLambda", "Arn"]},
                "/invocations"
              ]
            ]
          },
          "IntegrationResponses": [
            {
              "StatusCode": 200,
              "ResponseTemplates": {
                "application/json": {"Fn::Sub": "{\"status\":\"health\"}\n\n"}
              }
            },
            {
              "SelectionPattern": ".*[InternalServiceError].*",
              "StatusCode": 500,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[BadRequest].*",
              "StatusCode": 400,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[Conflict].*",
              "StatusCode": 409,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[NotFound].*",
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            }
          ],
          "RequestTemplates": {
            "application/json": {
              "Fn::Sub": "{\n    \"endpoint\":\"${ESVar.ESAddress}\",\n    \"method\":\"GET\",\n    \"path\":\"/_cluster/health\"\n}\n\n"
            }
          }
        },
        "ResourceId": {"Ref": "Health"},
        "MethodResponses": [
          {
            "StatusCode": 200,
            "ResponseParameters": {"method.response.header.date": true}
          },
          {"StatusCode": 404},
          {"StatusCode": 500}
        ],
        "RestApiId": {"Ref": "API"}
      }
    },
    "rootGet": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "NONE",
        "HttpMethod": "GET",
        "Integration": {
          "Type": "MOCK",
          "IntegrationResponses": [
            {
              "ResponseTemplates": {
                "application/json": {
                  "Fn::Sub": "#set ($root=\"https://${!context.domainName}/${!context.stage}\")\n\n{\n    \"region\":\"${!stageVariables.Region}\",\n    \"Version\":\"${InfoVar.Version}\",\n    \"BuildDate\":\"${InfoVar.BuildDateString}\",\n    \"BotName\":\"Use LexV2 bot\",\n    \"BotVersion\":\"$LATEST\",\n    \"v2BotId\": \"${LexV2Bot.botId}\",\n    \"v2BotAliasId\": \"${LexV2Bot.botAliasId}\",\n    \"v2BotLocaleId\": \"${LexV2BotLocaleIds}\",\n    \"PoolId\":\"${IdPool}\",\n    \"StackName\":\"${AWS::StackName}\",\n    \"ClientIdClient\":\"${ClientClient}\",\n    \"ClientIdDesigner\":\"${ClientDesigner}\",\n    \"UserPool\":\"${UserPool}\",\n    \"DefaultQnABotSettings\":\"${DefaultQnABotSettings}\",\n    \"CustomQnABotSettings\":\"${CustomQnABotSettings}\",\n    \"KendraCrawlerSnsTopic\":\"${KendraCrawlerSnsTopic}\",\n    \"Id\":\"$stageVariables.Id\",\n    \"_links\":{\n        \"root\":{\n            \"href\":\"$root\"\n        },\n        \"questions\":{\n            \"href\":\"$root/questions\"\n        },        \n        \"crawler\":{\n            \"href\":\"$root/crawler\"\n        },\n        \"crawlerV2\":{\n            \"href\":\"$root/kendranativecrawler\"\n        },\n        \"bot\":{\n            \"href\":\"$root/bot\"\n        },\n        \"jobs\":{\n            \"href\":\"$root/jobs\"\n        },\n        \"connect\":{\n            \"href\":\"$root/connect\"\n        },\n        \"genesys\":{\n            \"href\":\"$root/genesys\"\n        },\n        \"translate\":{\n            \"href\":\"$root/translate\"\n        },\n        \"examples\":{\n            \"href\":\"$root/examples/documents\"\n        },\n        \"DesignerLogin\":{\n            \"href\":\"$stageVariables.DesignerLoginUrl\"\n        },\n        \"ClientLogin\":{\n            \"href\":\"$stageVariables.ClientLoginUrl\"\n        },\n        \"CognitoEndpoint\":{\n            \"href\":\"$stageVariables.CognitoEndpoint\"\n        },\n        \"Services\":{\n            \"href\":\"$root/services\"\n        },\n        \"Kibana\":{\n            \"href\":\"https://${Urls.Kibana}\"\n        }\n    }\n}\n\n"
                }
              },
              "StatusCode": "200"
            }
          ],
          "RequestTemplates": {"application/json": "{\"statusCode\": 200}"}
        },
        "ResourceId": {"Fn::GetAtt": ["API", "RootResourceId"]},
        "MethodResponses": [{"StatusCode": 200}],
        "RestApiId": {"Ref": "API"}
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W59",
              "reason": "This ApiGateway Method does not need authorization setup"
            }
          ]
        }
      }
    },
    "Questions": {
      "Type": "AWS::ApiGateway::Resource",
      "Properties": {
        "ParentId": {"Fn::GetAtt": ["API", "RootResourceId"]},
        "PathPart": "questions",
        "RestApiId": {"Ref": "API"}
      }
    },
    "QuestionsGet": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "GET",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "POST",
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":lambda:path/2015-03-31/functions/",
                {"Fn::GetAtt": ["ESProxyLambda", "Arn"]},
                "/invocations"
              ]
            ]
          },
          "IntegrationResponses": [
            {
              "StatusCode": 200,
              "ResponseTemplates": {
                "application/json": {
                  "Fn::Sub": "#set($inputRoot = $input.path('$'))\n\n{\n    \"total\":$inputRoot.hits.total.value,\n    \"version\":\"1\",\n    \"qa\":[\n        #foreach( $hit in $inputRoot.hits.hits)\n            {\n                #set($Scorepath =  '$.hits.hits['+$foreach.index+']._score')\n                \"_score\":$input.json($Scorepath),\n                #set($Bodypath =  '$.hits.hits['+$foreach.index+']._source')\n                #foreach($paramName in $input.path($Bodypath).keySet())\n                    #if( $paramName == 'questions')\n                        \"q\":[\n                            #foreach( $question in $input.path($Bodypath).get($paramName))\n                                \"$question.q\"\n                                #if($foreach.hasNext),#end\n                            #end\n                        ]\n                    #else\n                        #set( $body =  $Bodypath+\".\"+$paramName)\n                        \"$paramName\" :$input.json($body) \n                    #end\n                #if($foreach.hasNext),#end\n                #end\n            }#if( $foreach.hasNext ),#end\n        #end\n    ]\n}\n\n"
                }
              }
            },
            {
              "SelectionPattern": ".*[InternalServiceError].*",
              "StatusCode": 500,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[BadRequest].*",
              "StatusCode": 400,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[Conflict].*",
              "StatusCode": 409,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[NotFound].*",
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            }
          ],
          "RequestTemplates": {
            "application/json": {
              "Fn::Sub": "#if ( $input.params('perpage').length()==0 )\n    #set ( $perpage = 10 )\n#else\n    #set ( $perpage = $input.params('perpage') )\n#end\n\n#if ( $input.params('from').length()==0)\n    #set ( $from = 0 )\n#else\n    #set ( $from = $input.params('from') )\n#end\n\n#if ( $input.params('order').length()==0 )\n    #set ( $order = \"asc\" )\n#else\n    #set ( $order = $input.params('order') )\n#end\n    \n{\n    \"endpoint\":\"${ESVar.ESAddress}\",\n    \"method\":\"POST\",\n\n    \n    #if($input.params('query').length()>0)\n    \"path\":\"/${Var.QnaIndex}/_search?search_type=dfs_query_then_fetch\",\n    \"question\": \"$util.urlDecode($input.params('query'))\",\n    #else\n    \"path\":\"/${Var.QnaIndex}/_search?search_type=dfs_query_then_fetch\",\n    \"question\": \"\",\n    #end\n    \n    #if ($input.params('topic'))\n    \"topic\": \"$util.urlDecode($input.params('topic'))\",\n    #else\n    \"topic\": \"\",\n    #end\n\n    #if ($input.params('client_filter'))\n    \"client_filter\": \"$util.urlDecode($input.params('client_filter'))\",\n    #else\n    \"client_filter\": \"\",\n    #end\n\n    #if ($input.params('score_answer'))\n    \"score_answer\": \"$util.urlDecode($input.params('score_answer'))\",\n    #else\n    \"score_answer\": \"\",\n    #end\n\n    #if ($input.params('score_text_passage'))\n    \"score_text_passage\": \"$util.urlDecode($input.params('score_text_passage'))\",\n    #else\n    \"score_text_passage\": \"\",\n    #end\n\n    \"size\":\"$perpage\",\n    \"from\":\"$from\",\n\n\n    \"body\":{\n        #if($input.params('query').length()>0)\n        \"comment\": \"ES Query for test queries are now built dynamically by ESProxy Lambda handler.\"\n        #else\n        \"size\":\"$perpage\",\n        \"from\":\"$from\",\n        \"_source\": {\n            \"exclude\": [\"questions.q_vector\", \"a_vector\"]\n        },\n        \"query\": {\n            \"bool\":{\n                #if($input.params('filter').length()==0)\n                \"must\":{\"match_all\":{}}\n                #else\n                \"filter\":{\"regexp\":{\n                    \"qid\":\"$util.urlDecode($input.params('filter'))\"\n                }}\n                #end\n            }\n        }\n        ,\"sort\":{\n            \"qid\":{\n                \"order\":\"$order\" \n            }\n        }\n        #end\n    }\n}\n\n"
            }
          }
        },
        "RequestParameters": {
          "method.request.querystring.query": false,
          "method.request.querystring.topic": false,
          "method.request.querystring.from": false,
          "method.request.querystring.filter": false,
          "method.request.querystring.order": false,
          "method.request.querystring.perpage": false
        },
        "ResourceId": {"Ref": "Questions"},
        "MethodResponses": [
          {
            "StatusCode": 200,
            "ResponseParameters": {"method.response.header.date": true}
          },
          {"StatusCode": 404},
          {"StatusCode": 500}
        ],
        "RestApiId": {"Ref": "API"}
      }
    },
    "QuestionsDelete": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "DELETE",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "POST",
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":lambda:path/2015-03-31/functions/",
                {"Fn::GetAtt": ["ESProxyLambda", "Arn"]},
                "/invocations"
              ]
            ]
          },
          "IntegrationResponses": [
            {
              "StatusCode": 204,
              "ResponseTemplates": {
                "application/json": {
                  "Fn::Sub": "{\n    \"message\":\"success\",\n    \"count\":\"$input.path('$.deleted')\"\n}\n"
                }
              }
            },
            {
              "SelectionPattern": ".*[InternalServiceError].*",
              "StatusCode": 500,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[BadRequest].*",
              "StatusCode": 400,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[Conflict].*",
              "StatusCode": 409,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[NotFound].*",
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            }
          ],
          "RequestTemplates": {
            "application/json": {
              "Fn::Sub": "{\n    \"endpoint\":\"${ESVar.ESAddress}\",\n    \"method\":\"POST\",\n    \"path\":\"/${Var.QnaIndex}/_delete_by_query?refresh=true\",\n    \"body\":{\n        \"query\":{\n            #if($input.path('$.query').length()!=0)\n            \"bool\":{\n                \"must\":{\"match_all\":{}},\n                \"filter\":{\"regexp\":{\n                    \"qid\":\"$input.path('$.query')\"\n                }}\n            }\n            #else\n            \"terms\":{\n                \"qid\":[\n                #foreach($qid in $input.path('$.list'))\n                    \"$qid\"#if($foreach.hasNext),#end\n                #end]\n            }\n            #end\n        }\n    }\n}\n\n\n"
            }
          }
        },
        "ResourceId": {"Ref": "Questions"},
        "MethodResponses": [
          {
            "StatusCode": 204,
            "ResponseParameters": {"method.response.header.date": true}
          },
          {"StatusCode": 404},
          {"StatusCode": 500}
        ],
        "RestApiId": {"Ref": "API"}
      }
    },
    "Question": {
      "Type": "AWS::ApiGateway::Resource",
      "Properties": {
        "ParentId": {"Ref": "Questions"},
        "PathPart": "{ID}",
        "RestApiId": {"Ref": "API"}
      }
    },
    "QuestionHead": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "HEAD",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "POST",
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":lambda:path/2015-03-31/functions/",
                {"Fn::GetAtt": ["ESProxyLambda", "Arn"]},
                "/invocations"
              ]
            ]
          },
          "IntegrationResponses": [
            {
              "StatusCode": 200,
              "ResponseTemplates": {
                "application/json": {"Fn::Sub": "{\"status\":\"exists\"}\n"}
              }
            },
            {
              "SelectionPattern": ".*[InternalServiceError].*",
              "StatusCode": 500,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[BadRequest].*",
              "StatusCode": 400,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[Conflict].*",
              "StatusCode": 409,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[NotFound].*",
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            }
          ],
          "RequestTemplates": {
            "application/json": {
              "Fn::Sub": "{\n    \"endpoint\":\"${ESVar.ESAddress}\",\n    \"method\":\"HEAD\",\n    \"path\":\"/${Var.QnaIndex}/_all/$util.urlDecode($input.params('ID'))\"\n}\n\n\n"
            }
          }
        },
        "RequestParameters": {"method.request.path.Id": true},
        "ResourceId": {"Ref": "Question"},
        "MethodResponses": [
          {
            "StatusCode": 200,
            "ResponseParameters": {"method.response.header.date": true}
          },
          {"StatusCode": 404},
          {"StatusCode": 500}
        ],
        "RestApiId": {"Ref": "API"}
      }
    },
    "QuestionPut": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "PUT",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "POST",
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":lambda:path/2015-03-31/functions/",
                {"Fn::GetAtt": ["ESProxyLambda", "Arn"]},
                "/invocations"
              ]
            ]
          },
          "IntegrationResponses": [
            {
              "StatusCode": 201,
              "ResponseTemplates": {
                "application/json": {
                  "Fn::Sub": "#set($inputRoot = $input.path('$'))\n#set($Idpath =  '$._id')\n#set($Successpath =  '$._shards.successful')\n\n{\n    \"result\":\"$inputRoot.result\",\n    \"id\":$input.json($Idpath),\n    \"success\":$input.json($Successpath)\n}\n\n"
                }
              }
            },
            {
              "SelectionPattern": ".*[InternalServiceError].*",
              "StatusCode": 500,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[BadRequest].*",
              "StatusCode": 400,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[Conflict].*",
              "StatusCode": 409,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[NotFound].*",
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            }
          ],
          "RequestTemplates": {
            "application/json": {
              "Fn::Sub": "#set($inputRoot = $input.path('$'))\n\n#if($input.json('$.type').length())\n    #set($type=$inputRoot.type)\n#else\n    #set($type=\"qna\")\n#end\n\n{\n    \"endpoint\":\"${ESVar.ESAddress}\",\n    \"method\":\"PUT\",\n    \"path\":\"/${Var.QnaIndex}/_doc/$input.params('ID')?refresh=wait_for\",\n    \"body\":{\n        #foreach($paramName in $inputRoot.keySet())\n            #if( $paramName == 'q' && $type==\"qna\")\n                ## generate quniqueterms field by concatenating questions in q array\n                \"quniqueterms\":\" #foreach( $q in $inputRoot.get($paramName))$q #end \",\n                ## replace q array with nested questions array\n                \"questions\":[\n                    #foreach( $q in $inputRoot.get($paramName))\n                        {\"q\":\"$q\"}\n                        #if($foreach.hasNext),#end\n                    #end\n                ]\n                #if($foreach.hasNext),#end\n            #else\n                #set( $body =  '$.'+$paramName)\n                \"$paramName\" :$input.json($body) \n                #if($foreach.hasNext),#end\n            #end\n        #end\n    }\n}\n\n\n"
            }
          }
        },
        "RequestParameters": {"method.request.path.Id": true},
        "ResourceId": {"Ref": "Question"},
        "MethodResponses": [
          {
            "StatusCode": 201,
            "ResponseParameters": {"method.response.header.date": true}
          },
          {"StatusCode": 404},
          {"StatusCode": 500}
        ],
        "RestApiId": {"Ref": "API"}
      }
    },
    "QuestionsOptions": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "OPTIONS",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "POST",
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":lambda:path/2015-03-31/functions/",
                {"Fn::GetAtt": ["SchemaLambda", "Arn"]},
                "/invocations"
              ]
            ]
          },
          "IntegrationResponses": [
            {"StatusCode": 200},
            {
              "SelectionPattern": ".*[InternalServiceError].*",
              "StatusCode": 500,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[BadRequest].*",
              "StatusCode": 400,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[Conflict].*",
              "StatusCode": 409,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[NotFound].*",
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            }
          ],
          "RequestTemplates": {
            "application/json": {
              "Fn::Sub": "{\n    \"comment\": \"API mapping no-op since ES 7.x upgrade. Schema now returned directly from SchemaLambda, rather than from Elasticsearch metadata\"\n}\n\n"
            }
          }
        },
        "ResourceId": {"Ref": "Questions"},
        "MethodResponses": [
          {
            "StatusCode": 200,
            "ResponseParameters": {"method.response.header.date": true}
          },
          {"StatusCode": 404},
          {"StatusCode": 500}
        ],
        "RestApiId": {"Ref": "API"}
      }
    },
    "QuestionDelete": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "DELETE",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "POST",
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":lambda:path/2015-03-31/functions/",
                {"Fn::GetAtt": ["ESProxyLambda", "Arn"]},
                "/invocations"
              ]
            ]
          },
          "IntegrationResponses": [
            {
              "StatusCode": 204,
              "ResponseTemplates": {
                "application/json": {
                  "Fn::Sub": "#set($inputRoot = $input.path('$'))\n#set($Idpath =  '$._id')\n#set($Successpath =  '$._shards.successful')\n\n{\n    \"result\":\"$inputRoot.result\",\n    \"id\":$input.json($Idpath),\n    \"success\":$input.json($Successpath)\n}\n\n"
                }
              }
            },
            {
              "SelectionPattern": ".*[InternalServiceError].*",
              "StatusCode": 500,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[BadRequest].*",
              "StatusCode": 400,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[Conflict].*",
              "StatusCode": 409,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[NotFound].*",
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            }
          ],
          "RequestTemplates": {
            "application/json": {
              "Fn::Sub": "{\n    \"endpoint\":\"${ESVar.ESAddress}\",\n    \"method\":\"POST\",\n    \"path\":\"/${Var.QnaIndex}/_delete_by_query?refresh=true\",\n    \"body\":{\n        \"query\":{\n            \"match\":{\n                \"qid\":\"$util.urlDecode($input.params('ID'))\"\n            }\n        }\n    }\n\n}\n\n\n"
            }
          }
        },
        "RequestParameters": {"method.request.path.Id": true},
        "ResourceId": {"Ref": "Question"},
        "MethodResponses": [
          {
            "StatusCode": 204,
            "ResponseParameters": {"method.response.header.date": true}
          },
          {"StatusCode": 404},
          {"StatusCode": 500}
        ],
        "RestApiId": {"Ref": "API"}
      }
    },
    "Static": {
      "Type": "AWS::ApiGateway::Resource",
      "Properties": {
        "ParentId": {"Fn::GetAtt": ["API", "RootResourceId"]},
        "PathPart": "static",
        "RestApiId": {"Ref": "API"}
      }
    },
    "Proxy": {
      "Type": "AWS::ApiGateway::Resource",
      "Properties": {
        "ParentId": {"Ref": "Static"},
        "PathPart": "{proxy+}",
        "RestApiId": {"Ref": "API"}
      }
    },
    "ProxyAnyGet": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "NONE",
        "HttpMethod": "GET",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "GET",
          "Credentials": {"Fn::GetAtt": ["S3AccessRole", "Arn"]},
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":s3:path/",
                {"Ref": "Bucket"},
                "/{proxy}"
              ]
            ]
          },
          "RequestParameters": {
            "integration.request.path.proxy": "method.request.path.proxy"
          },
          "IntegrationResponses": [
            {
              "StatusCode": 200,
              "ResponseParameters": {
                "method.response.header.content-type": "integration.response.header.Content-Type",
                "method.response.header.api-stage": "context.stage"
              }
            },
            {
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/xml": "{\"error\":\"Not found\"}"
              },
              "SelectionPattern": "403"
            }
          ]
        },
        "RequestParameters": {"method.request.path.proxy": false},
        "ResourceId": {"Ref": "Proxy"},
        "MethodResponses": [
          {
            "StatusCode": 200,
            "ResponseParameters": {
              "method.response.header.content-type": false,
              "method.response.header.api-stage": false
            }
          },
          {"StatusCode": 400},
          {"StatusCode": 404}
        ],
        "RestApiId": {"Ref": "API"}
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W59",
              "reason": "This ApiGateway Method does not need authorization setup"
            }
          ]
        }
      }
    },
    "ProxyAnyHead": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "NONE",
        "HttpMethod": "HEAD",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "HEAD",
          "Credentials": {"Fn::GetAtt": ["S3AccessRole", "Arn"]},
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":s3:path/",
                {"Ref": "Bucket"},
                "/{proxy}"
              ]
            ]
          },
          "RequestParameters": {
            "integration.request.path.proxy": "method.request.path.proxy"
          },
          "IntegrationResponses": [
            {
              "StatusCode": 200,
              "ResponseParameters": {
                "method.response.header.content-type": "integration.response.header.Content-Type",
                "method.response.header.api-stage": "context.stage"
              }
            },
            {
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/xml": "{\"error\":\"Not found\"}"
              },
              "SelectionPattern": "403"
            }
          ]
        },
        "RequestParameters": {"method.request.path.proxy": false},
        "ResourceId": {"Ref": "Proxy"},
        "MethodResponses": [
          {
            "StatusCode": 200,
            "ResponseParameters": {
              "method.response.header.content-type": false,
              "method.response.header.api-stage": false
            }
          },
          {"StatusCode": 400},
          {"StatusCode": 404}
        ],
        "RestApiId": {"Ref": "API"}
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W59",
              "reason": "This ApiGateway Method does not need authorization setup"
            }
          ]
        }
      }
    },
    "Login": {
      "Type": "AWS::ApiGateway::Resource",
      "Properties": {
        "ParentId": {"Fn::GetAtt": ["API", "RootResourceId"]},
        "PathPart": "pages",
        "RestApiId": {"Ref": "API"}
      }
    },
    "DesignerLoginResource": {
      "Type": "AWS::ApiGateway::Resource",
      "Properties": {
        "ParentId": {"Ref": "Login"},
        "PathPart": "designer",
        "RestApiId": {"Ref": "API"}
      }
    },
    "ClientLoginResource": {
      "Type": "AWS::ApiGateway::Resource",
      "Properties": {
        "ParentId": {"Ref": "Login"},
        "PathPart": "client",
        "RestApiId": {"Ref": "API"}
      }
    },
    "DesignerLoginResourceGet": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "NONE",
        "HttpMethod": "GET",
        "Integration": {
          "Type": "MOCK",
          "IntegrationResponses": [
            {
              "ResponseParameters": {
                "method.response.header.location": {
                  "Fn::Join": [
                    "",
                    ["'", {"Fn::GetAtt": ["DesignerLogin", "loginUrl"]}, "'"]
                  ]
                }
              },
              "StatusCode": "302"
            }
          ],
          "RequestTemplates": {"application/json": "{\"statusCode\": 302}"}
        },
        "ResourceId": {"Ref": "DesignerLoginResource"},
        "MethodResponses": [
          {
            "StatusCode": 302,
            "ResponseParameters": {"method.response.header.location": true}
          }
        ],
        "RestApiId": {"Ref": "API"}
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W59",
              "reason": "This ApiGateway Method does not need authorization setup"
            }
          ]
        }
      }
    },
    "ClientLoginResourceGet": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "NONE",
        "HttpMethod": "GET",
        "Integration": {
          "Type": "MOCK",
          "IntegrationResponses": [
            {
              "ResponseParameters": {
                "method.response.header.location": {
                  "Fn::Join": [
                    "",
                    ["'", {"Fn::GetAtt": ["ClientLogin", "loginUrl"]}, "'"]
                  ]
                }
              },
              "StatusCode": "302"
            }
          ],
          "RequestTemplates": {"application/json": "{\"statusCode\": 302}"}
        },
        "ResourceId": {"Ref": "ClientLoginResource"},
        "MethodResponses": [
          {
            "StatusCode": 302,
            "ResponseParameters": {"method.response.header.location": true}
          }
        ],
        "RestApiId": {"Ref": "API"}
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W59",
              "reason": "This ApiGateway Method does not need authorization setup"
            }
          ]
        }
      }
    },
    "Jobs": {
      "Type": "AWS::ApiGateway::Resource",
      "Properties": {
        "ParentId": {"Fn::GetAtt": ["API", "RootResourceId"]},
        "PathPart": "jobs",
        "RestApiId": {"Ref": "API"}
      }
    },
    "JobsGet": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "GET",
        "Integration": {
          "Type": "MOCK",
          "IntegrationResponses": [
            {
              "ResponseTemplates": {
                "application/json": {
                  "Fn::Sub": "#set ($root=\"https://${!context.domainName}/${!context.stage}\")\n\n{\n    \"_links\":{\n        \"imports\":{\n            \"href\":\"$root/jobs/imports\",\n            \"bucket\":\"${ImportBucket}\",\n            \"uploadPrefix\":\"data/\",\n            \"statusPrefix\":\"Status/\"\n        },\n        \"exports\":{\n            \"href\":\"$root/jobs/exports\"\n        },\n        \"testall\":{\n            \"href\":\"$root/jobs/testall\",\n            \"bucket\":\"${TestAllBucket}\",\n            \"statusPrefix\":\"Status/\"\n        }\n    }\n}\n\n"
                }
              },
              "StatusCode": "200"
            }
          ],
          "RequestTemplates": {"application/json": "{\"statusCode\": 200}"}
        },
        "ResourceId": {"Ref": "Jobs"},
        "MethodResponses": [{"StatusCode": 200}],
        "RestApiId": {"Ref": "API"}
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W59",
              "reason": "This ApiGateway Method does not need authorization setup"
            }
          ]
        }
      }
    },
    "testalls": {
      "Type": "AWS::ApiGateway::Resource",
      "Properties": {
        "ParentId": {"Ref": "Jobs"},
        "PathPart": "testall",
        "RestApiId": {"Ref": "API"}
      }
    },
    "testallsList": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "GET",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "POST",
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":lambda:path/2015-03-31/functions/",
                {"Fn::GetAtt": ["S3ListLambda", "Arn"]},
                "/invocations"
              ]
            ]
          },
          "IntegrationResponses": [
            {"StatusCode": 200},
            {
              "SelectionPattern": ".*[InternalServiceError].*",
              "StatusCode": 500,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[BadRequest].*",
              "StatusCode": 400,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[Conflict].*",
              "StatusCode": 409,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[NotFound].*",
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            }
          ],
          "RequestTemplates": {
            "application/json": {
              "Fn::Sub": "#set ($root=\"https://${!context.domainName}/${!context.stage}\")\n\n{\n    \"bucket\":\"${TestAllBucket}\",\n    \"prefix\":\"status/\",\n    \"perpage\":\"$input.params('perpage')\",\n    \"token\":\"$input.params('token')\",\n    \"type\":\"testall\",\n    \"root\":\"$root\"\n}\n\n"
            }
          }
        },
        "RequestParameters": {
          "method.request.querystring.perpage": false,
          "method.request.querystring.token": false
        },
        "ResourceId": {"Ref": "testalls"},
        "MethodResponses": [
          {
            "StatusCode": 200,
            "ResponseParameters": {"method.response.header.date": true}
          },
          {"StatusCode": 404},
          {"StatusCode": 500}
        ],
        "RestApiId": {"Ref": "API"}
      }
    },
    "testall": {
      "Type": "AWS::ApiGateway::Resource",
      "Properties": {
        "ParentId": {"Ref": "testalls"},
        "PathPart": "{proxy+}",
        "RestApiId": {"Ref": "API"}
      }
    },
    "testallPut": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "PUT",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "PUT",
          "Credentials": {"Fn::GetAtt": ["S3AccessRole", "Arn"]},
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":s3:path/",
                {"Ref": "TestAllBucket"},
                "/status/{proxy}"
              ]
            ]
          },
          "RequestParameters": {
            "integration.request.path.proxy": "method.request.path.proxy"
          },
          "RequestTemplates": {
            "application/json": {
              "Fn::Sub": "#set($inputRoot = $input.path('$'))\n\n{\n    \"bucket\":\"${TestAllBucket}\",\n    \"index\":\"${Var.QnaIndex}\",\n    \"id\":\"$input.params('proxy')\",\n    \"config\":\"status/$input.params('proxy')\",\n    \"tmp\":\"tmp/$input.params('proxy')\",\n    \"key\":\"data/$input.params('proxy')\",\n    \"filter\":\"$inputRoot.get('filter')\",\n    \"token\":\"$inputRoot.get('token')\",\n    \"status\":\"Started\"\n}\n\n"
            }
          },
          "IntegrationResponses": [
            {
              "StatusCode": 200,
              "ResponseParameters": {
                "method.response.header.content-type": "integration.response.header.Content-Type"
              }
            },
            {
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/xml": "{\"error\":\"Job not found\"}"
              },
              "SelectionPattern": "403"
            }
          ]
        },
        "RequestParameters": {"method.request.path.proxy": false},
        "ResourceId": {"Ref": "testall"},
        "MethodResponses": [
          {
            "StatusCode": 200,
            "ResponseParameters": {"method.response.header.content-type": false}
          },
          {"StatusCode": 400},
          {"StatusCode": 404}
        ],
        "RestApiId": {"Ref": "API"}
      }
    },
    "testallGet": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "GET",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "GET",
          "Credentials": {"Fn::GetAtt": ["S3AccessRole", "Arn"]},
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":s3:path/",
                {"Ref": "TestAllBucket"},
                "/status/{proxy}"
              ]
            ]
          },
          "RequestParameters": {
            "integration.request.path.proxy": "method.request.path.proxy"
          },
          "IntegrationResponses": [
            {
              "StatusCode": 200,
              "ResponseParameters": {
                "method.response.header.content-type": "integration.response.header.Content-Type"
              }
            },
            {
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/xml": "{\"error\":\"Job not found\"}"
              },
              "SelectionPattern": "403"
            }
          ]
        },
        "RequestParameters": {"method.request.path.proxy": false},
        "ResourceId": {"Ref": "testall"},
        "MethodResponses": [
          {
            "StatusCode": 200,
            "ResponseParameters": {"method.response.header.content-type": false}
          },
          {"StatusCode": 400},
          {"StatusCode": 404}
        ],
        "RestApiId": {"Ref": "API"}
      }
    },
    "testallDelete": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "DELETE",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "DELETE",
          "Credentials": {"Fn::GetAtt": ["S3AccessRole", "Arn"]},
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":s3:path/",
                {"Ref": "TestAllBucket"},
                "/status/{proxy}"
              ]
            ]
          },
          "RequestParameters": {
            "integration.request.path.proxy": "method.request.path.proxy"
          },
          "IntegrationResponses": [
            {
              "StatusCode": 200,
              "ResponseParameters": {
                "method.response.header.content-type": "integration.response.header.Content-Type"
              }
            },
            {
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/xml": "{\"error\":\"Job not found\"}"
              },
              "SelectionPattern": "403"
            }
          ]
        },
        "RequestParameters": {"method.request.path.proxy": false},
        "ResourceId": {"Ref": "testall"},
        "MethodResponses": [
          {
            "StatusCode": 200,
            "ResponseParameters": {"method.response.header.content-type": false}
          },
          {"StatusCode": 400},
          {"StatusCode": 404}
        ],
        "RestApiId": {"Ref": "API"}
      }
    },
    "exports": {
      "Type": "AWS::ApiGateway::Resource",
      "Properties": {
        "ParentId": {"Ref": "Jobs"},
        "PathPart": "exports",
        "RestApiId": {"Ref": "API"}
      }
    },
    "exportsList": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "GET",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "POST",
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":lambda:path/2015-03-31/functions/",
                {"Fn::GetAtt": ["S3ListLambda", "Arn"]},
                "/invocations"
              ]
            ]
          },
          "IntegrationResponses": [
            {"StatusCode": 200},
            {
              "SelectionPattern": ".*[InternalServiceError].*",
              "StatusCode": 500,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[BadRequest].*",
              "StatusCode": 400,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[Conflict].*",
              "StatusCode": 409,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[NotFound].*",
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            }
          ],
          "RequestTemplates": {
            "application/json": {
              "Fn::Sub": "#set ($root=\"https://${!context.domainName}/${!context.stage}\")\n\n{\n    \"bucket\":\"${ExportBucket}\",\n    \"prefix\":\"status/\",\n    \"perpage\":\"$input.params('perpage')\",\n    \"token\":\"$input.params('token')\",\n    \"type\":\"exports\",\n    \"root\":\"$root\"\n}\n\n"
            }
          }
        },
        "RequestParameters": {
          "method.request.querystring.perpage": false,
          "method.request.querystring.token": false
        },
        "ResourceId": {"Ref": "exports"},
        "MethodResponses": [
          {
            "StatusCode": 200,
            "ResponseParameters": {"method.response.header.date": true}
          },
          {"StatusCode": 404},
          {"StatusCode": 500}
        ],
        "RestApiId": {"Ref": "API"}
      }
    },
    "export": {
      "Type": "AWS::ApiGateway::Resource",
      "Properties": {
        "ParentId": {"Ref": "exports"},
        "PathPart": "{proxy+}",
        "RestApiId": {"Ref": "API"}
      }
    },
    "imports": {
      "Type": "AWS::ApiGateway::Resource",
      "Properties": {
        "ParentId": {"Ref": "Jobs"},
        "PathPart": "imports",
        "RestApiId": {"Ref": "API"}
      }
    },
    "exportPut": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "PUT",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "PUT",
          "Credentials": {"Fn::GetAtt": ["S3AccessRole", "Arn"]},
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":s3:path/",
                {"Ref": "ExportBucket"},
                "/status/{proxy}"
              ]
            ]
          },
          "RequestParameters": {
            "integration.request.path.proxy": "method.request.path.proxy"
          },
          "RequestTemplates": {
            "application/json": {
              "Fn::Sub": "#set($inputRoot = $input.path('$'))\n\n{\n    \"bucket\":\"${ExportBucket}\",\n    \"index\":\"${Var.QnaIndex}\",\n    \"id\":\"$input.params('proxy')\",\n    \"config\":\"status/$input.params('proxy')\",\n    \"tmp\":\"tmp/$input.params('proxy')\",\n    \"key\":\"$inputRoot.get('prefix')data/$input.params('proxy')\",\n    \"filter\":\"$inputRoot.get('filter')\",\n    \"status\":\"Started\"\n}"
            }
          },
          "IntegrationResponses": [
            {
              "StatusCode": 200,
              "ResponseParameters": {
                "method.response.header.content-type": "integration.response.header.Content-Type"
              }
            },
            {
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/xml": "{\"error\":\"Job not found\"}"
              },
              "SelectionPattern": "403"
            }
          ]
        },
        "RequestParameters": {"method.request.path.proxy": false},
        "ResourceId": {"Ref": "export"},
        "MethodResponses": [
          {
            "StatusCode": 200,
            "ResponseParameters": {"method.response.header.content-type": false}
          },
          {"StatusCode": 400},
          {"StatusCode": 404}
        ],
        "RestApiId": {"Ref": "API"}
      }
    },
    "exportGet": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "GET",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "GET",
          "Credentials": {"Fn::GetAtt": ["S3AccessRole", "Arn"]},
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":s3:path/",
                {"Ref": "ExportBucket"},
                "/status/{proxy}"
              ]
            ]
          },
          "RequestParameters": {
            "integration.request.path.proxy": "method.request.path.proxy"
          },
          "IntegrationResponses": [
            {
              "StatusCode": 200,
              "ResponseParameters": {
                "method.response.header.content-type": "integration.response.header.Content-Type"
              }
            },
            {
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/xml": "{\"error\":\"Job not found\"}"
              },
              "SelectionPattern": "403"
            }
          ]
        },
        "RequestParameters": {"method.request.path.proxy": false},
        "ResourceId": {"Ref": "export"},
        "MethodResponses": [
          {
            "StatusCode": 200,
            "ResponseParameters": {"method.response.header.content-type": false}
          },
          {"StatusCode": 400},
          {"StatusCode": 404}
        ],
        "RestApiId": {"Ref": "API"}
      }
    },
    "exportDelete": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "DELETE",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "DELETE",
          "Credentials": {"Fn::GetAtt": ["S3AccessRole", "Arn"]},
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":s3:path/",
                {"Ref": "ExportBucket"},
                "/status/{proxy}"
              ]
            ]
          },
          "RequestParameters": {
            "integration.request.path.proxy": "method.request.path.proxy"
          },
          "IntegrationResponses": [
            {
              "StatusCode": 200,
              "ResponseParameters": {
                "method.response.header.content-type": "integration.response.header.Content-Type"
              }
            },
            {
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/xml": "{\"error\":\"Job not found\"}"
              },
              "SelectionPattern": "403"
            }
          ]
        },
        "RequestParameters": {"method.request.path.proxy": false},
        "ResourceId": {"Ref": "export"},
        "MethodResponses": [
          {
            "StatusCode": 200,
            "ResponseParameters": {"method.response.header.content-type": false}
          },
          {"StatusCode": 400},
          {"StatusCode": 404}
        ],
        "RestApiId": {"Ref": "API"}
      }
    },
    "importsList": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "GET",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "POST",
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":lambda:path/2015-03-31/functions/",
                {"Fn::GetAtt": ["S3ListLambda", "Arn"]},
                "/invocations"
              ]
            ]
          },
          "IntegrationResponses": [
            {"StatusCode": 200},
            {
              "SelectionPattern": ".*[InternalServiceError].*",
              "StatusCode": 500,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[BadRequest].*",
              "StatusCode": 400,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[Conflict].*",
              "StatusCode": 409,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[NotFound].*",
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            }
          ],
          "RequestTemplates": {
            "application/json": {
              "Fn::Sub": "#set ($root=\"https://${!context.domainName}/${!context.stage}\")\n\n{\n    \"bucket\":\"${ImportBucket}\",\n    \"prefix\":\"status/\",\n    \"perpage\":\"$input.params('perpage')\",\n    \"token\":\"$input.params('token')\",\n    \"type\":\"imports\",\n    \"root\":\"$root\"\n}\n\n"
            }
          }
        },
        "RequestParameters": {
          "method.request.querystring.perpage": false,
          "method.request.querystring.token": false
        },
        "ResourceId": {"Ref": "imports"},
        "MethodResponses": [
          {
            "StatusCode": 200,
            "ResponseParameters": {"method.response.header.date": true}
          },
          {"StatusCode": 404},
          {"StatusCode": 500}
        ],
        "RestApiId": {"Ref": "API"}
      }
    },
    "import": {
      "Type": "AWS::ApiGateway::Resource",
      "Properties": {
        "ParentId": {"Ref": "imports"},
        "PathPart": "{proxy+}",
        "RestApiId": {"Ref": "API"}
      }
    },
    "importGet": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "GET",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "GET",
          "Credentials": {"Fn::GetAtt": ["S3AccessRole", "Arn"]},
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":s3:path/",
                {"Ref": "ImportBucket"},
                "/status/{proxy}"
              ]
            ]
          },
          "RequestParameters": {
            "integration.request.path.proxy": "method.request.path.proxy"
          },
          "IntegrationResponses": [
            {
              "StatusCode": 200,
              "ResponseParameters": {
                "method.response.header.content-type": "integration.response.header.Content-Type"
              }
            },
            {
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/xml": "{\"error\":\"Job not found\"}"
              },
              "SelectionPattern": "403"
            }
          ]
        },
        "RequestParameters": {"method.request.path.proxy": false},
        "ResourceId": {"Ref": "import"},
        "MethodResponses": [
          {
            "StatusCode": 200,
            "ResponseParameters": {"method.response.header.content-type": false}
          },
          {"StatusCode": 400},
          {"StatusCode": 404}
        ],
        "RestApiId": {"Ref": "API"}
      }
    },
    "importDelete": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "DELETE",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "DELETE",
          "Credentials": {"Fn::GetAtt": ["S3AccessRole", "Arn"]},
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":s3:path/",
                {"Ref": "ImportBucket"},
                "/status/{proxy}"
              ]
            ]
          },
          "RequestParameters": {
            "integration.request.path.proxy": "method.request.path.proxy"
          },
          "IntegrationResponses": [
            {
              "StatusCode": 200,
              "ResponseParameters": {
                "method.response.header.content-type": "integration.response.header.Content-Type"
              }
            },
            {
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/xml": "{\"error\":\"Job not found\"}"
              },
              "SelectionPattern": "403"
            }
          ]
        },
        "RequestParameters": {"method.request.path.proxy": false},
        "ResourceId": {"Ref": "import"},
        "MethodResponses": [
          {
            "StatusCode": 200,
            "ResponseParameters": {"method.response.header.content-type": false}
          },
          {"StatusCode": 400},
          {"StatusCode": 404}
        ],
        "RestApiId": {"Ref": "API"}
      }
    },
    "S3ListLambda": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Code": {
          "ZipFile": "var aws=require('aws-sdk')\naws.config.region=process.env.AWS_REGION\nvar s3=new aws.S3()\n\nexports.handler = (event, context, callback) => {\n    console.log('Received event:', JSON.stringify(event, null, 2));\n   \n    return s3.listObjects({\n        Bucket:event.bucket,\n        Prefix:event.prefix,\n        MaxKeys:event.perpage || 100,\n        Marker:event.token || null\n    }).promise()\n        .then(x => {\n            if (x.Contents && Array.isArray(x.Contents)) {\n                x.Contents.sort((a, b) => {\n                    if (a.LastModified && b.LastModified) {\n                        return new Date(b.LastModified).getTime() - new Date(a.LastModified).getTime();\n                    } else {\n                        return 0;\n                    }\n                })\n            }\n            callback(null, {\n            token:x.NextMarker,\n            jobs:x.Contents.map(y=>{return {\n                id:y.Key.split('/').pop(),\n                href:`${event.root}/jobs/${event.type}/`+encodeURI(y.Key.split('/').pop())\n            }})\n        })\n    })\n    .catch(e=>callback(JSON.stringify({\n        type:\"[InternalServiceError]\",\n        data:e\n    })))\n}\n\n\n"
        },
        "Handler": "index.handler",
        "MemorySize": "128",
        "Role": {"Fn::GetAtt": ["S3ListLambdaRole", "Arn"]},
        "Runtime": "nodejs18.x",
        "Timeout": 300,
        "VpcConfig": {
          "Fn::If": [
            "VPCEnabled",
            {
              "SubnetIds": [{"Ref": "AWS::NoValue"}],
              "SecurityGroupIds": [{"Ref": "AWS::NoValue"}]
            },
            {"Ref": "AWS::NoValue"}
          ]
        },
        "TracingConfig": {
          "Fn::If": ["XRAYEnabled", {"Mode": "Active"}, {"Ref": "AWS::NoValue"}]
        },
        "Layers": [{"Ref": "AwsSdkLayerLambdaLayer"}],
        "Tags": [{"Key": "Type", "Value": "Api"}]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W92",
              "reason": "This lambda function does not require to have ReservedConcurrentExecutions"
            }
          ]
        }
      }
    },
    "S3ListLambdaRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {"Service": "lambda.amazonaws.com"},
              "Action": "sts:AssumeRole"
            }
          ]
        },
        "Path": "/",
        "Policies": [
          {
            "PolicyDocument": {
              "Statement": [
                {
                  "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                  ],
                  "Effect": "Allow",
                  "Resource": {
                    "Fn::Join": [
                      "",
                      [
                        "arn:",
                        {"Ref": "AWS::Partition"},
                        ":logs:",
                        {"Ref": "AWS::Region"},
                        ":",
                        {"Ref": "AWS::AccountId"},
                        ":log-group:/aws/lambda/*"
                      ]
                    ]
                  }
                }
              ],
              "Version": "2012-10-17"
            },
            "PolicyName": "LambdaFunctionServiceRolePolicy"
          },
          {
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                  ],
                  "Resource": {
                    "Fn::Join": [
                      "",
                      [
                        "arn:",
                        {"Ref": "AWS::Partition"},
                        ":logs:",
                        {"Ref": "AWS::Region"},
                        ":",
                        {"Ref": "AWS::AccountId"},
                        ":log-group:/aws/lambda/*"
                      ]
                    ]
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "ec2:CreateNetworkInterface",
                    "ec2:AssignPrivateIpAddresses",
                    "ec2:UnassignPrivateIpAddresses",
                    "ec2:DescribeNetworkInterfaces",
                    "ec2:DeleteNetworkInterface"
                  ],
                  "Resource": "*"
                }
              ]
            },
            "PolicyName": "lambdaVPCAccessExecutionRole"
          },
          {
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "xray:PutTraceSegments",
                    "xray:PutTelemetryRecords",
                    "xray:GetSamplingRules",
                    "xray:GetSamplingTargets",
                    "xray:GetSamplingStatisticSummaries"
                  ],
                  "Resource": ["*"]
                }
              ]
            },
            "PolicyName": "xrayDaemonWriteAccess"
          },
          {
            "PolicyName": "S3ListPolicy",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {"Effect": "Allow", "Action": ["S3:List*"], "Resource": ["*"]}
              ]
            }
          }
        ]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W11",
              "reason": "This IAM role requires to have * resource on its permission policy"
            },
            {
              "id": "W12",
              "reason": "Lambda needs the following minimum required permissions to send trace data to X-Ray"
            }
          ]
        }
      }
    },
    "Examples": {
      "Type": "AWS::ApiGateway::Resource",
      "Properties": {
        "ParentId": {"Fn::GetAtt": ["API", "RootResourceId"]},
        "PathPart": "examples",
        "RestApiId": {"Ref": "API"}
      }
    },
    "ExamplesGet": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "GET",
        "Integration": {
          "Type": "MOCK",
          "IntegrationResponses": [
            {
              "ResponseTemplates": {
                "application/json": {
                  "Fn::Sub": "#set ($root=\"https://${!context.domainName}/${!context.stage}\")\n\n\n{\n    \"_links\":{\n        \"documents\":{\n            \"href\":\"$root/examples/documents\"\n        },\n        \"photos\":{\n            \"href\":\"$root/examples/photos\"\n        }\n    }\n}\n\n"
                }
              },
              "StatusCode": "200"
            }
          ],
          "RequestTemplates": {"application/json": "{\"statusCode\": 200}"}
        },
        "ResourceId": {"Ref": "Examples"},
        "MethodResponses": [{"StatusCode": 200}],
        "RestApiId": {"Ref": "API"}
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W59",
              "reason": "This ApiGateway Method does not need authorization setup"
            }
          ]
        }
      }
    },
    "photos": {
      "Type": "AWS::ApiGateway::Resource",
      "Properties": {
        "ParentId": {"Ref": "Examples"},
        "PathPart": "photos",
        "RestApiId": {"Ref": "API"}
      }
    },
    "photosList": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "GET",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "POST",
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":lambda:path/2015-03-31/functions/",
                {"Fn::GetAtt": ["ExampleS3ListPhotoLambda", "Arn"]},
                "/invocations"
              ]
            ]
          },
          "IntegrationResponses": [
            {"StatusCode": 200},
            {
              "SelectionPattern": ".*[InternalServiceError].*",
              "StatusCode": 500,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[BadRequest].*",
              "StatusCode": 400,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[Conflict].*",
              "StatusCode": 409,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[NotFound].*",
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            }
          ],
          "RequestTemplates": {
            "application/json": {
              "Fn::Sub": "#set ($root=\"https://${!context.domainName}/${!context.stage}\")\n\n{\n    \"bucket\":\"${AssetBucket}\",\n    \"prefix\":\"examples/photos/\",\n    \"perpage\":\"$input.params('perpage')\",\n    \"token\":\"$input.params('token')\",\n    \"root\":\"$root\"\n}\n\n"
            }
          }
        },
        "RequestParameters": {
          "method.request.querystring.perpage": false,
          "method.request.querystring.token": false
        },
        "ResourceId": {"Ref": "photos"},
        "MethodResponses": [
          {
            "StatusCode": 200,
            "ResponseParameters": {"method.response.header.date": true}
          },
          {"StatusCode": 404},
          {"StatusCode": 500}
        ],
        "RestApiId": {"Ref": "API"}
      }
    },
    "photo": {
      "Type": "AWS::ApiGateway::Resource",
      "Properties": {
        "ParentId": {"Ref": "photos"},
        "PathPart": "{proxy+}",
        "RestApiId": {"Ref": "API"}
      }
    },
    "photoGet": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "GET",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "GET",
          "Credentials": {"Fn::GetAtt": ["S3AccessRole", "Arn"]},
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":s3:path/",
                {"Ref": "AssetBucket"},
                "/examples/photos/{proxy}"
              ]
            ]
          },
          "RequestParameters": {
            "integration.request.path.proxy": "method.request.path.proxy"
          },
          "IntegrationResponses": [
            {
              "StatusCode": 200,
              "ResponseParameters": {
                "method.response.header.content-type": "integration.response.header.Content-Type"
              }
            },
            {
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/xml": "{\"error\":\"Not Found\"}"
              },
              "SelectionPattern": "403"
            }
          ]
        },
        "RequestParameters": {"method.request.path.proxy": false},
        "ResourceId": {"Ref": "photo"},
        "MethodResponses": [
          {
            "StatusCode": 200,
            "ResponseParameters": {"method.response.header.content-type": false}
          },
          {"StatusCode": 400},
          {"StatusCode": 404}
        ],
        "RestApiId": {"Ref": "API"}
      }
    },
    "Documents": {
      "Type": "AWS::ApiGateway::Resource",
      "Properties": {
        "ParentId": {"Ref": "Examples"},
        "PathPart": "documents",
        "RestApiId": {"Ref": "API"}
      }
    },
    "DocumentsList": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "GET",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "POST",
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":lambda:path/2015-03-31/functions/",
                {"Fn::GetAtt": ["ExampleS3ListLambda", "Arn"]},
                "/invocations"
              ]
            ]
          },
          "IntegrationResponses": [
            {"StatusCode": 200},
            {
              "SelectionPattern": ".*[InternalServiceError].*",
              "StatusCode": 500,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[BadRequest].*",
              "StatusCode": 400,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[Conflict].*",
              "StatusCode": 409,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[NotFound].*",
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            }
          ],
          "RequestTemplates": {
            "application/json": {
              "Fn::Sub": "#set ($root=\"https://${!context.domainName}/${!context.stage}\")\n\n{\n    \"bucket\":\"${AssetBucket}\",\n    \"prefix\":\"examples/documents/\",\n    \"perpage\":\"$input.params('perpage')\",\n    \"token\":\"$input.params('token')\",\n    \"root\":\"$root\"\n}\n\n"
            }
          }
        },
        "RequestParameters": {
          "method.request.querystring.perpage": false,
          "method.request.querystring.token": false
        },
        "ResourceId": {"Ref": "Documents"},
        "MethodResponses": [
          {
            "StatusCode": 200,
            "ResponseParameters": {"method.response.header.date": true}
          },
          {"StatusCode": 404},
          {"StatusCode": 500}
        ],
        "RestApiId": {"Ref": "API"}
      }
    },
    "Example": {
      "Type": "AWS::ApiGateway::Resource",
      "Properties": {
        "ParentId": {"Ref": "Documents"},
        "PathPart": "{proxy+}",
        "RestApiId": {"Ref": "API"}
      }
    },
    "ExampleGet": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "GET",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "GET",
          "Credentials": {"Fn::GetAtt": ["S3AccessRole", "Arn"]},
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":s3:path/",
                {"Ref": "AssetBucket"},
                "/examples/documents/{proxy}"
              ]
            ]
          },
          "RequestParameters": {
            "integration.request.path.proxy": "method.request.path.proxy"
          },
          "IntegrationResponses": [
            {
              "StatusCode": 200,
              "ResponseParameters": {
                "method.response.header.content-type": "integration.response.header.Content-Type"
              }
            },
            {
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/xml": "{\"error\":\"Not Found\"}"
              },
              "SelectionPattern": "403"
            }
          ]
        },
        "RequestParameters": {"method.request.path.proxy": false},
        "ResourceId": {"Ref": "Example"},
        "MethodResponses": [
          {
            "StatusCode": 200,
            "ResponseParameters": {"method.response.header.content-type": false}
          },
          {"StatusCode": 400},
          {"StatusCode": 404}
        ],
        "RestApiId": {"Ref": "API"}
      }
    },
    "ExampleHead": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "HEAD",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "HEAD",
          "Credentials": {"Fn::GetAtt": ["S3AccessRole", "Arn"]},
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":s3:path/",
                {"Ref": "AssetBucket"},
                "/examples/documents/{proxy}"
              ]
            ]
          },
          "RequestParameters": {
            "integration.request.path.proxy": "method.request.path.proxy"
          },
          "IntegrationResponses": [
            {
              "StatusCode": 200,
              "ResponseParameters": {
                "method.response.header.content-type": "integration.response.header.Content-Type"
              }
            },
            {
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/xml": "{\"error\":\"Not Found\"}"
              },
              "SelectionPattern": "403"
            }
          ]
        },
        "RequestParameters": {"method.request.path.proxy": false},
        "ResourceId": {"Ref": "Example"},
        "MethodResponses": [
          {
            "StatusCode": 200,
            "ResponseParameters": {"method.response.header.content-type": false}
          },
          {"StatusCode": 400},
          {"StatusCode": 404}
        ],
        "RestApiId": {"Ref": "API"}
      }
    },
    "ExampleS3ListLambda": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Code": {
          "ZipFile": "var aws=require('aws-sdk')\naws.config.region=process.env.AWS_REGION\nvar s3=new aws.S3()\n\nexports.photos = (event, context, callback) => {\n    console.log('Received event:', JSON.stringify(event, null, 2));\n    \n    return s3.listObjects({\n        Bucket:event.bucket,\n        Prefix:event.prefix,\n        MaxKeys:event.perpage || 100,\n        Marker:event.token || null\n    }).promise()\n    .then(x=>{\n        console.log(\"s3 response:\",JSON.stringify(x,null,2))\n        var photos=x.Contents.map(function(value){\n            var key=value.Key.split('/').pop()\n            return `${event.root}/examples/photos/${key}`\n        },[])\n        callback(null,{\n            token:x.NextMarker,\n            photos\n        })\n    })\n    .catch(e=>callback(JSON.stringify({\n        type:\"[InternalServiceError]\",\n        data:e\n    })))\n}\nexports.documents = (event, context, callback) => {\n    console.log('Received event:', JSON.stringify(event, null, 2));\n   \n    return s3.listObjects({\n        Bucket:event.bucket,\n        Prefix:event.prefix,\n        MaxKeys:event.perpage || 100,\n        Marker:event.token || null\n    }).promise()\n    .then(x=>{\n        console.log(\"s3 response:\",JSON.stringify(x,null,2))\n        var examples=x.Contents.reduce(function(accum,value){\n            var key=value.Key.split('/').pop().split('.')\n            var ext=key.length >1 ? key.pop() : 'txt'\n            key=key[0]\n            var href=`${event.root}/examples/documents/${key}.${ext}`\n            if(!accum[key]){\n                accum[key]={id:key}\n            }\n            if(ext==='json'){\n                accum[key].document={href}\n            }else{\n                accum[key].description={href}\n            }\n            return accum\n        },[])\n        \n        callback(null,{\n            token:x.NextMarker,\n            examples:Object.keys(examples).map(x=>examples[x])\n        })\n    })\n    .catch(e=>callback(JSON.stringify({\n        type:\"[InternalServiceError]\",\n        data:e\n    })))\n}\n\n\n"
        },
        "Handler": "index.documents",
        "MemorySize": "128",
        "Role": {"Fn::GetAtt": ["S3ListLambdaRole", "Arn"]},
        "Runtime": "nodejs18.x",
        "Timeout": 300,
        "VpcConfig": {
          "Fn::If": [
            "VPCEnabled",
            {
              "SubnetIds": [{"Ref": "AWS::NoValue"}],
              "SecurityGroupIds": [{"Ref": "AWS::NoValue"}]
            },
            {"Ref": "AWS::NoValue"}
          ]
        },
        "TracingConfig": {
          "Fn::If": ["XRAYEnabled", {"Mode": "Active"}, {"Ref": "AWS::NoValue"}]
        },
        "Layers": [{"Ref": "AwsSdkLayerLambdaLayer"}],
        "Tags": [{"Key": "Type", "Value": "Api"}]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W92",
              "reason": "This lambda function does not require to have ReservedConcurrentExecutions"
            }
          ]
        }
      }
    },
    "ExampleS3ListPhotoLambda": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Code": {
          "ZipFile": "var aws=require('aws-sdk')\naws.config.region=process.env.AWS_REGION\nvar s3=new aws.S3()\n\nexports.photos = (event, context, callback) => {\n    console.log('Received event:', JSON.stringify(event, null, 2));\n    \n    return s3.listObjects({\n        Bucket:event.bucket,\n        Prefix:event.prefix,\n        MaxKeys:event.perpage || 100,\n        Marker:event.token || null\n    }).promise()\n    .then(x=>{\n        console.log(\"s3 response:\",JSON.stringify(x,null,2))\n        var photos=x.Contents.map(function(value){\n            var key=value.Key.split('/').pop()\n            return `${event.root}/examples/photos/${key}`\n        },[])\n        callback(null,{\n            token:x.NextMarker,\n            photos\n        })\n    })\n    .catch(e=>callback(JSON.stringify({\n        type:\"[InternalServiceError]\",\n        data:e\n    })))\n}\nexports.documents = (event, context, callback) => {\n    console.log('Received event:', JSON.stringify(event, null, 2));\n   \n    return s3.listObjects({\n        Bucket:event.bucket,\n        Prefix:event.prefix,\n        MaxKeys:event.perpage || 100,\n        Marker:event.token || null\n    }).promise()\n    .then(x=>{\n        console.log(\"s3 response:\",JSON.stringify(x,null,2))\n        var examples=x.Contents.reduce(function(accum,value){\n            var key=value.Key.split('/').pop().split('.')\n            var ext=key.length >1 ? key.pop() : 'txt'\n            key=key[0]\n            var href=`${event.root}/examples/documents/${key}.${ext}`\n            if(!accum[key]){\n                accum[key]={id:key}\n            }\n            if(ext==='json'){\n                accum[key].document={href}\n            }else{\n                accum[key].description={href}\n            }\n            return accum\n        },[])\n        \n        callback(null,{\n            token:x.NextMarker,\n            examples:Object.keys(examples).map(x=>examples[x])\n        })\n    })\n    .catch(e=>callback(JSON.stringify({\n        type:\"[InternalServiceError]\",\n        data:e\n    })))\n}\n\n\n"
        },
        "Handler": "index.photos",
        "MemorySize": "128",
        "Role": {"Fn::GetAtt": ["S3ListLambdaRole", "Arn"]},
        "Runtime": "nodejs18.x",
        "Timeout": 300,
        "VpcConfig": {
          "Fn::If": [
            "VPCEnabled",
            {
              "SubnetIds": [{"Ref": "AWS::NoValue"}],
              "SecurityGroupIds": [{"Ref": "AWS::NoValue"}]
            },
            {"Ref": "AWS::NoValue"}
          ]
        },
        "TracingConfig": {
          "Fn::If": ["XRAYEnabled", {"Mode": "Active"}, {"Ref": "AWS::NoValue"}]
        },
        "Layers": [{"Ref": "AwsSdkLayerLambdaLayer"}],
        "Tags": [{"Key": "Type", "Value": "Api"}]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W92",
              "reason": "This lambda function does not require to have ReservedConcurrentExecutions"
            }
          ]
        }
      }
    },
    "Services": {
      "Type": "AWS::ApiGateway::Resource",
      "Properties": {
        "ParentId": {"Fn::GetAtt": ["API", "RootResourceId"]},
        "PathPart": "services",
        "RestApiId": {"Ref": "API"}
      }
    },
    "ServicesGet": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "GET",
        "Integration": {
          "Type": "MOCK",
          "IntegrationResponses": [
            {
              "ResponseTemplates": {
                "application/json": {
                  "Fn::Sub": "{\n    \"elasticsearch\":{\n        \"qid\":\"${ESQidLambda.Arn}\",\n        \"proxy\":\"${ESProxyLambda.Arn}\"\n    }\n}\n\n"
                }
              },
              "StatusCode": "200"
            }
          ],
          "RequestTemplates": {"application/json": "{\"statusCode\": 200}"}
        },
        "ResourceId": {"Ref": "Services"},
        "MethodResponses": [{"StatusCode": 200}],
        "RestApiId": {"Ref": "API"}
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W59",
              "reason": "This ApiGateway Method does not need authorization setup"
            }
          ]
        }
      }
    },
    "Images": {
      "Type": "AWS::ApiGateway::Resource",
      "Properties": {
        "ParentId": {"Fn::GetAtt": ["API", "RootResourceId"]},
        "PathPart": "images",
        "RestApiId": {"Ref": "API"}
      }
    },
    "ImagesProxy": {
      "Type": "AWS::ApiGateway::Resource",
      "Properties": {
        "ParentId": {"Ref": "Images"},
        "PathPart": "{proxy+}",
        "RestApiId": {"Ref": "API"}
      }
    },
    "ImagesProxyGet": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "NONE",
        "HttpMethod": "GET",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "GET",
          "Credentials": {"Fn::GetAtt": ["S3AccessRole", "Arn"]},
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":s3:path/",
                {"Ref": "Bucket"},
                "/assets/{proxy}"
              ]
            ]
          },
          "RequestParameters": {
            "integration.request.path.proxy": "method.request.path.proxy"
          },
          "IntegrationResponses": [
            {
              "StatusCode": 200,
              "ContentHandling": "CONVERT_TO_BINARY",
              "ResponseParameters": {
                "method.response.header.content-type": "integration.response.header.Content-Type",
                "method.response.header.api-stage": "context.stage"
              }
            },
            {
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/xml": "{\"error\":\"Not found\"}"
              },
              "SelectionPattern": "403"
            }
          ]
        },
        "RequestParameters": {"method.request.path.proxy": false},
        "ResourceId": {"Ref": "ImagesProxy"},
        "MethodResponses": [
          {
            "StatusCode": 200,
            "ResponseParameters": {
              "method.response.header.content-type": false,
              "method.response.header.api-stage": false
            }
          },
          {"StatusCode": 400},
          {"StatusCode": 404}
        ],
        "RestApiId": {"Ref": "API"}
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W59",
              "reason": "This ApiGateway Method does not need authorization setup"
            }
          ]
        }
      }
    },
    "Bucket": {
      "Type": "AWS::S3::Bucket",
      "DeletionPolicy": "Delete",
      "Properties": {
        "WebsiteConfiguration": {"IndexDocument": "index.html"},
        "PublicAccessBlockConfiguration": {
          "BlockPublicAcls": true,
          "BlockPublicPolicy": true,
          "IgnorePublicAcls": true,
          "RestrictPublicBuckets": true
        },
        "BucketEncryption": {
          "Fn::If": [
            "Encrypted",
            {
              "ServerSideEncryptionConfiguration": [
                {"ServerSideEncryptionByDefault": {"SSEAlgorithm": "AES256"}}
              ]
            },
            {"Ref": "AWS::NoValue"}
          ]
        }
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W35",
              "reason": "Access logging is not required for this Bucket."
            }
          ]
        }
      }
    },
    "HTTPSOnlyBucketPolicy": {
      "Type": "AWS::S3::BucketPolicy",
      "Properties": {
        "Bucket": {"Ref": "Bucket"},
        "PolicyDocument": {
          "Statement": [
            {
              "Action": "*",
              "Condition": {"Bool": {"aws:SecureTransport": "false"}},
              "Effect": "Deny",
              "Principal": "*",
              "Resource": {
                "Fn::Join": ["", [{"Fn::GetAtt": ["Bucket", "Arn"]}, "/*"]]
              },
              "Sid": "HttpsOnly"
            }
          ],
          "Version": "2012-10-17"
        }
      }
    },
    "Clear": {
      "Type": "Custom::S3Clear",
      "DependsOn": ["CFNInvokePolicy"],
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "Bucket": {"Ref": "Bucket"}
      }
    },
    "Unzip": {
      "Type": "Custom::S3Unzip",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "SrcBucket": {"Fn::Sub": "solutions-${AWS::Region}"},
        "Key": {"Fn::Join": ["", ["qnabot-on-aws/v5.4.0", "/website.zip"]]},
        "DstBucket": {"Ref": "Bucket"},
        "buildDate": "2023-07-27T21:25:42.097Z"
      },
      "DependsOn": "Clear"
    },
    "S3AccessRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {"Service": "apigateway.amazonaws.com"},
              "Action": "sts:AssumeRole"
            }
          ]
        },
        "Path": "/",
        "Policies": [
          {
            "PolicyName": "S3AccessPolicy",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": ["s3:GetObject"],
                  "Resource": [
                    {"Fn::Sub": "arn:aws:s3:::${ImportBucket}/*"},
                    {"Fn::Sub": "arn:aws:s3:::${ExportBucket}/*"},
                    {"Fn::Sub": "arn:aws:s3:::${TestAllBucket}/*"},
                    {"Fn::Sub": "arn:aws:s3:::${Bucket}/*"},
                    {"Fn::Sub": "arn:aws:s3:::${AssetBucket}/*"}
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": ["s3:PutObject"],
                  "Resource": [
                    {"Fn::Sub": "arn:aws:s3:::${ExportBucket}/*"},
                    {"Fn::Sub": "arn:aws:s3:::${TestAllBucket}/*"}
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": ["s3:DeleteObject"],
                  "Resource": [
                    {"Fn::Sub": "arn:aws:s3:::${ImportBucket}/*"},
                    {"Fn::Sub": "arn:aws:s3:::${ExportBucket}/*"},
                    {"Fn::Sub": "arn:aws:s3:::${TestAllBucket}/*"}
                  ]
                }
              ]
            }
          }
        ]
      }
    },
    "SagemakerEmbeddingsStack": {
      "Type": "AWS::CloudFormation::Stack",
      "Condition": "EmbeddingsSagemaker",
      "Properties": {
        "TemplateURL": {
          "Fn::Sub": "https://solutions-${AWS::Region}.s3.${AWS::Region}.amazonaws.com/qnabot-on-aws/v5.4.0/templates/sagemaker-embeddings.json"
        },
        "Parameters": {
          "CFNLambda": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
          "BootstrapBucket": {"Fn::Sub": "solutions-${AWS::Region}"},
          "BootstrapPrefix": "qnabot-on-aws/v5.4.0",
          "SagemakerInitialInstanceCount": {
            "Ref": "SagemakerInitialInstanceCount"
          },
          "VPCSubnetIdList": {"Fn::Join": [",", [{"Ref": "AWS::NoValue"}]]},
          "VPCSecurityGroupIdList": {
            "Fn::Join": [",", [{"Ref": "AWS::NoValue"}]]
          }
        }
      }
    },
    "SageMakerQASummarizeLLMStack": {
      "Type": "AWS::CloudFormation::Stack",
      "Condition": "LLMSagemaker",
      "Properties": {
        "TemplateURL": {
          "Fn::Sub": "https://solutions-${AWS::Region}.s3.${AWS::Region}.amazonaws.com/qnabot-on-aws/v5.4.0/templates/sagemaker-qa-summarize-llm.json"
        },
        "Parameters": {
          "CFNLambda": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
          "BootstrapBucket": {"Fn::Sub": "solutions-${AWS::Region}"},
          "BootstrapPrefix": "qnabot-on-aws/v5.4.0",
          "SagemakerInstanceType": {"Ref": "LLMSagemakerInstanceType"},
          "SagemakerInitialInstanceCount": {
            "Ref": "LLMSagemakerInitialInstanceCount"
          },
          "VPCSubnetIdList": {"Fn::Join": [",", [{"Ref": "AWS::NoValue"}]]},
          "VPCSecurityGroupIdList": {
            "Fn::Join": [",", [{"Ref": "AWS::NoValue"}]]
          }
        }
      }
    },
    "SchemaLambdaCodeVersion": {
      "Type": "Custom::S3Version",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
        "Key": {"Fn::Sub": "qnabot-on-aws/v5.4.0/lambda/schema.zip"},
        "BuildDate": "2023-07-27T21:25:42.097Z"
      }
    },
    "SchemaLambda": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Code": {
          "S3Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
          "S3Key": {"Fn::Sub": "qnabot-on-aws/v5.4.0/lambda/schema.zip"},
          "S3ObjectVersion": {"Ref": "SchemaLambdaCodeVersion"}
        },
        "Handler": "index.handler",
        "MemorySize": "128",
        "Role": {"Fn::GetAtt": ["SchemaLambdaRole", "Arn"]},
        "Runtime": "nodejs18.x",
        "Timeout": 300,
        "VpcConfig": {
          "Fn::If": [
            "VPCEnabled",
            {
              "SubnetIds": [{"Ref": "AWS::NoValue"}],
              "SecurityGroupIds": [{"Ref": "AWS::NoValue"}]
            },
            {"Ref": "AWS::NoValue"}
          ]
        },
        "TracingConfig": {
          "Fn::If": ["XRAYEnabled", {"Mode": "Active"}, {"Ref": "AWS::NoValue"}]
        },
        "Layers": [{"Ref": "AwsSdkLayerLambdaLayer"}],
        "Tags": [{"Key": "Type", "Value": "Api"}]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W92",
              "reason": "This lambda function does not require to have ReservedConcurrentExecutions"
            }
          ]
        }
      }
    },
    "SchemaLambdaRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {"Service": "lambda.amazonaws.com"},
              "Action": "sts:AssumeRole"
            }
          ]
        },
        "Path": "/",
        "Policies": [
          {
            "PolicyDocument": {
              "Statement": [
                {
                  "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                  ],
                  "Effect": "Allow",
                  "Resource": {
                    "Fn::Join": [
                      "",
                      [
                        "arn:",
                        {"Ref": "AWS::Partition"},
                        ":logs:",
                        {"Ref": "AWS::Region"},
                        ":",
                        {"Ref": "AWS::AccountId"},
                        ":log-group:/aws/lambda/*"
                      ]
                    ]
                  }
                }
              ],
              "Version": "2012-10-17"
            },
            "PolicyName": "LambdaFunctionServiceRolePolicy"
          },
          {
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                  ],
                  "Resource": {
                    "Fn::Join": [
                      "",
                      [
                        "arn:",
                        {"Ref": "AWS::Partition"},
                        ":logs:",
                        {"Ref": "AWS::Region"},
                        ":",
                        {"Ref": "AWS::AccountId"},
                        ":log-group:/aws/lambda/*"
                      ]
                    ]
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "ec2:CreateNetworkInterface",
                    "ec2:AssignPrivateIpAddresses",
                    "ec2:UnassignPrivateIpAddresses",
                    "ec2:DescribeNetworkInterfaces",
                    "ec2:DeleteNetworkInterface"
                  ],
                  "Resource": "*"
                }
              ]
            },
            "PolicyName": "lambdaVPCAccessExecutionRole"
          },
          {
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "xray:PutTraceSegments",
                    "xray:PutTelemetryRecords",
                    "xray:GetSamplingRules",
                    "xray:GetSamplingTargets",
                    "xray:GetSamplingStatisticSummaries"
                  ],
                  "Resource": ["*"]
                }
              ]
            },
            "PolicyName": "xrayDaemonWriteAccess"
          }
        ],
        "ManagedPolicyArns": [{"Ref": "QueryPolicy"}]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W11",
              "reason": "This IAM role requires to have * resource on its permission policy"
            },
            {
              "id": "W12",
              "reason": "Lambda needs the following minimum required permissions to send trace data to X-Ray"
            }
          ]
        }
      }
    },
    "SignupPermision": {
      "Type": "AWS::Lambda::Permission",
      "Properties": {
        "Action": "lambda:InvokeFunction",
        "FunctionName": {"Fn::GetAtt": ["SignupLambda", "Arn"]},
        "Principal": "cognito-idp.amazonaws.com",
        "SourceArn": {"Fn::GetAtt": ["UserPool", "Arn"]}
      }
    },
    "MessagePermision": {
      "Type": "AWS::Lambda::Permission",
      "Properties": {
        "Action": "lambda:InvokeFunction",
        "FunctionName": {"Fn::GetAtt": ["MessageLambda", "Arn"]},
        "Principal": "cognito-idp.amazonaws.com",
        "SourceArn": {"Fn::GetAtt": ["UserPool", "Arn"]}
      }
    },
    "MessageLambda": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Code": {
          "ZipFile": "exports.handler = (event, context, callback) => {\n    console.log('Received event:', JSON.stringify(event, null, 2));\n    var approvedDomain = process.env.APPROVED_DOMAIN;\n\n    if(approvedDomain){\n        var regex=new RegExp(`^[A-Za-z0-9._%+-]+@${approvedDomain}$`)\n        if (event.request.userAttributes.email.match(regex)) {\n            event.response.emailSubject = subject;\n            event.response.emailMessage = message(\n                event.request.codeParameter,\n                event.request.usernameParameter\n            );\n            context.done(null, event);\n        } else {\n            var error = new Error('EMAIL_DOMAIN_DENIED_ERR');\n            context.done(error, event);\n        }\n    }else{\n        event.response.emailSubject = subject;\n        event.response.emailMessage = message(event.request.codeParameter);\n        context.done(null, event);\n    }\n};\n\nvar subject=\"QnABot Signup Verification Code\";\nfunction message(code,name){\n    return `Hello, Your QnABot verification code is: ${code}`\n}\n\n"
        },
        "Handler": "index.handler",
        "MemorySize": "128",
        "Environment": {
          "Variables": {
            "APPROVED_DOMAIN": {
              "Fn::If": ["Domain", "EMPTY", {"Ref": "AWS::NoValue"}]
            }
          }
        },
        "Role": {"Fn::GetAtt": ["SignupLambdaRole", "Arn"]},
        "Runtime": "nodejs18.x",
        "Timeout": 300,
        "VpcConfig": {
          "Fn::If": [
            "VPCEnabled",
            {
              "SubnetIds": [{"Ref": "AWS::NoValue"}],
              "SecurityGroupIds": [{"Ref": "AWS::NoValue"}]
            },
            {"Ref": "AWS::NoValue"}
          ]
        },
        "TracingConfig": {
          "Fn::If": ["XRAYEnabled", {"Mode": "Active"}, {"Ref": "AWS::NoValue"}]
        },
        "Layers": [{"Ref": "AwsSdkLayerLambdaLayer"}],
        "Tags": [{"Key": "Type", "Value": "Cognito"}]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W92",
              "reason": "This lambda function does not require to have ReservedConcurrentExecutions"
            }
          ]
        }
      }
    },
    "SignupLambda": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Code": {
          "ZipFile": "exports.handler = (event, context, callback) => {\n    console.log('Received event:', JSON.stringify(event, null, 2));\n    var approvedDomain = process.env.APPROVED_DOMAIN;\n    \n    if(approvedDomain){\n        var regex=new RegExp(`^[A-Za-z0-9._%+-]+@${approvedDomain}$`)\n        if (event.request.userAttributes.email.match(regex)) {\n            context.done(null, event);\n        }else{\n            var error = new Error('EMAIL_DOMAIN_DENIED_ERR');\n            context.done(error, event);\n        }\n    }else{\n        context.done(null,event) \n    }\n};\n\n"
        },
        "Handler": "index.handler",
        "MemorySize": "128",
        "Environment": {
          "Variables": {
            "APPROVED_DOMAIN": {
              "Fn::If": ["Domain", "EMPTY", {"Ref": "AWS::NoValue"}]
            }
          }
        },
        "Role": {"Fn::GetAtt": ["SignupLambdaRole", "Arn"]},
        "Runtime": "nodejs18.x",
        "Timeout": 300,
        "VpcConfig": {
          "Fn::If": [
            "VPCEnabled",
            {
              "SubnetIds": [{"Ref": "AWS::NoValue"}],
              "SecurityGroupIds": [{"Ref": "AWS::NoValue"}]
            },
            {"Ref": "AWS::NoValue"}
          ]
        },
        "TracingConfig": {
          "Fn::If": ["XRAYEnabled", {"Mode": "Active"}, {"Ref": "AWS::NoValue"}]
        },
        "Layers": [{"Ref": "AwsSdkLayerLambdaLayer"}],
        "Tags": [{"Key": "Type", "Value": "Cognito"}]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W92",
              "reason": "This lambda function does not require to have ReservedConcurrentExecutions"
            }
          ]
        }
      }
    },
    "SignupLambdaRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {"Service": "lambda.amazonaws.com"},
              "Action": "sts:AssumeRole"
            }
          ]
        },
        "Path": "/",
        "Policies": [
          {
            "PolicyDocument": {
              "Statement": [
                {
                  "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                  ],
                  "Effect": "Allow",
                  "Resource": {
                    "Fn::Join": [
                      "",
                      [
                        "arn:",
                        {"Ref": "AWS::Partition"},
                        ":logs:",
                        {"Ref": "AWS::Region"},
                        ":",
                        {"Ref": "AWS::AccountId"},
                        ":log-group:/aws/lambda/*"
                      ]
                    ]
                  }
                }
              ],
              "Version": "2012-10-17"
            },
            "PolicyName": "LambdaFunctionServiceRolePolicy"
          },
          {
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                  ],
                  "Resource": {
                    "Fn::Join": [
                      "",
                      [
                        "arn:",
                        {"Ref": "AWS::Partition"},
                        ":logs:",
                        {"Ref": "AWS::Region"},
                        ":",
                        {"Ref": "AWS::AccountId"},
                        ":log-group:/aws/lambda/*"
                      ]
                    ]
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "ec2:CreateNetworkInterface",
                    "ec2:AssignPrivateIpAddresses",
                    "ec2:UnassignPrivateIpAddresses",
                    "ec2:DescribeNetworkInterfaces",
                    "ec2:DeleteNetworkInterface"
                  ],
                  "Resource": "*"
                }
              ]
            },
            "PolicyName": "lambdaVPCAccessExecutionRole"
          },
          {
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "xray:PutTraceSegments",
                    "xray:PutTelemetryRecords",
                    "xray:GetSamplingRules",
                    "xray:GetSamplingTargets",
                    "xray:GetSamplingStatisticSummaries"
                  ],
                  "Resource": ["*"]
                }
              ]
            },
            "PolicyName": "xrayDaemonWriteAccess"
          }
        ]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W11",
              "reason": "This IAM role requires to have * resource on its permission policy"
            },
            {
              "id": "W12",
              "reason": "Lambda needs the following minimum required permissions to send trace data to X-Ray"
            }
          ]
        }
      }
    },
    "TestAllStack": {
      "Type": "AWS::CloudFormation::Stack",
      "Properties": {
        "TemplateURL": {
          "Fn::Sub": "https://solutions-${AWS::Region}.s3.${AWS::Region}.amazonaws.com/qnabot-on-aws/v5.4.0/templates/testall.json"
        },
        "Parameters": {
          "CFNLambda": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
          "CFNInvokePolicy": {"Ref": "CFNInvokePolicy"},
          "LexV2BotId": {"Fn::GetAtt": ["LexV2Bot", "botId"]},
          "LexV2BotAliasId": {"Fn::GetAtt": ["LexV2Bot", "botAliasId"]},
          "BootstrapBucket": {"Fn::Sub": "solutions-${AWS::Region}"},
          "BootstrapPrefix": "qnabot-on-aws/v5.4.0",
          "VarIndex": {"Fn::GetAtt": ["Var", "QnaIndex"]},
          "EsEndpoint": {"Fn::GetAtt": ["ESVar", "ESAddress"]},
          "EsProxyLambda": {"Fn::GetAtt": ["ESProxyLambda", "Arn"]},
          "TestAllBucket": {"Ref": "TestAllBucket"},
          "VPCSubnetIdList": {"Fn::Join": [",", [{"Ref": "AWS::NoValue"}]]},
          "VPCSecurityGroupIdList": {
            "Fn::Join": [",", [{"Ref": "AWS::NoValue"}]]
          },
          "XraySetting": {"Ref": "XraySetting"},
          "AwsSdkLayerLambdaLayer": {"Ref": "AwsSdkLayerLambdaLayer"}
        }
      }
    },
    "Var": {
      "Type": "Custom::Variable",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "index": {"value": {"Ref": "AWS::StackName"}, "op": "toLowerCase"},
        "QnAType": "qna",
        "QuizType": "quiz",
        "QnaIndex": {
          "value": {"Fn::Sub": "${AWS::StackName}"},
          "op": "toLowerCase"
        },
        "MetricsIndex": {
          "value": {"Fn::Sub": "${AWS::StackName}-metrics"},
          "op": "toLowerCase"
        },
        "FeedbackIndex": {
          "value": {"Fn::Sub": "${AWS::StackName}-feedback"},
          "op": "toLowerCase"
        }
      }
    },
    "InfoVar": {
      "Type": "Custom::Variable",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "Version": "5.4.0",
        "BuildDateString": "Thu Jul 27 2023 21:25:42 GMT+0000 (Coordinated Universal Time)",
        "BuildDate": "2023-07-27T21:25:42.098Z"
      }
    },
    "ESVar": {
      "Type": "Custom::Variable",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "ESArn": {
          "Fn::If": [
            "CreateDomain",
            {"Fn::GetAtt": ["OpensearchDomain", "DomainArn"]},
            {"Fn::GetAtt": ["ESInfo", "Arn"]}
          ]
        },
        "ESAddress": {
          "Fn::If": [
            "CreateDomain",
            {"Fn::GetAtt": ["OpensearchDomain", "DomainEndpoint"]},
            {"Fn::GetAtt": ["ESInfo", "Endpoint"]}
          ]
        },
        "ESDomain": {
          "Fn::If": ["CreateDomain", {"Ref": "OpensearchDomain"}, "EMPTY"]
        }
      }
    },
    "ApiUrl": {
      "Type": "Custom::Variable",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "Name": {
          "Fn::Join": [
            "",
            [
              "https://",
              {"Ref": "API"},
              ".execute-api.",
              {"Ref": "AWS::Region"},
              ".amazonaws.com/prod"
            ]
          ]
        }
      }
    },
    "Urls": {
      "Type": "Custom::Variable",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "Designer": {
          "Fn::Join": [
            "",
            [{"Fn::GetAtt": ["ApiUrl", "Name"]}, "/static/index.html"]
          ]
        },
        "Client": {
          "Fn::Join": [
            "",
            [{"Fn::GetAtt": ["ApiUrl", "Name"]}, "/static/client.html"]
          ]
        },
        "Kibana": {
          "Fn::Sub": "${ESVar.ESAddress}/_dashboards/app/dashboards#/list"
        }
      }
    },
    "API": {
      "Type": "AWS::ApiGateway::RestApi",
      "Properties": {
        "Name": {"Ref": "AWS::StackName"},
        "Description": "An Api interface for the admin actions on the QNA bot",
        "BinaryMediaTypes": ["image/png"],
        "MinimumCompressionSize": 500000
      }
    },
    "Deployment": {
      "Type": "Custom::ApiDeployment",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "restApiId": {"Ref": "API"},
        "buildDate": "2023-07-27T21:25:42.100Z",
        "stage": "prod",
        "Encryption": {"Ref": "Encryption"},
        "LexV2BotLocaleIds": {"Ref": "LexV2BotLocaleIds"}
      },
      "DependsOn": [
        "AlexaSchema",
        "BotPost",
        "BotGet",
        "HealthGet",
        "rootGet",
        "QuestionsGet",
        "QuestionsDelete",
        "QuestionHead",
        "QuestionPut",
        "QuestionsOptions",
        "QuestionDelete",
        "ProxyAnyGet",
        "ProxyAnyHead",
        "DesignerLoginResourceGet",
        "ClientLoginResourceGet",
        "JobsGet",
        "testallsList",
        "testallPut",
        "testallGet",
        "testallDelete",
        "exportsList",
        "exportPut",
        "exportGet",
        "exportDelete",
        "importsList",
        "importGet",
        "importDelete",
        "ExamplesGet",
        "photosList",
        "photoGet",
        "DocumentsList",
        "ExampleGet",
        "ExampleHead",
        "ServicesGet",
        "ImagesProxyGet",
        "InvokePermissionLexBuildLambdaStart",
        "InvokePermissionLexv2BotLambda",
        "InvokePermissionUtteranceLambda",
        "InvokePermissionESQidLambda",
        "InvokePermissionESCleaningLambda",
        "InvokePermissionESProxyLambda",
        "InvokePermissionLexProxyLambda",
        "InvokePermissionS3ListLambda",
        "InvokePermissionExampleS3ListLambda",
        "InvokePermissionExampleS3ListPhotoLambda",
        "InvokePermissionSchemaLambda"
      ]
    },
    "Stage": {
      "Type": "AWS::ApiGateway::Stage",
      "Properties": {
        "DeploymentId": {"Ref": "Deployment"},
        "RestApiId": {"Ref": "API"},
        "StageName": "prod",
        "MethodSettings": [
          {
            "DataTraceEnabled": true,
            "HttpMethod": "*",
            "LoggingLevel": "INFO",
            "ResourcePath": "/*"
          }
        ],
        "Variables": {
          "Id": "QnABot",
          "Region": {"Ref": "AWS::Region"},
          "CognitoEndpoint": {"Fn::GetAtt": ["DesignerLogin", "Domain"]},
          "DesignerLoginUrl": {
            "Fn::Join": [
              "",
              [{"Fn::GetAtt": ["ApiUrl", "Name"]}, "/pages/designer"]
            ]
          },
          "ClientLoginUrl": {
            "Fn::If": [
              "Public",
              {"Fn::GetAtt": ["Urls", "Client"]},
              {
                "Fn::Join": [
                  "",
                  [{"Fn::GetAtt": ["ApiUrl", "Name"]}, "/pages/client"]
                ]
              }
            ]
          }
        }
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W64",
              "reason": "This apiGateway stage does not require to be associated with a usage plan"
            },
            {
              "id": "W69",
              "reason": "This apiGateway stage does not require to have access logging"
            }
          ]
        }
      }
    },
    "ApiGatewayAccount": {
      "Type": "AWS::ApiGateway::Account",
      "Properties": {
        "CloudWatchRoleArn": {
          "Fn::GetAtt": ["ApiGatewayCloudWatchLogsRole", "Arn"]
        }
      }
    },
    "DocumentationVersion": {
      "Type": "AWS::ApiGateway::DocumentationVersion",
      "DependsOn": ["BotDoc"],
      "Properties": {
        "Description": "",
        "DocumentationVersion": "1.0",
        "RestApiId": {"Ref": "API"}
      }
    },
    "InvokePermissionLexBuildLambda": {
      "Type": "AWS::Lambda::Permission",
      "Properties": {
        "Action": "lambda:InvokeFunction",
        "FunctionName": {"Fn::GetAtt": ["LexBuildLambda", "Arn"]},
        "Principal": "apigateway.amazonaws.com"
      }
    },
    "InvokePermissionLexBuildLambdaStart": {
      "Type": "AWS::Lambda::Permission",
      "Properties": {
        "Action": "lambda:InvokeFunction",
        "FunctionName": {"Fn::GetAtt": ["LexBuildLambdaStart", "Arn"]},
        "Principal": "apigateway.amazonaws.com"
      }
    },
    "InvokePermissionLexBuildLambdaPoll": {
      "Type": "AWS::Lambda::Permission",
      "Properties": {
        "Action": "lambda:InvokeFunction",
        "FunctionName": {"Fn::GetAtt": ["LexBuildLambdaPoll", "Arn"]},
        "Principal": "apigateway.amazonaws.com"
      }
    },
    "InvokePermissionLexv2BotLambda": {
      "Type": "AWS::Lambda::Permission",
      "Properties": {
        "Action": "lambda:InvokeFunction",
        "FunctionName": {"Fn::GetAtt": ["Lexv2BotLambda", "Arn"]},
        "Principal": "apigateway.amazonaws.com"
      }
    },
    "InvokePermissionUtteranceLambda": {
      "Type": "AWS::Lambda::Permission",
      "Properties": {
        "Action": "lambda:InvokeFunction",
        "FunctionName": {"Fn::GetAtt": ["UtteranceLambda", "Arn"]},
        "Principal": "apigateway.amazonaws.com"
      }
    },
    "InvokePermissionESQidLambda": {
      "Type": "AWS::Lambda::Permission",
      "Properties": {
        "Action": "lambda:InvokeFunction",
        "FunctionName": {"Fn::GetAtt": ["ESQidLambda", "Arn"]},
        "Principal": "apigateway.amazonaws.com"
      }
    },
    "InvokePermissionESCleaningLambda": {
      "Type": "AWS::Lambda::Permission",
      "Properties": {
        "Action": "lambda:InvokeFunction",
        "FunctionName": {"Fn::GetAtt": ["ESCleaningLambda", "Arn"]},
        "Principal": "apigateway.amazonaws.com"
      }
    },
    "InvokePermissionESProxyLambda": {
      "Type": "AWS::Lambda::Permission",
      "Properties": {
        "Action": "lambda:InvokeFunction",
        "FunctionName": {"Fn::GetAtt": ["ESProxyLambda", "Arn"]},
        "Principal": "apigateway.amazonaws.com"
      }
    },
    "InvokePermissionLexProxyLambda": {
      "Type": "AWS::Lambda::Permission",
      "Properties": {
        "Action": "lambda:InvokeFunction",
        "FunctionName": {"Fn::GetAtt": ["LexProxyLambda", "Arn"]},
        "Principal": "apigateway.amazonaws.com"
      }
    },
    "InvokePermissionLexStatusLambda": {
      "Type": "AWS::Lambda::Permission",
      "Properties": {
        "Action": "lambda:InvokeFunction",
        "FunctionName": {"Fn::GetAtt": ["LexStatusLambda", "Arn"]},
        "Principal": "apigateway.amazonaws.com"
      }
    },
    "InvokePermissionS3ListLambda": {
      "Type": "AWS::Lambda::Permission",
      "Properties": {
        "Action": "lambda:InvokeFunction",
        "FunctionName": {"Fn::GetAtt": ["S3ListLambda", "Arn"]},
        "Principal": "apigateway.amazonaws.com"
      }
    },
    "InvokePermissionExampleS3ListLambda": {
      "Type": "AWS::Lambda::Permission",
      "Properties": {
        "Action": "lambda:InvokeFunction",
        "FunctionName": {"Fn::GetAtt": ["ExampleS3ListLambda", "Arn"]},
        "Principal": "apigateway.amazonaws.com"
      }
    },
    "InvokePermissionExampleS3ListPhotoLambda": {
      "Type": "AWS::Lambda::Permission",
      "Properties": {
        "Action": "lambda:InvokeFunction",
        "FunctionName": {"Fn::GetAtt": ["ExampleS3ListPhotoLambda", "Arn"]},
        "Principal": "apigateway.amazonaws.com"
      }
    },
    "InvokePermissionSchemaLambda": {
      "Type": "AWS::Lambda::Permission",
      "Properties": {
        "Action": "lambda:InvokeFunction",
        "FunctionName": {"Fn::GetAtt": ["SchemaLambda", "Arn"]},
        "Principal": "apigateway.amazonaws.com"
      }
    },
    "dashboard": {
      "Type": "AWS::CloudWatch::Dashboard",
      "Properties": {
        "DashboardName": {"Fn::Sub": "${AWS::Region}-${AWS::StackName}"},
        "DashboardBody": {
          "Fn::Sub": "{\"widgets\":[{\"type\":\"text\",\"width\":24,\"height\":2,\"x\":0,\"y\":0,\"properties\":{\"markdown\":\"# QnABot:${AWS::StackName} Dashboard\"}},{\"type\":\"text\",\"width\":24,\"height\":2,\"x\":0,\"y\":3,\"properties\":{\"markdown\":\"## ElasticSearch\"}},{\"type\":\"metric\",\"width\":6,\"height\":6,\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/ES\",\"ReadLatency\",\"DomainName\",\"${ESVar.ESDomain}\",\"ClientId\",\"${AWS::AccountId}\"]],\"region\":\"${AWS::Region}\"},\"x\":0,\"y\":5},{\"type\":\"metric\",\"width\":6,\"height\":6,\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/ES\",\"ReadIOPS\",\"DomainName\",\"${ESVar.ESDomain}\",\"ClientId\",\"${AWS::AccountId}\"],[\".\",\"ReadThroughput\",\".\",\".\",\".\",\".\",{\"yAxis\":\"right\"}]],\"region\":\"${AWS::Region}\"},\"x\":6,\"y\":5},{\"type\":\"metric\",\"width\":6,\"height\":6,\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/ES\",\"CPUUtilization\",\"DomainName\",\"${ESVar.ESDomain}\",\"ClientId\",\"${AWS::AccountId}\"]],\"region\":\"${AWS::Region}\"},\"x\":12,\"y\":5},{\"type\":\"metric\",\"x\":18,\"y\":5,\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/ES\",\"ClusterUsedSpace\",\"DomainName\",\"${ESVar.ESDomain}\",\"ClientId\",\"${AWS::AccountId}\"],[\".\",\"SearchableDocuments\",\".\",\".\",\".\",\".\",{\"yAxis\":\"right\"}]],\"region\":\"${AWS::Region}\"},\"height\":6,\"width\":6},{\"type\":\"metric\",\"width\":6,\"height\":6,\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/ES\",\"ClusterStatus.green\",\"DomainName\",\"${ESVar.ESDomain}\",\"ClientId\",\"${AWS::AccountId}\",{\"color\":\"#2ca02c\"}],[\".\",\"ClusterStatus.red\",\".\",\".\",\".\",\".\",{\"color\":\"#d62728\"}],[\".\",\"ClusterStatus.yellow\",\".\",\".\",\".\",\".\",{\"color\":\"#bcbd22\"}]],\"region\":\"${AWS::Region}\"},\"x\":0,\"y\":11},{\"type\":\"text\",\"width\":24,\"height\":2,\"x\":0,\"y\":24,\"properties\":{\"markdown\":\"## Lambda Function\"}},{\"type\":\"text\",\"width\":24,\"height\":2,\"x\":0,\"y\":26,\"properties\":{\"markdown\":\"### CustomResource\"}},{\"type\":\"metric\",\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/Lambda\",\"Errors\",\"FunctionName\",\"${VersionLambda}\",{\"stat\":\"Sum\"}],[\".\",\"Invocations\",\".\",\".\",{\"stat\":\"Sum\"}],[\".\",\"Duration\",\".\",\".\",{\"yAxis\":\"right\"}],[\".\",\"Throttles\",\".\",\".\",{\"stat\":\"Sum\"}]],\"region\":\"${AWS::Region}\",\"title\":\"VersionLambda\",\"period\":300},\"height\":6,\"width\":6,\"x\":0,\"y\":28},{\"type\":\"metric\",\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/Lambda\",\"Errors\",\"FunctionName\",\"${CFNLambda}\",{\"stat\":\"Sum\"}],[\".\",\"Invocations\",\".\",\".\",{\"stat\":\"Sum\"}],[\".\",\"Duration\",\".\",\".\",{\"yAxis\":\"right\"}],[\".\",\"Throttles\",\".\",\".\",{\"stat\":\"Sum\"}]],\"region\":\"${AWS::Region}\",\"title\":\"CFNLambda\",\"period\":300},\"height\":6,\"width\":6,\"x\":6,\"y\":28},{\"type\":\"metric\",\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/Lambda\",\"Errors\",\"FunctionName\",\"${ESCFNProxyLambda}\",{\"stat\":\"Sum\"}],[\".\",\"Invocations\",\".\",\".\",{\"stat\":\"Sum\"}],[\".\",\"Duration\",\".\",\".\",{\"yAxis\":\"right\"}],[\".\",\"Throttles\",\".\",\".\",{\"stat\":\"Sum\"}]],\"region\":\"${AWS::Region}\",\"title\":\"ESCFNProxyLambda\",\"period\":300},\"height\":6,\"width\":6,\"x\":12,\"y\":28},{\"type\":\"text\",\"width\":24,\"height\":2,\"x\":0,\"y\":34,\"properties\":{\"markdown\":\"### Fulfillment\"}},{\"type\":\"metric\",\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/Lambda\",\"Errors\",\"FunctionName\",\"${FulfillmentLambda}\",{\"stat\":\"Sum\"}],[\".\",\"Invocations\",\".\",\".\",{\"stat\":\"Sum\"}],[\".\",\"Duration\",\".\",\".\",{\"yAxis\":\"right\"}],[\".\",\"Throttles\",\".\",\".\",{\"stat\":\"Sum\"}]],\"region\":\"${AWS::Region}\",\"title\":\"FulfillmentLambda\",\"period\":300},\"height\":6,\"width\":6,\"x\":0,\"y\":36},{\"type\":\"text\",\"width\":24,\"height\":2,\"x\":0,\"y\":42,\"properties\":{\"markdown\":\"### Warmer\"}},{\"type\":\"metric\",\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/Lambda\",\"Errors\",\"FunctionName\",\"${ESWarmerLambda}\",{\"stat\":\"Sum\"}],[\".\",\"Invocations\",\".\",\".\",{\"stat\":\"Sum\"}],[\".\",\"Duration\",\".\",\".\",{\"yAxis\":\"right\"}],[\".\",\"Throttles\",\".\",\".\",{\"stat\":\"Sum\"}]],\"region\":\"${AWS::Region}\",\"title\":\"ESWarmerLambda\",\"period\":300},\"height\":6,\"width\":6,\"x\":0,\"y\":44},{\"type\":\"text\",\"width\":24,\"height\":2,\"x\":0,\"y\":50,\"properties\":{\"markdown\":\"### Api\"}},{\"type\":\"metric\",\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/Lambda\",\"Errors\",\"FunctionName\",\"${LexBuildLambda}\",{\"stat\":\"Sum\"}],[\".\",\"Invocations\",\".\",\".\",{\"stat\":\"Sum\"}],[\".\",\"Duration\",\".\",\".\",{\"yAxis\":\"right\"}],[\".\",\"Throttles\",\".\",\".\",{\"stat\":\"Sum\"}]],\"region\":\"${AWS::Region}\",\"title\":\"LexBuildLambda\",\"period\":300},\"height\":6,\"width\":6,\"x\":0,\"y\":52},{\"type\":\"metric\",\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/Lambda\",\"Errors\",\"FunctionName\",\"${LexBuildLambdaStart}\",{\"stat\":\"Sum\"}],[\".\",\"Invocations\",\".\",\".\",{\"stat\":\"Sum\"}],[\".\",\"Duration\",\".\",\".\",{\"yAxis\":\"right\"}],[\".\",\"Throttles\",\".\",\".\",{\"stat\":\"Sum\"}]],\"region\":\"${AWS::Region}\",\"title\":\"LexBuildLambdaStart\",\"period\":300},\"height\":6,\"width\":6,\"x\":6,\"y\":52},{\"type\":\"metric\",\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/Lambda\",\"Errors\",\"FunctionName\",\"${LexBuildLambdaPoll}\",{\"stat\":\"Sum\"}],[\".\",\"Invocations\",\".\",\".\",{\"stat\":\"Sum\"}],[\".\",\"Duration\",\".\",\".\",{\"yAxis\":\"right\"}],[\".\",\"Throttles\",\".\",\".\",{\"stat\":\"Sum\"}]],\"region\":\"${AWS::Region}\",\"title\":\"LexBuildLambdaPoll\",\"period\":300},\"height\":6,\"width\":6,\"x\":12,\"y\":52},{\"type\":\"metric\",\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/Lambda\",\"Errors\",\"FunctionName\",\"${Lexv2BotLambda}\",{\"stat\":\"Sum\"}],[\".\",\"Invocations\",\".\",\".\",{\"stat\":\"Sum\"}],[\".\",\"Duration\",\".\",\".\",{\"yAxis\":\"right\"}],[\".\",\"Throttles\",\".\",\".\",{\"stat\":\"Sum\"}]],\"region\":\"${AWS::Region}\",\"title\":\"Lexv2BotLambda\",\"period\":300},\"height\":6,\"width\":6,\"x\":18,\"y\":52},{\"type\":\"metric\",\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/Lambda\",\"Errors\",\"FunctionName\",\"${LexProxyLambda}\",{\"stat\":\"Sum\"}],[\".\",\"Invocations\",\".\",\".\",{\"stat\":\"Sum\"}],[\".\",\"Duration\",\".\",\".\",{\"yAxis\":\"right\"}],[\".\",\"Throttles\",\".\",\".\",{\"stat\":\"Sum\"}]],\"region\":\"${AWS::Region}\",\"title\":\"LexProxyLambda\",\"period\":300},\"height\":6,\"width\":6,\"x\":0,\"y\":58},{\"type\":\"metric\",\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/Lambda\",\"Errors\",\"FunctionName\",\"${LexStatusLambda}\",{\"stat\":\"Sum\"}],[\".\",\"Invocations\",\".\",\".\",{\"stat\":\"Sum\"}],[\".\",\"Duration\",\".\",\".\",{\"yAxis\":\"right\"}],[\".\",\"Throttles\",\".\",\".\",{\"stat\":\"Sum\"}]],\"region\":\"${AWS::Region}\",\"title\":\"LexStatusLambda\",\"period\":300},\"height\":6,\"width\":6,\"x\":6,\"y\":58},{\"type\":\"metric\",\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/Lambda\",\"Errors\",\"FunctionName\",\"${S3ListLambda}\",{\"stat\":\"Sum\"}],[\".\",\"Invocations\",\".\",\".\",{\"stat\":\"Sum\"}],[\".\",\"Duration\",\".\",\".\",{\"yAxis\":\"right\"}],[\".\",\"Throttles\",\".\",\".\",{\"stat\":\"Sum\"}]],\"region\":\"${AWS::Region}\",\"title\":\"S3ListLambda\",\"period\":300},\"height\":6,\"width\":6,\"x\":12,\"y\":58},{\"type\":\"metric\",\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/Lambda\",\"Errors\",\"FunctionName\",\"${ExampleS3ListLambda}\",{\"stat\":\"Sum\"}],[\".\",\"Invocations\",\".\",\".\",{\"stat\":\"Sum\"}],[\".\",\"Duration\",\".\",\".\",{\"yAxis\":\"right\"}],[\".\",\"Throttles\",\".\",\".\",{\"stat\":\"Sum\"}]],\"region\":\"${AWS::Region}\",\"title\":\"ExampleS3ListLambda\",\"period\":300},\"height\":6,\"width\":6,\"x\":18,\"y\":58},{\"type\":\"metric\",\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/Lambda\",\"Errors\",\"FunctionName\",\"${ExampleS3ListPhotoLambda}\",{\"stat\":\"Sum\"}],[\".\",\"Invocations\",\".\",\".\",{\"stat\":\"Sum\"}],[\".\",\"Duration\",\".\",\".\",{\"yAxis\":\"right\"}],[\".\",\"Throttles\",\".\",\".\",{\"stat\":\"Sum\"}]],\"region\":\"${AWS::Region}\",\"title\":\"ExampleS3ListPhotoLambda\",\"period\":300},\"height\":6,\"width\":6,\"x\":0,\"y\":64},{\"type\":\"metric\",\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/Lambda\",\"Errors\",\"FunctionName\",\"${SchemaLambda}\",{\"stat\":\"Sum\"}],[\".\",\"Invocations\",\".\",\".\",{\"stat\":\"Sum\"}],[\".\",\"Duration\",\".\",\".\",{\"yAxis\":\"right\"}],[\".\",\"Throttles\",\".\",\".\",{\"stat\":\"Sum\"}]],\"region\":\"${AWS::Region}\",\"title\":\"SchemaLambda\",\"period\":300},\"height\":6,\"width\":6,\"x\":6,\"y\":64},{\"type\":\"text\",\"width\":24,\"height\":2,\"x\":0,\"y\":70,\"properties\":{\"markdown\":\"### Service\"}},{\"type\":\"metric\",\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/Lambda\",\"Errors\",\"FunctionName\",\"${UtteranceLambda}\",{\"stat\":\"Sum\"}],[\".\",\"Invocations\",\".\",\".\",{\"stat\":\"Sum\"}],[\".\",\"Duration\",\".\",\".\",{\"yAxis\":\"right\"}],[\".\",\"Throttles\",\".\",\".\",{\"stat\":\"Sum\"}]],\"region\":\"${AWS::Region}\",\"title\":\"UtteranceLambda\",\"period\":300},\"height\":6,\"width\":6,\"x\":0,\"y\":72},{\"type\":\"metric\",\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/Lambda\",\"Errors\",\"FunctionName\",\"${ESQidLambda}\",{\"stat\":\"Sum\"}],[\".\",\"Invocations\",\".\",\".\",{\"stat\":\"Sum\"}],[\".\",\"Duration\",\".\",\".\",{\"yAxis\":\"right\"}],[\".\",\"Throttles\",\".\",\".\",{\"stat\":\"Sum\"}]],\"region\":\"${AWS::Region}\",\"title\":\"ESQidLambda\",\"period\":300},\"height\":6,\"width\":6,\"x\":6,\"y\":72},{\"type\":\"metric\",\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/Lambda\",\"Errors\",\"FunctionName\",\"${ESCleaningLambda}\",{\"stat\":\"Sum\"}],[\".\",\"Invocations\",\".\",\".\",{\"stat\":\"Sum\"}],[\".\",\"Duration\",\".\",\".\",{\"yAxis\":\"right\"}],[\".\",\"Throttles\",\".\",\".\",{\"stat\":\"Sum\"}]],\"region\":\"${AWS::Region}\",\"title\":\"ESCleaningLambda\",\"period\":300},\"height\":6,\"width\":6,\"x\":12,\"y\":72},{\"type\":\"metric\",\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/Lambda\",\"Errors\",\"FunctionName\",\"${ESProxyLambda}\",{\"stat\":\"Sum\"}],[\".\",\"Invocations\",\".\",\".\",{\"stat\":\"Sum\"}],[\".\",\"Duration\",\".\",\".\",{\"yAxis\":\"right\"}],[\".\",\"Throttles\",\".\",\".\",{\"stat\":\"Sum\"}]],\"region\":\"${AWS::Region}\",\"title\":\"ESProxyLambda\",\"period\":300},\"height\":6,\"width\":6,\"x\":18,\"y\":72},{\"type\":\"text\",\"width\":24,\"height\":2,\"x\":0,\"y\":78,\"properties\":{\"markdown\":\"### Logging\"}},{\"type\":\"metric\",\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/Lambda\",\"Errors\",\"FunctionName\",\"${ESLoggingLambda}\",{\"stat\":\"Sum\"}],[\".\",\"Invocations\",\".\",\".\",{\"stat\":\"Sum\"}],[\".\",\"Duration\",\".\",\".\",{\"yAxis\":\"right\"}],[\".\",\"Throttles\",\".\",\".\",{\"stat\":\"Sum\"}]],\"region\":\"${AWS::Region}\",\"title\":\"ESLoggingLambda\",\"period\":300},\"height\":6,\"width\":6,\"x\":0,\"y\":80},{\"type\":\"text\",\"width\":24,\"height\":2,\"x\":0,\"y\":86,\"properties\":{\"markdown\":\"### Query\"}},{\"type\":\"metric\",\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/Lambda\",\"Errors\",\"FunctionName\",\"${ESQueryLambda}\",{\"stat\":\"Sum\"}],[\".\",\"Invocations\",\".\",\".\",{\"stat\":\"Sum\"}],[\".\",\"Duration\",\".\",\".\",{\"yAxis\":\"right\"}],[\".\",\"Throttles\",\".\",\".\",{\"stat\":\"Sum\"}]],\"region\":\"${AWS::Region}\",\"title\":\"ESQueryLambda\",\"period\":300},\"height\":6,\"width\":6,\"x\":0,\"y\":88},{\"type\":\"text\",\"width\":24,\"height\":2,\"x\":0,\"y\":94,\"properties\":{\"markdown\":\"### Cognito\"}},{\"type\":\"metric\",\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/Lambda\",\"Errors\",\"FunctionName\",\"${MessageLambda}\",{\"stat\":\"Sum\"}],[\".\",\"Invocations\",\".\",\".\",{\"stat\":\"Sum\"}],[\".\",\"Duration\",\".\",\".\",{\"yAxis\":\"right\"}],[\".\",\"Throttles\",\".\",\".\",{\"stat\":\"Sum\"}]],\"region\":\"${AWS::Region}\",\"title\":\"MessageLambda\",\"period\":300},\"height\":6,\"width\":6,\"x\":0,\"y\":96},{\"type\":\"metric\",\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/Lambda\",\"Errors\",\"FunctionName\",\"${SignupLambda}\",{\"stat\":\"Sum\"}],[\".\",\"Invocations\",\".\",\".\",{\"stat\":\"Sum\"}],[\".\",\"Duration\",\".\",\".\",{\"yAxis\":\"right\"}],[\".\",\"Throttles\",\".\",\".\",{\"stat\":\"Sum\"}]],\"region\":\"${AWS::Region}\",\"title\":\"SignupLambda\",\"period\":300},\"height\":6,\"width\":6,\"x\":6,\"y\":96}]}"
        }
      }
    }
  },
  "Conditions": {
    "Public": {"Fn::Equals": [{"Ref": "PublicOrPrivate"}, "PUBLIC"]},
    "Encrypted": {"Fn::Equals": [{"Ref": "Encryption"}, "ENCRYPTED"]},
    "AdminSignUp": {"Fn::Equals": [true, true]},
    "XRAYEnabled": {"Fn::Equals": [{"Ref": "XraySetting"}, "TRUE"]},
    "Domain": {"Fn::Equals": [true, false]},
    "BuildExamples": {"Fn::Equals": [true, true]},
    "CreateDomain": {"Fn::Equals": [true, true]},
    "DontCreateDomain": {"Fn::Equals": [true, false]},
    "CreateLexV1Bots": {
      "Fn::Equals": [{"Ref": "LexBotVersion"}, "LexV1 and LexV2"]
    },
    "VPCEnabled": {"Fn::Equals": [true, false]},
    "CreateConcurrency": {
      "Fn::Not": [{"Fn::Equals": [{"Ref": "FulfillmentConcurrency"}, "0"]}]
    },
    "SingleNode": {"Fn::Equals": [{"Ref": "ElasticSearchNodeCount"}, "1"]},
    "EmbeddingsEnable": {
      "Fn::Not": [{"Fn::Equals": [{"Ref": "EmbeddingsApi"}, "DISABLED"]}]
    },
    "EmbeddingsSagemaker": {
      "Fn::Equals": [{"Ref": "EmbeddingsApi"}, "SAGEMAKER"]
    },
    "EmbeddingsLambda": {"Fn::Equals": [{"Ref": "EmbeddingsApi"}, "LAMBDA"]},
    "EmbeddingsLambdaArn": {
      "Fn::Not": [{"Fn::Equals": [{"Ref": "EmbeddingsLambdaArn"}, ""]}]
    },
    "LLMEnable": {"Fn::Not": [{"Fn::Equals": [{"Ref": "LLMApi"}, "DISABLED"]}]},
    "LLMSagemaker": {"Fn::Equals": [{"Ref": "LLMApi"}, "SAGEMAKER"]},
    "LLMLambda": {"Fn::Equals": [{"Ref": "LLMApi"}, "LAMBDA"]},
    "LLMLambdaArn": {"Fn::Not": [{"Fn::Equals": [{"Ref": "LLMLambdaArn"}, ""]}]}
  },
  "AWSTemplateFormatVersion": "2010-09-09",
  "Description": "(SO0189) QnABot with admin and client websites - Version v5.4.0",
  "Mappings": {
    "Solution": {
      "Data": {
        "ID": "SO0189",
        "Version": "5.4.0",
        "AppRegistryApplicationName": "qnabot",
        "SolutionName": "QnABot on AWS",
        "ApplicationType": "AWS-Solutions"
      }
    }
  },
  "Outputs": {
    "ContentDesignerURL": {
      "Value": {
        "Fn::Join": [
          "",
          [{"Fn::GetAtt": ["ApiUrl", "Name"]}, "/pages/designer"]
        ]
      }
    },
    "ClientURL": {
      "Value": {
        "Fn::If": [
          "Public",
          {"Fn::GetAtt": ["Urls", "Client"]},
          {
            "Fn::Join": [
              "",
              [{"Fn::GetAtt": ["ApiUrl", "Name"]}, "/pages/client"]
            ]
          }
        ]
      }
    },
    "DashboardURL": {
      "Value": {
        "Fn::Join": [
          "",
          [
            "https://console.aws.amazon.com/cloudwatch/home?",
            "region=",
            {"Ref": "AWS::Region"},
            "#dashboards:name=",
            {"Ref": "dashboard"}
          ]
        ]
      }
    },
    "UserPoolURL": {
      "Value": {
        "Fn::Join": [
          "",
          [
            "https://console.aws.amazon.com/cognito/users/",
            "?region=",
            {"Ref": "AWS::Region"},
            "#/pool/",
            {"Ref": "UserPool"},
            "/details"
          ]
        ]
      }
    },
    "LexV1BotName": {
      "Condition": "CreateLexV1Bots",
      "Value": {"Ref": "LexBot"}
    },
    "LexV1BotAlias": {
      "Condition": "CreateLexV1Bots",
      "Value": {"Ref": "VersionAlias"}
    },
    "LexV1Intent": {"Condition": "CreateLexV1Bots", "Value": {"Ref": "Intent"}},
    "LexV1IntentFallback": {
      "Condition": "CreateLexV1Bots",
      "Value": {"Ref": "IntentFallback"}
    },
    "LexV2BotName": {"Value": {"Fn::GetAtt": ["LexV2Bot", "botName"]}},
    "LexV2BotId": {"Value": {"Fn::GetAtt": ["LexV2Bot", "botId"]}},
    "LexV2BotAlias": {"Value": {"Fn::GetAtt": ["LexV2Bot", "botAlias"]}},
    "LexV2BotAliasId": {"Value": {"Fn::GetAtt": ["LexV2Bot", "botAliasId"]}},
    "LexV2Intent": {"Value": {"Fn::GetAtt": ["LexV2Bot", "botIntent"]}},
    "LexV2IntentFallback": {
      "Value": {"Fn::GetAtt": ["LexV2Bot", "botIntentFallback"]}
    },
    "LexV2BotLocaleIds": {
      "Value": {"Fn::GetAtt": ["LexV2Bot", "botLocaleIds"]}
    },
    "FeedbackSNSTopic": {
      "Value": {"Fn::GetAtt": ["ExamplesStack", "Outputs.FeedbackSNSTopic"]}
    },
    "ESProxyLambda": {"Value": {"Fn::GetAtt": ["ESProxyLambda", "Arn"]}},
    "ElasticsearchEndpoint": {"Value": {"Fn::GetAtt": ["ESVar", "ESAddress"]}},
    "ElasticsearchIndex": {"Value": {"Fn::GetAtt": ["Var", "index"]}},
    "MetricsBucket": {"Value": {"Ref": "MetricsBucket"}}
  },
  "Parameters": {
    "Email": {
      "Type": "String",
      "Description": "Required: Email address for the admin user. Will be used for logging in and for setting the admin password. This email will receive the temporary password for the admin user.",
      "AllowedPattern": ".+\\@.+\\..+",
      "ConstraintDescription": "Must be valid email address eg. johndoe@example.com"
    },
    "Username": {
      "Type": "String",
      "Description": "Administrator username",
      "Default": "Admin"
    },
    "DefaultKendraIndexId": {
      "Type": "String",
      "Description": "Optional: Index ID of an existing Kendra index, used as the default index for QnABot's Kendra integration. You can use the QnABot Content Designer to reconfigure Kendra Index ID settings at any time.",
      "Default": ""
    },
    "Encryption": {
      "Type": "String",
      "Description": "Enables encryption at rest for S3 and ElasticSearch, and provisions m6g.large.elasticsearch instances - recommended for production deployments. Selecting the unencrypted configuration provisions lower cost t3.small.elasticsearch instances. See https://aws.amazon.com/elasticsearch-service/pricing/.",
      "AllowedValues": ["ENCRYPTED", "UNENCRYPTED"],
      "Default": "ENCRYPTED",
      "ConstraintDescription": "Allowed Values are UNENCRYPTED or ENCRYPTED"
    },
    "ElasticSearchNodeCount": {
      "Type": "String",
      "Description": "Number of nodes in ElasticSearch domain - '4' is recommended for fault tolerant production deployments.",
      "AllowedValues": ["1", "2", "4"],
      "Default": "4"
    },
    "ElasticSearchEBSVolumeSize": {
      "Type": "Number",
      "Description": "Size in GB of each EBS volume attached to OpenSearch node instances - '10' is the minimum default volume size.",
      "Default": 10
    },
    "KibanaDashboardRetentionMinutes": {
      "Type": "Number",
      "Description": "To conserve storage in Amazon ElasticSearch, metrics and feedback data used to populate the Kibana dashboard are automatically deleted after this period (default 43200 minutes = 30 days). Monitor 'Free storage space' for your ElasticSearch domain to ensure that you have sufficient space available to store data for the desired retention period.",
      "Default": 43200
    },
    "PublicOrPrivate": {
      "Type": "String",
      "Description": "Choose whether access to the QnABot client should be publicly available or restricted to users in QnABot UserPool.",
      "AllowedValues": ["PUBLIC", "PRIVATE"],
      "Default": "PRIVATE"
    },
    "LexV2BotLocaleIds": {
      "Description": "Languages for QnABot voice interaction using LexV2. Specify as a comma separated list of valid Locale IDs without empty spaces - see https://github.com/aws-solutions/aws-qnabot/blob/main/docs/multilanguage_support.md#supported-languages",
      "Type": "String",
      "Default": "en_US,es_US,fr_CA"
    },
    "LexBotVersion": {
      "Description": "Lex versions to use for QnABot. Select 'LexV2 Only' to install QnABot in AWS reqions where LexV1 is not supported.",
      "Type": "String",
      "AllowedValues": ["LexV1 and LexV2", "LexV2 Only"],
      "Default": "LexV2 Only"
    },
    "InstallLexResponseBots": {
      "Description": "If Elicit Response feature is not needed, choose 'false' to skip sample Lex Response Bot installation.",
      "Type": "String",
      "AllowedValues": ["true", "false"],
      "Default": "true"
    },
    "FulfillmentConcurrency": {
      "Type": "Number",
      "Description": "The amount of provisioned concurrency for the fulfillment Lambda function",
      "Default": 0
    },
    "XraySetting": {
      "Type": "String",
      "Description": "Configure Lambdas with X-Ray enabled",
      "AllowedValues": ["FALSE", "TRUE"],
      "Default": "FALSE",
      "ConstraintDescription": "Allowed Values are FALSE or TRUE"
    },
    "EmbeddingsApi": {
      "Type": "String",
      "Description": "Optionally enable (experimental) QnABot Semantics Search using Embeddings from a pre-trained Large Language Model. If set to SAGEMAKER, an ml.m5.xlarge Sagemaker endpoint is automatically provisioned with Hugging Face e5-large model. To use a custom LAMBDA function, provide additional parameters below.",
      "AllowedValues": ["DISABLED", "SAGEMAKER", "LAMBDA"],
      "Default": "DISABLED"
    },
    "SagemakerInitialInstanceCount": {
      "Type": "Number",
      "MinValue": 0,
      "Description": "Optional: If EmbeddingsApi is SAGEMAKER, provide initial instance count. Set to '0' to enable Serverless Inference (for cold-start delay tolerant deployments only).",
      "Default": 1
    },
    "EmbeddingsLambdaArn": {
      "Type": "String",
      "AllowedPattern": "^(|arn:aws:lambda:.*)$",
      "Description": "Optional: If EmbeddingsApi is LAMBDA, provide ARN for a Lambda function that takes JSON {\"inputtext\":\"string\"}, and returns JSON {\"embedding\":[...]}",
      "Default": ""
    },
    "EmbeddingsLambdaDimensions": {
      "Type": "Number",
      "MinValue": 1,
      "Description": "Optional: If EmbeddingsApi is LAMBDA, provide number of dimensions for embeddings returned by the EmbeddingsLambda function specified above.",
      "Default": 4096
    },
    "LLMApi": {
      "Type": "String",
      "Description": "Optionally enable (experimental) QnABot question disambiguation and generative question answering using an LLM. If set to SAGEMAKER, a Sagemaker endpoint is automatically provisioned. To use a custom LAMBDA function, provide additional parameters below.",
      "AllowedValues": ["DISABLED", "SAGEMAKER", "LAMBDA"],
      "Default": "DISABLED"
    },
    "LLMSagemakerInstanceType": {
      "Type": "String",
      "AllowedPattern": "^ml.*$",
      "Description": "Optional: If LLMApi is SAGEMAKER, provide the SageMaker endpoint instance type. Defaults to ml.g5.12xlarge. Check account and region availability through the Service Quotas service before deploying",
      "Default": "ml.g5.12xlarge"
    },
    "LLMSagemakerInitialInstanceCount": {
      "Type": "Number",
      "MinValue": 1,
      "Description": "Optional: If LLMApi is SAGEMAKER, provide initial instance count. Serverless Inference is not currently available for the built-in LLM model.",
      "Default": 1
    },
    "LLMLambdaArn": {
      "Type": "String",
      "AllowedPattern": "^(|arn:aws:lambda:.*)$",
      "Description": "Optional: If LLMApi is LAMBDA, provide ARN for a Lambda function that takes JSON {\"prompt\":\"string\", \"settings\":{key:value,..}}, and returns JSON {\"generated_text\":\"string\"}",
      "Default": ""
    }
  },
  "Metadata": {
    "AWS::CloudFormation::Interface": {
      "ParameterGroups": [
        {
          "Label": {"default": "Authentication"},
          "Parameters": ["Email", "Username", "PublicOrPrivate"]
        },
        {
          "Label": {"default": "Amazon Kendra Integration"},
          "Parameters": ["DefaultKendraIndexId"]
        },
        {
          "Label": {"default": "Amazon OpenSearch Service"},
          "Parameters": [
            "ElasticSearchNodeCount",
            "ElasticSearchEBSVolumeSize",
            "Encryption",
            "KibanaDashboardRetentionMinutes"
          ]
        },
        {
          "Label": {"default": "Amazon LexV2"},
          "Parameters": ["LexV2BotLocaleIds"]
        },
        {
          "Label": {"default": "Semantic Search with Embeddings"},
          "Parameters": [
            "EmbeddingsApi",
            "SagemakerInitialInstanceCount",
            "EmbeddingsLambdaArn",
            "EmbeddingsLambdaDimensions"
          ]
        },
        {
          "Label": {
            "default": "LLM integration for contextual followup and generative answers"
          },
          "Parameters": [
            "LLMApi",
            "LLMSagemakerInstanceType",
            "LLMSagemakerInitialInstanceCount",
            "LLMLambdaArn"
          ]
        },
        {
          "Label": {"default": "Miscellaneous"},
          "Parameters": [
            "LexBotVersion",
            "InstallLexResponseBots",
            "FulfillmentConcurrency",
            "XraySetting"
          ]
        }
      ]
    }
  }
}