AWSTemplateFormatVersion: "2010-09-09" Description: "Deploys the Rafay System helm chart into an existing Kubernetes cluster (qs-1r9rrs0h6)" Metadata: QuickStartDocumentation: EntrypointName: "Launch into an existing EKS cluster" OptionalParameters: - BootstrapBucket - BootstrapKey AWS::CloudFormation::Interface: ParameterGroups: - Label: default: EKS cluster configuration Parameters: - EksClusterName - Label: default: Rafay cluster configuration Parameters: - Project - BootstrapBucket - BootstrapKey - Label: default: Register new Rafay account Parameters: - FirstName - LastName - OrganizationName - Email - Label: default: Use existing Rafay account Parameters: - ApiKey - ApiSecret - Label: default: AWS Quick Start configuration Parameters: - QSS3BucketName - QSS3KeyPrefix ParameterLabels: EksClusterName: default: EKS cluster name Project: default: Rafay project FirstName: default: First name LastName: default: Last name OrganizationName: default: Organization name Email: default: Email ApiKey: default: API key ApiSecret: default: API secret QSS3BucketName: default: Quick Start S3 bucket name QSS3KeyPrefix: default: Quick Start S3 key prefix BootstrapBucket: default: Bootstrap S3 bucket BootstrapKey: default: Bootstrap S3 key LintSpellExclude: - Rafay - Namespace Parameters: EksClusterName: Type: String Description: Name of the EKS cluster to deploy Rafay to. Project: Type: String Description: Rafay System project name Default: "defaultproject" BootstrapBucket: Type: String Description: "(Optional) S3 bucket to place the Rafay bootstrap .yaml file. If blank, the EKS Quick Start bucket is used." Default: "" BootstrapKey: Type: String Description: "(Optional) S3 key to place the Rafay bootstrap .yaml file. If blank, the key is rafay//cluster-bootstrap.yaml." Default: "" ApiKey: Type: String Description: Required if using an existing Rafay account. Default: "" ApiSecret: Type: String Description: Required if using an existing Rafay account. Default: "" NoEcho: true FirstName: Type: String Description: Required if registering a new Rafay account. Default: "" LastName: Type: String Description: Required if registering a new Rafay account. Default: "" OrganizationName: Type: String Description: Required if registering a new Rafay account. Default: "" Email: Type: String Description: Required if registering a new Rafay account. Default: "" QSS3BucketName: AllowedPattern: ^[0-9a-zA-Z]+([0-9a-zA-Z-]*[0-9a-zA-Z])*$ ConstraintDescription: Quick Start bucket name can include numbers, lowercase letters, uppercase letters, and hyphens (-). It cannot start or end with a hyphen (-). Default: aws-quickstart Description: S3 bucket name for Quick Start assets. This string can include numbers, lowercase letters, uppercase letters, and hyphens (-). It cannot start or end with a hyphen (-). Type: String QSS3KeyPrefix: AllowedPattern: ^[0-9a-zA-Z-/.]*$ ConstraintDescription: Quick Start key prefix can include numbers, lowercase letters, uppercase letters, hyphens (-), periods (.), and forward slashes (/). Default: quickstart-amazon-eks/submodules/quickstart-eks-rafay/ Description: S3 key prefix for the Quick Start assets. This string can include numbers, lowercase letters, uppercase letters, hyphens (-), periods (.), and forward slashes (/). Type: String Conditions: RegisterNewAccount: !Equals [!Ref ApiKey, ""] UsingDefaultBucket: !Equals [!Ref QSS3BucketName, 'aws-quickstart'] CustomBootstrapBucket: !Not [!Equals [!Ref BootstrapBucket, ""]] CustomBootstrapKey: !Not [!Equals [!Ref BootstrapKey, ""]] Mappings: Config: Prefix: { Value: 'eks-quickstart' } Resources: RafayCreateCluster: Type: "Custom::RafayCluster" Properties: ServiceToken: !GetAtt RafayCreateClusterFunction.Arn RAFAY_CLUSTER_NAME: !Sub '${EksClusterName}-${AWS::Region}-${AWS::AccountId}' RAFAY_PROJECT: !Ref Project RAFAY_API_KEY: !If [RegisterNewAccount, !GetAtt RafayCreateOrg.rafay_api_key, !Ref ApiKey] RAFAY_API_SECRET: !If [RegisterNewAccount, !GetAtt RafayCreateOrg.rafay_secret_key, !Ref ApiSecret] s3_bucket: !If - CustomBootstrapBucket - !Ref BootstrapBucket - !Sub ['${Prefix}-lambdazips-${AWS::Region}-${AWS::AccountId}', {Prefix: !FindInMap [Config, Prefix, Value]}] s3_key: !If - CustomBootstrapKey - !Ref BootstrapKey - !Sub "rafay/${EksClusterName}/cluster-bootstrap.yaml" RafayCreateOrg: Type: "Custom::RafayOrg" Condition: RegisterNewAccount Properties: ServiceToken: !GetAtt RafayCreateOrgFunction.Arn first_name: !Ref FirstName last_name: !Ref LastName organization_name: !Ref OrganizationName email: !Ref Email RafayBootStrap: Type: "AWSQS::Kubernetes::Resource" Properties: ClusterName: !Ref EksClusterName Url: !Sub 's3://${RafayCreateCluster.rafay_s3_bucket}/${RafayCreateCluster.rafay_s3_key}' Namespace: rafay-system CopyZips: Type: Custom::CopyZips Properties: ServiceToken: !Sub ['arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:${Prefix}-CopyZips', {Prefix: !FindInMap [Config, Prefix, Value]}] DestBucket: !Sub ['${Prefix}-lambdazips-${AWS::Region}-${AWS::AccountId}', {Prefix: !FindInMap [Config, Prefix, Value]}] SourceBucket: !If [UsingDefaultBucket, !Sub '${QSS3BucketName}-${AWS::Region}', !Ref QSS3BucketName] Prefix: !Ref 'QSS3KeyPrefix' Objects: - functions/packages/aws_qs_create_cluster/aws_qs_create_cluster.zip - functions/packages/aws_qs_create_org/aws_qs_create_org.zip - functions/packages/rctlLayer/lambda.zip RctlLayer: DependsOn: CopyZips Type: AWS::Lambda::LayerVersion Properties: LayerName: !Sub ['${Prefix}-Rafay-Rctl-${EksClusterName}', {Prefix: !FindInMap [Config, Prefix, Value]}] CompatibleRuntimes: - python3.6 - python3.7 Content: S3Bucket: !Sub ['${Prefix}-lambdazips-${AWS::Region}-${AWS::AccountId}', {Prefix: !FindInMap [Config, Prefix, Value]}] S3Key: !Sub '${QSS3KeyPrefix}functions/packages/rctlLayer/lambda.zip' RafayLambdaRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: lambda.amazonaws.com Action: sts:AssumeRole ManagedPolicyArns: - !Sub 'arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole' Policies: - PolicyName: 'rafay' PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: ["s3:PutObject", "s3:DeleteObject"] Resource: !Sub - "arn:${AWS::Partition}:s3:::${s3_bucket}/${s3_key}" - s3_bucket: !If - CustomBootstrapBucket - !Ref BootstrapBucket - !Sub ['${Prefix}-lambdazips-${AWS::Region}-${AWS::AccountId}', {Prefix: !FindInMap [Config, Prefix, Value]}] s3_key: !If - CustomBootstrapKey - !Ref BootstrapKey - !Sub "rafay/${EksClusterName}/cluster-bootstrap.yaml" - Effect: Allow Action: ["ssm:GetParameter"] Resource: !Sub 'arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:parameter/quickstart/rafay/*' RafayCreateClusterFunction: Type: AWS::Lambda::Function DependsOn: CopyZips Properties: Handler: aws_qs_create_cluster.lambda_handler MemorySize: 256 Role: !GetAtt RafayLambdaRole.Arn Runtime: python3.7 Timeout: 900 Layers: - !Ref GetCrhelperLayerArn - !Ref RctlLayer Code: S3Bucket: !Sub ['${Prefix}-lambdazips-${AWS::Region}-${AWS::AccountId}', {Prefix: !FindInMap [Config, Prefix, Value]}] S3Key: !Sub '${QSS3KeyPrefix}functions/packages/aws_qs_create_cluster/aws_qs_create_cluster.zip' RafayCreateOrgFunction: Type: AWS::Lambda::Function Condition: RegisterNewAccount DependsOn: CopyZips Properties: Handler: aws_qs_create_org.lambda_handler MemorySize: 256 Role: !GetAtt RafayLambdaRole.Arn Runtime: python3.7 Timeout: 900 Layers: - !Ref GetCrhelperLayerArn - !Ref RctlLayer Code: S3Bucket: !Sub [ '${Prefix}-lambdazips-${AWS::Region}-${AWS::AccountId}', { Prefix: !FindInMap [ Config, Prefix, Value ] } ] S3Key: !Sub '${QSS3KeyPrefix}functions/packages/aws_qs_create_org/aws_qs_create_org.zip' RafaySecret: Type: AWS::SecretsManager::Secret Condition: RegisterNewAccount Properties: Name: !Sub 'Rafay-api-key-${EksClusterName}' SecretString: !Sub '{ "ApiKey": "${RafayCreateOrg.rafay_api_key}", "SecretKey": "${RafayCreateOrg.rafay_secret_key}" }' GetCrhelperLayerArn: Type: Custom::CliQuery Properties: ServiceToken: !Sub ['arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:${Prefix}-ResourceReader', {Prefix: !FindInMap [Config, Prefix, Value]}] AwsCliCommand: !Sub - | lambda list-layer-versions --layer-name ${Prefix}-Crhelper --query 'max_by(LayerVersions, &Version)' - Prefix: !FindInMap [Config, Prefix, Value] IdField: 'LayerVersionArn' Outputs: BootstrapManifestUri: Value: !Sub 's3://${RafayCreateCluster.rafay_s3_bucket}/${RafayCreateCluster.rafay_s3_key}' RafayApiKey: Value: !If [RegisterNewAccount, !GetAtt RafayCreateOrg.rafay_api_key, !Ref ApiKey] # Validation rules are in-progress Rules: AssertNewUser: RuleCondition: !And - !Not [!Equals [!Ref FirstName, '']] - !Not [!Equals [!Ref LastName, '']] - !Not [!Equals [!Ref OrganizationName, '']] - !Not [!Equals [!Ref Email, '']] Assertions: - Assert: !Equals [!Ref ApiKey, ''] AssertDescription: 'When creating a new Rafay account "API key" must be blank' - Assert: !Equals [!Ref ApiSecret, ''] AssertDescription: 'When creating a new Rafay account "API secret" must be blank' AssertExistingUser: RuleCondition: !And - !Not [!Equals [!Ref ApiKey, '']] - !Not [!Equals [!Ref ApiSecret, '']] Assertions: - Assert: !Equals [!Ref FirstName, ''] AssertDescription: 'When using an existing Rafay account "First name" must be blank' - Assert: !Equals [!Ref LastName, ''] AssertDescription: 'When using an existing Rafay account "Last name" must be blank' - Assert: !Equals [!Ref OrganizationName, ''] AssertDescription: 'When using an existing Rafay account "Organization name" must be blank' - Assert: !Equals [!Ref Email, ''] AssertDescription: 'When using an existing Rafay account "Email" must be blank' AssertUser: RuleCondition: !Not [!Equals [!Ref EksClusterName, '']] Assertions: - Assert: !Or - !And - !Not [!Equals [!Ref ApiKey, '']] - !Not [!Equals [!Ref ApiSecret, '']] - !And - !Not [!Equals [!Ref FirstName, '']] - !Not [!Equals [!Ref LastName, '']] - !Not [!Equals [!Ref OrganizationName, '']] - !Not [!Equals [!Ref Email, '']] AssertDescription: 'Either "Register new Rafay account" or "Use existing Rafay account" sections must be completed'