--- AWSTemplateFormatVersion: 2010-09-09 Parameters: Name: Type: String Description: > The name to prefix the secrets with. LambdaBucket: Type: String Default: aws-shibboleth-reference-architecture Description: > The S3 bucket from which to fetch the templates used by this stack. LambdaFolder: Type: String Default: '' Description: > The optional path to a folder in the S3 bucket from which to fetch the templates used by this stack. LDAPUrl: Type: String Default: ldaps://ad-ldap.example.com:636 Description: > The URL of the LDAP server. LDAPBaseDN: Type: String Default: CN=Users,DC=example,DC=org Description: > The base DN of the LDAP server. LDAPReadOnlyUser: Type: String Default: readonlyuser@example.com Description: > The username of a read-only user for connecting to the LDAP server. LDAPReadOnlyPassword: Type: String NoEcho: true Default: EnterYourPasswordHere Description: > The password of a read-only user for connecting to the LDAP server. SealerKeyVersionCount: Type: Number Default: 10 Description: The number of versions of the sealear key to support Resources: # Secret to hold the signing key and cert for shibboleth. SigningSecret: Type: AWS::SecretsManager::Secret Properties: Name: !Sub ${Name}-signing Description: "This is the signing key and certificate for shibboleth" # Secret to hold the backchannel key and cert for shibboleth. BackchannelSecret: Type: AWS::SecretsManager::Secret Properties: Name: !Sub ${Name}-backchannel Description: "This is the backchannel key and certificate for shibboleth" # Secret to hold the encryption key and cert for shibboleth. EncryptionSecret: Type: AWS::SecretsManager::Secret Properties: Name: !Sub ${Name}-encryption Description: "This is the encryption key and certificate for shibboleth" # Secret to hold the LDAP settings for shibboleth. LDAPSettingsSecret: Type: AWS::SecretsManager::Secret Properties: Name: !Sub ${Name}-ldap-settings Description: "This contains the LDAP settings for shibboleth" SecretString: !Sub '{"ldap_url":"${LDAPUrl}", "base_dn":"${LDAPBaseDN}", "read_only_user":"${LDAPReadOnlyUser}", "read_only_password":"${LDAPReadOnlyPassword}"}' #This is a Secret resource with a randomly generated password in its SecretString JSON. SealerKeySecret: Type: AWS::SecretsManager::Secret Properties: Name: !Sub ${Name}-sealer-key Description: "This is a secret for the Shibboleth sealer key" # This is a RotationSchedule resource. It configures rotation of the password for the referenced # secret using a Lambda rotation function. The first rotation happens immediately when # CloudFormation processes this resource type. All subsequent rotations are scheduled according to # the configured rotation rules. We explicitly depend on the SecretTargetAttachment resource to # ensure that the secret contains all the information necessary for rotation to succeed. SealerKeySecretRotationSchedule: Type: AWS::SecretsManager::RotationSchedule Properties: SecretId: !Ref SealerKeySecret RotationLambdaARN: !GetAtt SealerKeySecretRotationLambda.Arn RotationRules: AutomaticallyAfterDays: 1 #This is a Lambda Permission resource that grants Secrets Manager permission to invoke the function SealerKeySecretRotationLambdaInvokePermission: Type: AWS::Lambda::Permission DependsOn: SealerKeySecretRotationLambda Properties: FunctionName: !Sub ${Name}-Rotator Action: 'lambda:InvokeFunction' Principal: secretsmanager.amazonaws.com # This is an IAM Role resource. It gets attached to the Lambda rotation function and grants # permissions to the function to retrieve and update the secret as part of the rotation process. # It also includes the required KMS permissions and CloudWatch logging permissions. SealerKeySecretRotationLambdaExecutionRole: Type: AWS::IAM::Role Properties: RoleName: !Sub ${Name}-RotatorRole AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: "Allow" Principal: Service: - "lambda.amazonaws.com" Action: - "sts:AssumeRole" Policies: - PolicyName: !Sub ${Name}-RotationPolicy PolicyDocument: Version: "2012-10-17" Statement: - Effect: "Allow" Action: - "secretsmanager:DescribeSecret" - "secretsmanager:GetSecretValue" - "secretsmanager:PutSecretValue" - "secretsmanager:UpdateSecretVersionStage" Resource: !Sub 'arn:${AWS::Partition}:secretsmanager:${AWS::Region}:${AWS::AccountId}:secret:*' Condition: StringEquals: secretsmanager:resource/AllowRotationLambdaArn: !Sub 'arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:${Name}-Rotator' - Effect: "Allow" Action: - "secretsmanager:GetRandomPassword" Resource: "*" - Effect: "Allow" Action: - "logs:CreateLogGroup" - "logs:CreateLogStream" - "logs:PutLogEvents" Resource: "arn:aws:logs:*:*:*" - Effect: "Allow" Action: - "kms:Decrypt" - "kms:DescribeKey" - "kms:GenerateDataKey" Resource: "*" # This is a Lambda Function resource. We use this to create the rotation function that rotate # our secret. For details about rotation Lambdas, see: # https://docs.aws.amazon.com/secretsmanager/latest/userguide/rotating-secrets.html # This example assumes that the Lambda code is already present in an S3 bucket, and that it # is coded to rotate a MySQL database password SealerKeySecretRotationLambda: Type: AWS::Lambda::Function Properties: Runtime: python3.7 Role: !GetAtt SealerKeySecretRotationLambdaExecutionRole.Arn Handler: lambda_function.lambda_handler Description: 'This is a lambda to rotate sealer key' FunctionName: !Sub ${Name}-Rotator Environment: Variables: SECRETS_MANAGER_ENDPOINT: !Sub 'https://secretsmanager.${AWS::Region}.amazonaws.com' SEALER_KEY_VERSION_COUNT: !Ref SealerKeyVersionCount Code: S3Bucket: !Ref LambdaBucket S3Key: !Sub '${LambdaFolder}functions/packages/rotate_sealer_key_secret/rotate_sealer_key_sercret.zip' Outputs: SigningArn: Value: !Ref SigningSecret BackchannelArn: Value: !Ref BackchannelSecret EncryptionArn: Value: !Ref EncryptionSecret LDAPSettingsArn: Value: !Ref LDAPSettingsSecret SealerKeyArn: Value: !Ref SealerKeySecret