# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: MIT-0 AWSTemplateFormatVersion: '2010-09-09' Metadata: License: MIT-0 AWS::CloudFormation::Interface: ParameterGroups: - Label: default: OpenShift type - ROSA or OCP Parameters: - 00OpenShiftType - Label: default: IBM Entitlement Key Parameters: - 07IBMEntitlementKey - Label: default: Deploy a VPC stack with Public and Private subnets to host the Private OCP cluster. Parameters: - 01VpcCIDR - 01PublicSubnet1CIDR - 01PublicSubnet2CIDR - 01PublicSubnet3CIDR - 01PrivateSubnet1CIDR - 01PrivateSubnet2CIDR - 01PrivateSubnet3CIDR - Label: default: Define a Private Hosted Zone that will host the OCP cluster Parameters: - 02DeployPHZ - 03PrivateHostedZone - Label: default: Parameters to create a Seed and Bastion Host required to start installation Parameters: #- 04DeploySeedBastion - 05SeedInstanceType - 05OCPClusterName - 05OCPClusterVersion - 05ClusterSize - Label: default: Define an RDS SQL Server instance if you would like SQL Parameters: - 06DeployRDS - 06RDSDBInstanceClass - 06RDSAllocatedStorage - 06RDSDBInstanceIdentifier - 06RDSBackupRetentionPeriod - 06RDSMasterUsername - 06MultiAZ - Label: default: Define an DocDB cluster with 3 instances for the MAS Install Parameters: - 08DeployDocDB - 08DBClusterName - 08MasterUser - 08DBInstanceClass - Label: default: Enter the ROSA Machine, Service, Pod CIDR and host prefix Parameters: - 01ROSAMachineCIDR - 01ROSAServiceCIDR - 01ROSAPodCIDR - 01ROSAHostPrefix Description: 'CFN Template to create a Seed EC2 instance with ansible collection installed' Conditions: IsROSA: !Equals [!Ref 00OpenShiftType, 'ROSA'] IsOCP: !Equals [!Ref 00OpenShiftType, 'OCP'] IsDeployPHZ: !Equals [!Ref 02DeployPHZ, 'true'] #IsDeploySeedBastion: !Equals [!Ref 04DeploySeedBastion, 'true'] IsDeployRDS: !Equals [!Ref 06DeployRDS, 'true'] IsIBMEntitlementKeyPresent: !Not [!Equals [!Ref 07IBMEntitlementKey, ""]] IsDeployDocDB: !Equals [!Ref 08DeployDocDB, 'true'] Parameters: 00OpenShiftType: Description: OpenShift Cluster type - OCP or ROSA ? Type: String Default: 'OCP' AllowedValues: - 'ROSA' - 'OCP' 01VpcCIDR: Description: Enter the IP range (CIDR notation) for VPC Type: String Default: 10.0.0.0/16 01PublicSubnet1CIDR: Description: Enter the IP range (CIDR notation) for the public subnet in AZ A Type: String Default: 10.0.0.0/19 01PublicSubnet2CIDR: Description: Enter the IP range (CIDR notation) for the public subnet in AZ B Type: String Default: 10.0.32.0/19 01PublicSubnet3CIDR: Description: Enter the IP range (CIDR notation) for the public subnet in AZ C Type: String Default: 10.0.64.0/19 01PrivateSubnet1CIDR: Description: Enter the IP range (CIDR notation) for the private subnet in AZ A Type: String Default: 10.0.128.0/19 01PrivateSubnet2CIDR: Description: Enter the IP range (CIDR notation) for the private subnet in AZ B Type: String Default: 10.0.160.0/19 01PrivateSubnet3CIDR: Description: Enter the IP range (CIDR notation) for the private subnet in AZ C Type: String Default: 10.0.192.0/19 01ROSAMachineCIDR: Description: Enter the Machine CIDR Type: String Default: 10.0.0.0/16 01ROSAServiceCIDR: Description: Enter the Service CIDR Type: String Default: 172.30.0.0/16 01ROSAPodCIDR: Description: Enter the POD CIDR Type: String Default: 10.128.0.0/14 01ROSAHostPrefix: Description: Enter the Host prefix Type: Number Default: 23 02DeployPHZ: Description: Do you want to create the PHZ and associate it with the VPC that will be created ? Type: String Default: 'true' AllowedValues: - 'true' - 'false' 03PrivateHostedZone: Description: Enter the DNS name for PHZ Type: String Default: example.com # 04DeploySeedBastion: # Description: Do you want to create the SeedInstance and the Bastion in the existing VPC ? # Type: String # Default: 'true' # AllowedValues: # - 'true' # - 'false' 05SeedInstanceType: Description: Seed EC2 instance type Type: String Default: t2.large ConstraintDescription: must be a valid EC2 instance type. 05OCPClusterName: Type: String Description: Name of the OCP Cluster that will be created Default: 'masocp' 05OCPClusterVersion: Type: String Description: Version of the OCP Cluster Default: '4.12.18' 05ClusterSize: Type: String Description: Cluster size - small, medium or large. Check the Cluster Size section at https://www.ibm.com/docs/en/mas87/8.7.0?topic=installation-considerations#Cluster%20Size Default: 'small' AllowedValues: - 'small' - 'medium' - 'large' 06DeployRDS: Description: Do you want to create the RDS instance Type: String Default: 'true' AllowedValues: - 'true' - 'false' 06RDSDBInstanceClass: Default: db.t3.xlarge Description: Select DB instance. Burstable classes (includes t classes). Standard classes (includes m classes). Memory optimized classes (includes r and x classes) Type: String AllowedValues: - db.t3.xlarge - db.t3.2xlarge - db.m6i.large - db.m6i.xlarge - db.m6i.2xlarge - db.m6i.4xlarge - db.m6i.8xlarge - db.m5.large - db.m5.xlarge - db.m5.2xlarge - db.m5.4xlarge - db.r5.large - db.r5.xlarge - db.r5.2xlarge - db.r5.4xlarge - db.r5.8xlarge - db.r5.12large 06RDSAllocatedStorage: Default: 30 Description: The size of the Deep Security database (Gb) Type: Number MinValue: 20 MaxValue: 16384 ConstraintDescription: must be between 20 and 16Tb. 06RDSDBInstanceIdentifier: Default: masonaws Description: A name for the DB instance Type: String 06RDSBackupRetentionPeriod: Default: 1 Description: Days to keep automatic RDS backups (0-35) Type: Number MinValue: 0 MaxValue: 35 ConstraintDescription: must be between 0 and 35 days. 06RDSMasterUsername: Default: admin Description: Admin account username to be used for the database instance Type: String MinLength: 1 MaxLength: 16 AllowedPattern: '[a-zA-Z][a-zA-Z0-9]*' ConstraintDescription: must begin with a letter and contain only alphanumeric characters. 06MultiAZ: Description: Use Multi-AZ or SQL Mirroring Option Group for RDS Instance Type: String Default: 'false' AllowedValues: - 'true' - 'false' 07IBMEntitlementKey: Type: String NoEcho: true Default: 'REPLACE ME' Description: IBM Entitlement Key to access the IBM Maximo Application images - REPLACE ME 08DeployDocDB: Description: Do you want to create the DocDB as part of the MAS install Type: String Default: 'true' AllowedValues: - 'true' - 'false' 08DBClusterName: Default: docdb-mas Description: "Cluster name" Type: "String" MinLength: "1" MaxLength: "64" AllowedPattern : "[a-zA-Z][a-zA-Z0-9]*(-[a-zA-Z0-9]+)*" ConstraintDescription: "Must begin with a letter and contain only alphanumeric characters." 08MasterUser: Default: "docdbadmin" Description: "The database admin account username" Type: "String" MinLength: "1" MaxLength: "16" AllowedPattern: "[a-zA-Z][a-zA-Z0-9]*" ConstraintDescription: "Must begin with a letter and contain only alphanumeric characters." 08DBInstanceClass: Description: "Instance class. Please refer to: https://docs.aws.amazon.com/documentdb/latest/developerguide/db-instance-classes.html#db-instance-classes-by-region" Default: "db.t3.medium" Type: "String" AllowedValues: - db.t3.medium - db.r5.large - db.r5.xlarge - db.r5.2xlarge - db.r5.4xlarge - db.r5.12xlarge - db.r5.24xlarge ConstraintDescription: "Instance type must be of the ones supported for the region. Please refer to: https://docs.aws.amazon.com/documentdb/latest/developerguide/db-instance-classes.html#db-instance-classes-by-region" Resources: IBMEntitlementKeySecret: Condition: IsIBMEntitlementKeyPresent Type: AWS::SecretsManager::Secret Properties: Description: IBM Entitlement Key AWS Secret Manager secret SecretString: !Ref 07IBMEntitlementKey 05PreReqS3Bucket: Type: AWS::S3::Bucket Description: S3 bucket name of the pre-requisite bucket. Naming convention masocp-license-{AWS.Region}-{AWS.AccountNumber} Properties: BucketName: !Sub masocp-license-${AWS::Region}-${AWS::AccountId} MASOCPKeyPair: Type: 'AWS::EC2::KeyPair' Properties: KeyName: MASOCPKeyPair KMSKey: Type: AWS::KMS::Key Properties: Description: KMS Key to encrypt RDS DB and Secret Manager secrets EnableKeyRotation: true KeyPolicy: Version: 2012-10-17 Id: rds-key-poicy Statement: - Sid: Enable IAM User Permissions Effect: Allow Principal: AWS: !Join - '' - - 'arn:' - !Ref 'AWS::Partition' - ':iam::' - !Ref 'AWS::AccountId' - ':root' Action: 'kms:*' Resource: '*' DeadLetterSNSTopic: Type: AWS::SNS::Topic Properties: KmsMasterKeyId: !Ref KMSKey MSSQLSecret: Type: AWS::SecretsManager::Secret Properties: KmsKeyId: !Ref KMSKey GenerateSecretString: SecretStringTemplate: !Join [ '', [ '{"username": "', !Ref 06RDSMasterUsername, '"}' ] ] GenerateStringKey: 'password' PasswordLength: 16 ExcludeCharacters: '"@/\' ## Stack to create the VPC resources required for an OCP Cluster ExistingVPCStack: Type: AWS::CloudFormation::Stack Properties: TemplateURL: https://ee-assets-prod-us-east-1.s3.amazonaws.com/modules/59674cf6b6e04aa19cd95f91d5d0dca7/v1/ocp_existing_vpc_setup.yaml Parameters: VpcCIDR: !Ref 01VpcCIDR PublicSubnet1CIDR: !Ref 01PublicSubnet1CIDR PublicSubnet2CIDR: !Ref 01PublicSubnet2CIDR PublicSubnet3CIDR: !Ref 01PublicSubnet3CIDR PrivateSubnet1CIDR: !Ref 01PrivateSubnet1CIDR PrivateSubnet2CIDR: !Ref 01PrivateSubnet2CIDR PrivateSubnet3CIDR: !Ref 01PrivateSubnet3CIDR UniqueStr: !Ref AWS::StackId OCPClusterName: !Ref 05OCPClusterName ## Stack to create a Private Hosted Zone and associate with the VPC PHZStack: Condition: IsDeployPHZ Type: AWS::CloudFormation::Stack Properties: TemplateURL: https://ee-assets-prod-us-east-1.s3.amazonaws.com/modules/59674cf6b6e04aa19cd95f91d5d0dca7/v1/ocp_phz_create.yaml Parameters: PrivateHostedZone: !Ref 03PrivateHostedZone openshiftVPCId: Fn::GetAtt: - ExistingVPCStack - Outputs.outputVPC ## Stack to create an optional RDS Instance RDSStack: Condition: IsDeployRDS Type: AWS::CloudFormation::Stack Properties: TemplateURL: https://ee-assets-prod-us-east-1.s3.amazonaws.com/modules/59674cf6b6e04aa19cd95f91d5d0dca7/v1/ocp_rds_optional_template.yaml Parameters: RDSDBInstanceClass: !Ref 06RDSDBInstanceClass RDSAllocatedStorage: !Ref 06RDSAllocatedStorage RDSDBInstanceIdentifier: !Ref 06RDSDBInstanceIdentifier RDSBackupRetentionPeriod: !Ref 06RDSBackupRetentionPeriod RDSMasterUsername: !Ref 06RDSMasterUsername MSSQLSecret: !Ref MSSQLSecret RDSPrivateSubnetId1: Fn::GetAtt: - ExistingVPCStack - Outputs.outputPrivateSubnet1 RDSPrivateSubnetId2: Fn::GetAtt: - ExistingVPCStack - Outputs.outputPrivateSubnet2 RDSPrivateSubnetId3: Fn::GetAtt: - ExistingVPCStack - Outputs.outputPrivateSubnet3 RDSPrivateSubnet1CIDR: !Ref 01PrivateSubnet1CIDR RDSPrivateSubnet2CIDR: !Ref 01PrivateSubnet2CIDR RDSPrivateSubnet3CIDR: !Ref 01PrivateSubnet3CIDR BastionSecurityGroupId: Fn::GetAtt: - SeedBastionStack - Outputs.BastionSecurityGroupId UniqueStr: !Ref AWS::StackId VpcId: Fn::GetAtt: - ExistingVPCStack - Outputs.outputVPC RDSKMSKey: !GetAtt KMSKey.Arn MultiAZ: !Ref 06MultiAZ OCPClusterName: !Ref 05OCPClusterName ## Stack to create a Bastion host and Seed Instance. Windows Bastion will be created in the Public Subnet and Seed Instance in a Private Subnet SeedBastionStack: ## DependsOn: PHZStack #Condition: IsDeploySeedBastion Type: AWS::CloudFormation::Stack Properties: TemplateURL: https://ee-assets-prod-us-east-1.s3.amazonaws.com/modules/59674cf6b6e04aa19cd95f91d5d0dca7/v1/ocp_seed_bastion_instance.yaml Parameters: OpenShiftType: !Ref 00OpenShiftType KeyName: !Ref MASOCPKeyPair InstanceType: !Ref 05SeedInstanceType PreReqS3Bucket: !Ref 05PreReqS3Bucket OCPClusterName: !Ref 05OCPClusterName OCPClusterVersion: !Ref 05OCPClusterVersion ClusterSize: !Ref 05ClusterSize SeedSubnetId: Fn::GetAtt: - ExistingVPCStack - Outputs.outputPrivateSubnetSeedInstance BastionSubnetId: Fn::GetAtt: - ExistingVPCStack - Outputs.outputPublicSubnetBastionInstance VpcId: Fn::GetAtt: - ExistingVPCStack - Outputs.outputVPC VpcCIDR: !Ref 01VpcCIDR PrivateSubnet1: Fn::GetAtt: - ExistingVPCStack - Outputs.outputPrivateSubnet1 PrivateSubnet2: Fn::GetAtt: - ExistingVPCStack - Outputs.outputPrivateSubnet2 PrivateSubnet3: Fn::GetAtt: - ExistingVPCStack - Outputs.outputPrivateSubnet3 HostedZoneID: !If [ IsDeployPHZ, !GetAtt PHZStack.Outputs.PHZId, 'rosa' ] BaseDomain: !Ref 03PrivateHostedZone KMSKey: !GetAtt KMSKey.Arn DeadLetterSNSTopic: !Ref DeadLetterSNSTopic DocDBMongoStack: ## DependsOn: PHZStack Condition: IsDeployDocDB Type: AWS::CloudFormation::Stack Properties: TemplateURL: https://ee-assets-prod-us-east-1.s3.amazonaws.com/modules/59674cf6b6e04aa19cd95f91d5d0dca7/v1/ocp_document_db.yaml Parameters: DBClusterName: !Ref 08DBClusterName MasterUser: !Ref 08MasterUser DBInstanceClass: !Ref 08DBInstanceClass VpcId: Fn::GetAtt: - ExistingVPCStack - Outputs.outputVPC VpcCIDR: !Ref 01VpcCIDR PrivateSubnet1: Fn::GetAtt: - ExistingVPCStack - Outputs.outputPrivateSubnet1 PrivateSubnet2: Fn::GetAtt: - ExistingVPCStack - Outputs.outputPrivateSubnet2 PrivateSubnet3: Fn::GetAtt: - ExistingVPCStack - Outputs.outputPrivateSubnet3 KMSKey: !GetAtt KMSKey.Arn Outputs: 01DeployClusterCommand: Description: Command to deploy an OCP cluster Condition: IsOCP Value: !Join [ "", [ '/root/ibm-mas-on-aws/scripts/deploy_cluster.sh "', !Ref 05PreReqS3Bucket, '" "', !Ref 05OCPClusterName , '" "', !Ref 03PrivateHostedZone, '"' ]] 01DeployROSAClusterCommand: Description: Command to deploy a ROSA cluster Condition: IsROSA Value: !Join [ "", [ 'rosa create account-roles --region ', !Ref AWS::Region, ' --mode auto --yes && rosa create cluster --cluster-name ',!Ref 05OCPClusterName,' --sts --operator-roles-prefix ',!Ref 05OCPClusterName,'-', !Select [3 , !Split ['-', !Select [2, !Split ['/', !Ref AWS::StackId ] ] ] ] , ' --multi-az --region ', !Ref AWS::Region, ' --version ' , !Ref 05OCPClusterVersion, ' --enable-autoscaling --min-replicas 3 --max-replicas 3 --compute-machine-type m6i.2xlarge --machine-cidr ', !Ref 01ROSAMachineCIDR, ' --service-cidr ', !Ref 01ROSAServiceCIDR, ' --pod-cidr ', !Ref 01ROSAPodCIDR, ' --host-prefix ', !Ref 01ROSAHostPrefix, ' --subnet-ids ', !GetAtt ExistingVPCStack.Outputs.outputPrivatePublicSubnetIds, ' --mode auto --yes ']] 01CreateROSAClusterAdmin: Description: Command to create a cluster admin user to login to ROSA cluster Condition: IsROSA Value: !Join [ "", [ 'rosa create admin --cluster=',!Ref 05OCPClusterName,' --region ', !Ref AWS::Region]] 02CreateEFSCommand: Description: Command to create an EFS Value: !Join [ "", [ '/root/ibm-mas-on-aws/scripts/create_efs_rwx_sc.sh "', !Ref 05OCPClusterName , '" ' ]] 03FinishPendingOCUpdatesCommand: Condition: IsOCP Description: Command to finish the pending oc updates Value: !Join [ "", [ '/root/ibm-mas-on-aws/scripts/pending_oc_updates.sh "', !Ref 05PreReqS3Bucket, '" "', !Ref 05OCPClusterName , '" "', !Ref 03PrivateHostedZone, '"' ]] 04DeployMASOperatorCommand: Condition: IsDeployDocDB Description: Command to Deploy the MAS Operator on OpenShift Cluster Value: !Join [ "", [ '/root/ibm-mas-on-aws/scripts/deploy_mascore.sh "', !Ref 05PreReqS3Bucket, '" "', !Ref 05OCPClusterName , '" "', !Ref IBMEntitlementKeySecret,'" "',!GetAtt DocDBMongoStack.Outputs.MongoHosts, '" "',!GetAtt DocDBMongoStack.Outputs.DocDBSecretARN,'"' ]] 05GenMASJDBCCommand: Condition: IsDeployRDS Description: Command to generate MAS JDBC config. If deploying RDS SQL using CFN stack, then get the JDBC Connection String from RDS Stack output Value: !Join [ "", [ '/root/ibm-mas-on-aws/scripts/gen_mas_jdbc.sh maximo "MAS_JDBC_PASSWORD" "',!GetAtt RDSStack.Outputs.JDBCConnectionString, '"' ]] 06AddMaximoManageCommand: Description: Command to deploy Maximo Manage on MAS. Value: !Join [ "", [ '/root/ibm-mas-on-aws/scripts/add_maximo_manage.sh "', !Ref IBMEntitlementKeySecret,'"', '' ]] 07JDBCConnectionString: Condition: IsDeployRDS Description: JDBC connection string to connect Maximo Manage to RDS. Remember to create a Database after the DB instance is ready Value: Fn::GetAtt: - RDSStack - Outputs.JDBCConnectionString 08PHZId: Description: Hosted Zone ID for the hosted zone created for the DNS Name Condition: IsDeployPHZ Value: Fn::GetAtt: - PHZStack - Outputs.PHZId 0901outputVPC: Description: VPCId created Value: Fn::GetAtt: - ExistingVPCStack - Outputs.outputVPC Export: Name: VPCId 0902outputRedshiftPrivateSubnet1: Description: Private subnetID 1 created for Redshift subnet group Value: Fn::GetAtt: - ExistingVPCStack - Outputs.outputPrivateSubnet1 Export: Name: RedshiftSubnetGroupPrivateSubnet1 0903outputRedshiftPrivateSubnet2: Description: Private subnetID 2 created for Redshift subnet group Value: Fn::GetAtt: - ExistingVPCStack - Outputs.outputPrivateSubnet2 Export: Name: RedshiftSubnetGroupPrivateSubnet2 0904outputRedshiftPrivateSubnet3: Description: Private subnetID 3 created for Redshift subnet group Value: Fn::GetAtt: - ExistingVPCStack - Outputs.outputPrivateSubnet3 Export: Name: RedshiftSubnetGroupPrivateSubnet3 0905outputRDSSecurityGroupId: Description: Security Group ID for RDS Condition: IsDeployRDS Value: Fn::GetAtt: - RDSStack - Outputs.OCPRDSDBVPCSecurityGroupId Export: Name: RedshiftRDSSGId 0906RDSJDBCEndpoint: Description: JDBC Endpoint for RDS Condition: IsDeployRDS Value: Fn::GetAtt: - RDSStack - Outputs.JDBCEndpoint Export: Name: RDSJDBCEndpoint 0907outputRDSCredsSecret: Description: Secret ARN for the RDS credentials Value: !Ref MSSQLSecret Export: Name: RDSCredsSecretARN 10outputPublicSubnetBastionInstance: Description: Public subnetID created for Bastion Value: Fn::GetAtt: - ExistingVPCStack - Outputs.outputPublicSubnetBastionInstance 1101outputPrivateSubnetSeedInstance: Description: Private subnetID created for Seed Value: Fn::GetAtt: - ExistingVPCStack - Outputs.outputPrivateSubnetSeedInstance Export: Name: SeedSubnetId 1102outputSeedSecurityGroupId: Description: Seed Security group Id Value: Fn::GetAtt: - SeedBastionStack - Outputs.SeedSecurityGroupId Export: Name: SeedSecurityGroupId 1103outputDeadLetterSNSTopic: Description: Lambda Dead Letter SNS Topic Value: !Ref DeadLetterSNSTopic Export: Name: LambdaDeadLetterSNSTopic 1104outputKMSKey: Description: KMS Key that will be used to encrypt Lambda code Value: !GetAtt KMSKey.Arn Export: Name: LambdaKMSKey