diff --git a/.gitignore b/.gitignore index 64540f2e..48eba8b4 100644 --- a/.gitignore +++ b/.gitignore @@ -71,3 +71,4 @@ jmeter.log installer/*.log security-check/*.log saas-boost-install.log +samples diff --git a/resources/saas-boost-svc-onboarding.yaml b/resources/saas-boost-svc-onboarding.yaml index a882a9f8..651ad2b9 100644 --- a/resources/saas-boost-svc-onboarding.yaml +++ b/resources/saas-boost-svc-onboarding.yaml @@ -45,6 +45,7 @@ Parameters: ECSRepository: Description: SaaS Boost ECR image repository Type: String + Resources: SSMParamOnboardingTemplate: Type: AWS::SSM::Parameter @@ -232,6 +233,13 @@ Resources: - lambda.amazonaws.com Action: - sts:AssumeRole + # # Elasticsearch policy + # - Effect: Allow + # Action: + # - es:DescribeElasticsearchDomain + # Resource: + # - !Sub arn:aws:es:${AWS::Region}:${AWS::AccountId}:domain/*/* + Policies: - PolicyName: !Sub sb-${Environment}-onboarding-svc-policy-${AWS::Region} PolicyDocument: @@ -564,6 +572,16 @@ Resources: - ec2:AuthorizeSecurityGroupEgress Resource: - !Sub arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:security-group/* + # Elasticsearch onboarding policy + - Effect: Allow + Action: + - es:AddTags + - es:CreateElasticsearchDomain + - es:DescribeElasticsearchDomain + - es:CreateElasticsearchServiceRole + Resource: + - !Sub arn:aws:es:${AWS::Region}:${AWS::AccountId}:domain/* + OnboardingServiceDeleteTenantExecutionRole: Type: AWS::IAM::Role Properties: @@ -875,6 +893,19 @@ Resources: - ec2:RevokeSecurityGroupEgress Resource: - !Sub arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:security-group/* + # Elasticsearch onboarding delete policy + - Effect: Allow + Action: + - es:DeleteElasticsearchDomain + - es:DeleteElasticsearchServiceRole + - es:DescribeElasticsearchDomain + # case specific - debug purpose + # - es:ESHttpPut + ############## + - es:RemoveTags + Resource: + - !Sub arn:aws:es:${AWS::Region}:${AWS::AccountId}:domain/* + OnboardingServiceGetAllLogs: Type: AWS::Logs::LogGroup Properties: @@ -1200,9 +1231,6 @@ Resources: Environment: Variables: ONBOARDING_TABLE: !Ref OnboardingTable - API_TRUST_ROLE: !Sub arn:aws:iam::${AWS::AccountId}:role/sb-private-api-trust-role-${Environment}-${AWS::Region} - API_GATEWAY_HOST: !Sub ${SaaSBoostPrivateApi}.execute-api.${AWS::Region}.amazonaws.com - API_GATEWAY_STAGE: !Ref PrivateApiStage Tags: - Key: "Application" Value: "SaaSBoost" diff --git a/resources/tenant-onboarding-es.yaml b/resources/tenant-onboarding-es.yaml new file mode 100644 index 00000000..14753e82 --- /dev/null +++ b/resources/tenant-onboarding-es.yaml @@ -0,0 +1,177 @@ + +# Copyright 2020 Daniel Cortez Stevenson +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Original: https://gist.github.com/daniel-cortez-stevenson/ +# modified: https://github.com/AffiTheCreator +# +--- +AWSTemplateFormatVersion: 2010-09-09 +Description: SaaS Boost Tenant Onboarding AWS Elasticsearch Service (ES) +Parameters: + TenantId: + Description: The GUID for the tenant + Type: String + VPC: + Description: VPC id for this tenant + Type: AWS::EC2::VPC::Id + # PrivateSubnetA: + # Description: Private subnet for ES + # Type: AWS::EC2::Subnet::Id + SubnetPublicA: + Description: Public subnet for ES + Type: AWS::EC2::Subnet::Id + # PrivateSubnetB: + # Description: Private subnet for EFS mount target + # Type: AWS::EC2::Subnet::Id + ECSSecurityGroup: + Description: Source security group for ECS to access EFS + Type: AWS::EC2::SecurityGroup::Id + CustomEndpointEnabled: + Type: String + AllowedValues: ['true', 'false'] + Default: 'false' + EnforceHTTPS: + Type: String + AllowedValues: ['true', 'false'] + Default: 'false' + ESPortHTTP: + Type: String + Default: '80' + ESPortHTTPS: + Type: String + Default: '443' + ESPort: + Type: String + TLSSecurityPolicy: + Type: String + AllowedValues: ['true', 'false'] + Default: 'false' + ElasticsearchName: + Description: The name of the AWS Elasticsearch Service deployment. + Type: String + ConstraintDescription: Must be a valid AWS ES domain name prefix. The name must start with a + lowercase letter and must be between 3 and 28 characters. Valid characters + are a-z (lowercase only), 0-9, and - (hyphen). + AllowedPattern: '[a-z][a-z0-9\\-]+' + ElasticsearchVersion: + Default: '6.2' + Type: String + ConstraintDescription: Must be an allowed AWS ES version (Major.Minor) + AllowedValues: ['7.9', '7.8', '7.7', '7.4', '7.1', '6.8', '6.7', '6.5', '6.4', '6.3', '6.2', '6.0', '5.6', '5.5'] # aws es list-elasticsearch-versions --query "ElasticsearchVersions[]" + ElasticsearchDataInstanceType: + Description: Instance type for data nodes. + Type: String + Default: 'r5.2xlarge.elasticsearch' + NumberOfMasterNodes: + Description: How many dedicated master nodes you want to have. 3 is recommended. + Type: Number + Default: 3 + NumberOfDataNodes: + Description: How many data nodes you want to have. Multiples of your number of availability zones (2) is recommended. + Type: Number + Default: '2' + MinValue: '1' + MaxValue: '20' + EBSEnabled: + Description: 'Specifies whether Amazon EBS volumes are attached to data nodes in the Amazon ES domain (some instance types come with instance store that you can use instead).' + Type: String + AllowedValues: ['true', 'false'] + Default: 'true' + EBSVolumeSize: + Description: 'The size of the EBS volume for each data node. The minimum and maximum size of an EBS volume depends on the EBS volume type and the instance type to which it is attached.' + Type: Number + Default: '10' +Conditions: + EnforceHTTPS_false: !Equals [ !Ref "EnforceHTTPS", "false" ] + +Resources: + ESSecurityGroup: + Type: AWS::EC2::SecurityGroup + Properties: + GroupName: + Fn::Join: ['', ['tenant-', !Select [0, !Split ['-', !Ref TenantId]], '-es-sg']] + GroupDescription: Elasticsearch Security Group + VpcId: !Ref VPC + ESSecurityGroupIngressECS: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: !Ref ESSecurityGroup + IpProtocol: tcp + # To review !! + FromPort: !If [EnforceHTTPS_false, !Ref ESPortHTTP, !Ref ESPortHTTPS] + ToPort: !If [EnforceHTTPS_false, !Ref ESPortHTTP, !Ref ESPortHTTPS] + SourceSecurityGroupId: !Ref ECSSecurityGroup + + ElasticsearchDomain: + DependsOn: ESSecurityGroup + Type: AWS::Elasticsearch::Domain + Properties: + ElasticsearchVersion: !Ref ElasticsearchVersion + DomainName: !Ref ElasticsearchName + DomainEndpointOptions: + EnforceHTTPS: !Ref EnforceHTTPS + EBSOptions: + EBSEnabled: !Ref EBSEnabled + Iops: 0 + VolumeSize: !Ref EBSVolumeSize + VolumeType: standard + ElasticsearchClusterConfig: + InstanceCount: !Ref NumberOfDataNodes + InstanceType: !Ref ElasticsearchDataInstanceType + ZoneAwarenessEnabled: false + AdvancedOptions: + rest.action.multi.allow_explicit_index: "true" + SnapshotOptions: + AutomatedSnapshotStartHour: 0 + VPCOptions: + SubnetIds: + - !Ref SubnetPublicA + # - !Ref PrivateSubnetB + SecurityGroupIds: + - !Ref ESSecurityGroup + AccessPolicies: + Version: 2012-10-17 + Statement: + - Effect: Allow + Principal: + AWS: '*' + Action: "es:*" + Resource: !Sub "arn:aws:es:${AWS::Region}:${AWS::AccountId}:domain/${ElasticsearchName}/*" + Tags: + - Key: Tenant + Value: !Ref TenantId + +Outputs: + Arn: + Value: !GetAtt ElasticsearchDomain.Arn + ESDomainArn: + Value: !GetAtt ElasticsearchDomain.DomainArn + ESDomainEndpoint: + Description: Elasticsearch endpoint + Value: !GetAtt ElasticsearchDomain.DomainEndpoint + ESClusterName: + Description: The Elasticsearch Cluster + Value: !Ref ElasticsearchName + ESClusterPort: + Description: Listening Port of Elasticsearch cluster + Value: !Ref ESPortHTTP + ESClusterPortDefault: + Description: Typicaly when migrating an on-premises elastricsearch(ES) stack to a cloud cluster the application that uses ES will need 2 ports, this bypasses such requirement + Value: !Ref ESPortHTTPS + # ESSubnetID: + # Description: VPC Subnet ID for Elasticsearch Cluster + # Value: !Ref PrivateSubnetA + +... \ No newline at end of file diff --git a/resources/tenant-onboarding.yaml b/resources/tenant-onboarding.yaml index 1d113ce4..01188d65 100644 --- a/resources/tenant-onboarding.yaml +++ b/resources/tenant-onboarding.yaml @@ -18,13 +18,16 @@ Parameters: Environment: Description: Environment (test, uat, prod, etc.) Type: String + Default: oct12 SaaSBoostBucket: Description: SaaS Boost assets S3 bucket Type: String + Default: sb-oct12-artifacts-e7389e84-cdae LambdaSourceFolder: Description: Folder for lambda source code to change on each deployment Type: String Default: lambdas + #Default: lambdas-2020-10-12-15-26 TenantId: Description: The GUID for the tenant Type: String @@ -61,6 +64,7 @@ Parameters: ContainerRepository: Description: The name of the ECR repository hosting the container image Type: String + Default: ecsrepository-o9zf9rbljvnt ContainerPort: Description: The TCP port the container is listening on via EXPOSE in the Dockerfile Type: Number @@ -68,7 +72,8 @@ Parameters: ContainerHealthCheckPath: Description: The destination on the Container for the Load Balancer to use for health checks Type: String - Default: '/' + #Default: '/index.html' + Default: / CodePipelineRoleArn: Description: The IAM role for CodePipeline Type: String @@ -78,15 +83,20 @@ Parameters: CidrPrefix: Description: Prefix of Cidr for this tenant such as 10.1, 10.2 etc. Type: String + #Default: 10.0 + Default: 10.10 TransitGateway: Description: Id of Transit Gateway for Egress Type: String + Default: tgw-0e8f91a21d14b1e5e TenantTransitGatewayRouteTable: Description: Id of the Tenants Route table for Transit Gateway Type: String + Default: tgw-rtb-034f653af0d951d46 EgressTransitGatewayRouteTable: Description: Id of the Egress Route table for Transit Gateway Type: String + Default: tgw-rtb-06222a87e38f4df69 DomainName: Description: The hosted zone domain name Type: String @@ -117,6 +127,143 @@ Parameters: - AFTER_60_DAYS - AFTER_90_DAYS Default: NEVER +# Elasticsearch config + # ProvisionES: + # Description: Deploy the elasticsearch nested stack? + # Type: String + # AllowedValues: ['true', 'false'] + # Default: 'true' + UseES: + Description: Deploy the Elasticsearch nested stack? + Type: String + AllowedValues: ['true', 'false'] + Default: 'true' + ElasticsearchVersion: + Default: '6.2' + Type: String + ConstraintDescription: Must be an allowed AWS ES version (Major.Minor) + AllowedValues: ['7.9', '7.8', '7.7', '7.4', '7.1', '6.8', '6.7', '6.5', '6.4', '6.3', '6.2', '6.0', '5.6', '5.5'] + ElasticsearchMasterInstanceType: + Description: Instance type for master nodes. + Type: String + Default: t2.small.elasticsearch + AllowedValues: + - r5.large.elasticsearch + - r5.xlarge.elasticsearch + - r5.2xlarge.elasticsearch + - r5.4xlarge.elasticsearch + - r5.12xlarge.elasticsearch + - t2.small.elasticsearch + - t2.medium.elasticsearch + - c4.large.elasticsearch + - c4.xlarge.elasticsearch + - c4.2xlarge.elasticsearch + - c4.4xlarge.elasticsearch + - c4.8xlarge.elasticsearch + - i2.xlarge.elasticsearch + - i2.2xlarge.elasticsearch + - m4.large.elasticsearch + - m4.xlarge.elasticsearch + - m4.2xlarge.elasticsearch + - m4.4xlarge.elasticsearch + - m4.10xlarge.elasticsearch + - r4.large.elasticsearch + - r4.xlarge.elasticsearch + - r4.2xlarge.elasticsearch + - r4.4xlarge.elasticsearch + - r4.8xlarge.elasticsearch + - r4.16xlarge.elasticsearch + - m3.medium.elasticsearch + - m3.large.elasticsearch + - m3.xlarge.elasticsearch + - m3.2xlarge.elasticsearch + - r3.large.elasticsearch + - r3.xlarge.elasticsearch + - r3.2xlarge.elasticsearch + - r3.4xlarge.elasticsearch + - r3.8xlarge.elasticsearch + ElasticsearchDataInstanceType: + Description: Instance type for data nodes. + Type: String + Default: r5.2xlarge.elasticsearch + AllowedValues: + - r5.large.elasticsearch + - r5.xlarge.elasticsearch + - r5.2xlarge.elasticsearch + - r5.4xlarge.elasticsearch + - r5.12xlarge.elasticsearch + - t2.small.elasticsearch + - t2.medium.elasticsearch + - c4.large.elasticsearch + - c4.xlarge.elasticsearch + - c4.2xlarge.elasticsearch + - c4.4xlarge.elasticsearch + - c4.8xlarge.elasticsearch + - i2.xlarge.elasticsearch + - i2.2xlarge.elasticsearch + - m4.large.elasticsearch + - m4.xlarge.elasticsearch + - m4.2xlarge.elasticsearch + - m4.4xlarge.elasticsearch + - m4.10xlarge.elasticsearch + - r4.large.elasticsearch + - r4.xlarge.elasticsearch + - r4.2xlarge.elasticsearch + - r4.4xlarge.elasticsearch + - r4.8xlarge.elasticsearch + - r4.16xlarge.elasticsearch + - m3.medium.elasticsearch + - m3.large.elasticsearch + - m3.xlarge.elasticsearch + - m3.2xlarge.elasticsearch + - r3.large.elasticsearch + - r3.xlarge.elasticsearch + - r3.2xlarge.elasticsearch + - r3.4xlarge.elasticsearch + - r3.8xlarge.elasticsearch + NumberOfMasterNodes: + Description: How many dedicated master nodes you want to have. 3 is recommended. + Type: Number + Default: 3 + AllowedValues: + - 3 + - 5 + NumberOfDataNodes: + Description: How many data nodes you want to have. Multiples of your number of availability zones (2) is recommended. + Type: Number + Default: 2 + MinValue: 1 + MaxValue: 20 + # CustomEndpoint: + # Description: Name for custom endpoint + # Type: string + CustomEndpointEnabled: + Type: String + AllowedValues: ['true', 'false'] + Default: 'false' + EnforceHTTPS: + Type: String + AllowedValues: ['true', 'false'] + Default: 'false' + ESPortHTTP: + Type: String + Default: '80' + ESPortHTTPS: + Type: String + Default: '443' + TLSSecurityPolicy: + Type: String + AllowedValues: ['true', 'false'] + Default: 'false' + # ElasticsearchName: + # Description: The name of the AWS Elasticsearch Service deployment. + # Type: String + # ConstraintDescription: Must be a valid AWS ES domain name prefix. The name must start with a + # lowercase letter and must be between 3 and 28 characters. Valid characters + # are a-z (lowercase only), 0-9, and - (hyphen). + # AllowedPattern: '[a-z][a-z0-9\\-]+' + +# RDS config UseRDS: Description: Deploy the RDS nested stack? Type: String @@ -155,12 +302,16 @@ Parameters: ALBAccessLogsBucket: Description: SaaS Boost bucket for Access logs Type: String + Default: sb-oct12-albaccesslogs-15ofqujyc1ley EventBus: Description: Optional. SaaS boost Metering and Billing Event Bridge Type: String + Default: sb-events-oct12-us-east-2 BillingPlan: Description: The billing plan to assign this tenant to after the stack completes Type: String + Default: plan_none +#Fsx for Windows UseFSx: Description: Deploy the FSX nested stack? Type: String @@ -177,7 +328,7 @@ Parameters: Type: Number FSxThroughputCapacity: Default: 8 - Description: Specify the throughput of the Amazon FSx file system. Valid values are 8 - 2048. + Description: Specify the throughput of the Amazon FSx file system. Valid values are 8 - 2048. Consider choosing a higher value for better performance. Type: Number FSxBackupRetention: @@ -197,6 +348,7 @@ Parameters: SSLCertArnParam: Description: The Parameter Store string parameter and version containing the certficate ARN to use Type: String + # Default: /saas-boost//SSL_CERT_ARN:1 Default: '' ## These params are here to read the image values from the public SSM. Leave the defaults WIN2019FULL: @@ -215,15 +367,19 @@ Conditions: HasDomainName: !Not [!Equals [!Ref DomainName, '']] ProvisionEFS: !Equals [!Ref UseEFS, 'true'] ProvisionRDS: !Equals [!Ref UseRDS, 'true'] + ProvisionES: !Equals [!Ref UseES, 'true'] WindowsOS: !Not [!Equals [!Ref DockerHostOS, 'LINUX']] HasCertificate: !Not [!Equals [!Ref SSLCertArnParam, '']] NoCertificate: !Not [Condition: HasCertificate] + ESEnforceHTTPS_false: !Equals [ !Ref "EnforceHTTPS", "false" ] + # FSX ProvisionFsx: !And - !Equals [!Ref UseFSx, 'true'] - Condition: WindowsOS IsWin2019Full: !Equals [WIN2019FULL, !Ref DockerHostOS] IsWin2019Core: !Equals [WIN2019CORE, !Ref DockerHostOS] IsWin1909Core: !Equals [WIN1909CORE, !Ref DockerHostOS] + Resources: VPC: Type: AWS::EC2::VPC @@ -586,7 +742,13 @@ Resources: - !Sub arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/saas-boost/${Environment}/DB_PORT - !Sub arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/saas-boost/${Environment}/DB_HOST - !Sub arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/saas-boost/${Environment}/DB_NAME - - !Sub arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/saas-boost/${Environment}/METRICS_STREAM + - !Sub arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/saas-boost/${Environment}METRICS_STREAM + # Makes more sense to add parameter to tenant rather than in saas boost environment + - !Sub arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/saas-boost/${Environment}/tenant/${TenantId}/ES_CLUSTER_NAME + - !Sub arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/saas-boost/${Environment}/tenant/${TenantId}/ES_CLUSTER_ENDPOINT + - !Sub arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/saas-boost/${Environment}/tenant/${TenantId}/ES_CLUSTER_PORT + - !Sub arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/saas-boost/${Environment}/tenant/${TenantId}/ES_CLUSTER_PORT_DEFAULT + ECSLogGroup: Type: AWS::Logs::LogGroup Properties: @@ -626,6 +788,7 @@ Resources: - events:PutEvents Resource: - !Sub arn:aws:events:${AWS::Region}:${AWS::AccountId}:event-bus/${EventBus} + #added to access config files for tenant. - Effect: Allow Action: - s3:GetObject @@ -672,9 +835,10 @@ Resources: awslogs-region: !Ref AWS::Region awslogs-stream-prefix: ecs Environment: - Fn::If: + !If - ProvisionRDS - - - Name: AWS_REGION + - + - Name: AWS_REGION Value: !Ref AWS::Region - Name: TENANT_ID Value: !Ref TenantId @@ -686,8 +850,29 @@ Resources: Value: !GetAtt rds.Outputs.RdsEndpoint - Name: DB_NAME Value: !Ref RDSDatabase - - - Name: SAAS_BOOST_BUCKET + - Name: SAAS_BOOST_BUCKET Value: !Ref SaaSBoostBucket + - !If + - ProvisionES + - + - Name: AWS_REGION + Value: !Ref AWS::Region + - Name: TENANT_ID + Value: !Ref TenantId + - Name: SAAS_BOOST_EVENT_BUS + Value: !Ref EventBus + - Name: METRICS_STREAM + Value: !Ref MetricsStream + - Name: ES_CLUSTER_NAME + Value: !GetAtt es.Outputs.ESClusterName + - Name: ES_CLUSTER_ENDPOINT + Value: !GetAtt es.Outputs.ESDomainEndpoint + - Name: ES_CLUSTER_PORT + Value: !GetAtt es.Outputs.ESClusterPort + - Name: ES_CLUSTER_PORT_DEFAULT + Value: !GetAtt es.Outputs.ESClusterPortDefault + - !Ref 'AWS::NoValue' + MountPoints: !If - ProvisionEFS @@ -706,21 +891,34 @@ Resources: - !Ref 'AWS::NoValue' - InitProcessEnabled: true Secrets: - Fn::If: + !If - ProvisionRDS - - - Name: DB_MASTER_USERNAME + - + - Name: DB_MASTER_USERNAME ValueFrom: !Sub arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/saas-boost/${Environment}/DB_MASTER_USERNAME - Name: DB_MASTER_PASSWORD ValueFrom: !Sub arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/saas-boost/${Environment}/DB_MASTER_PASSWORD - Name: DB_PORT ValueFrom: !Sub arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/saas-boost/${Environment}/DB_PORT - !Ref 'AWS::NoValue' + + # - !If + # - ProvisionES + # - + # - Name: ES_CLUSTER_NAME + # ValueFrom: !Sub arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/saas-boost/${Environment}/tenant/${TenantId}/ES_CLUSTER_NAME + # - Name: ES_CLUSTER_ENDPOINT + # ValueFrom: !Sub arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/saas-boost/${Environment}/tenant/${TenantId}/ES_CLUSTER_ENDPOINT + # - Name: ES_CLUSTER_PORT + # ValueFrom: !Sub arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/saas-boost/${Environment}/tenant/${TenantId}/ES_CLUSTER_PORT + # - !Ref 'AWS::NoValue' + Volumes: !If - ProvisionEFS - - Name: !GetAtt efs.Outputs.FileSystemId - EfsVolumeConfiguration: + EfsVolumeConfiguration: FileSystemId: !GetAtt efs.Outputs.FileSystemId - !If - ProvisionFsx @@ -1067,10 +1265,10 @@ Resources: Fn::Join: ['', ['tenant-', !Select [0, !Split ['-', !Ref TenantId]]]] HealthCheckProtocol: HTTP HealthCheckPath: !Ref ContainerHealthCheckPath - HealthCheckIntervalSeconds: 30 + HealthCheckIntervalSeconds: 300 HealthCheckTimeoutSeconds: 10 HealthyThresholdCount: 2 - UnhealthyThresholdCount: 2 + UnhealthyThresholdCount: 10 Port: !Ref ContainerPort Protocol: HTTP TargetType: !If [WindowsOS, instance, ip] @@ -1331,8 +1529,6 @@ Resources: fsx: Type: AWS::CloudFormation::Stack Condition: ProvisionFsx - Metadata: - ForceUpdate: !Ref LambdaSourceFolder DependsOn: - SubnetPublicA - SubnetPublicB @@ -1370,8 +1566,6 @@ Resources: efs: Type: AWS::CloudFormation::Stack Condition: ProvisionEFS - Metadata: - ForceUpdate: !Ref LambdaSourceFolder Properties: TemplateURL: !Sub https://${SaaSBoostBucket}.s3.amazonaws.com/tenant-onboarding-efs.yaml TimeoutInMinutes: 15 @@ -1384,11 +1578,45 @@ Resources: EncryptEFS: !Ref EncryptEFS EFSLifecyclePolicy: !Ref EFSLifecyclePolicy +# ElasticSearch Extension + es: + Type: AWS::CloudFormation::Stack + Condition: ProvisionES + DependsOn: + - SubnetPublicA + - SubnetPublicB + - SubnetPublicARouteTable + - SubnetPublicBRouteTable + - RoutePublic + - RouteTablePublic + - InternetGateway + - Subnet1RouteTableAssociation + - Subnet2RouteTableAssociation + - TenantRouteTablePrivate + - TenantTGWAttachment + - TenantRoute + - TenantVpcTgwAssociation + - UpdateRouteTable + Properties: + TemplateURL: !Sub https://${SaaSBoostBucket}.s3.amazonaws.com/tenant-onboarding-es.yaml + TimeoutInMinutes: 30 + Parameters: + TenantId: !Ref TenantId + VPC: !Ref VPC + SubnetPublicA: !Ref SubnetPublicA + # PrivateSubnetB: !Ref SubnetPrivateB + ElasticsearchVersion: !Ref ElasticsearchVersion + ECSSecurityGroup: !Ref ECSSecurityGroup + ElasticsearchDataInstanceType: !Ref ElasticsearchDataInstanceType + NumberOfDataNodes: !Ref NumberOfDataNodes + EnforceHTTPS: !Ref EnforceHTTPS + ESPort: !If [ESEnforceHTTPS_false, !Ref ESPortHTTPS, !Ref ESPortHTTP] + ElasticsearchName: + Fn::Join: ['', ['tenant-', !Select [0, !Split ['-', !Ref TenantId]], '-es-cluster']] + rds: Type: AWS::CloudFormation::Stack Condition: ProvisionRDS - Metadata: - ForceUpdate: !Ref LambdaSourceFolder # Have to make sure the entire network is still up when you delete # or we won't be able to call back to the CFN response URL DependsOn: