From 34bee9d75d2f5aab11c34b180705bc526a94cf17 Mon Sep 17 00:00:00 2001 From: Chris Pates Date: Wed, 1 Nov 2023 19:21:16 +0000 Subject: [PATCH] Update template.yaml - Improved parameter validation - enhanced descriptions including whether optional. --- template.yaml | 162 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 112 insertions(+), 50 deletions(-) diff --git a/template.yaml b/template.yaml index 35045550..ad98e635 100644 --- a/template.yaml +++ b/template.yaml @@ -5,9 +5,9 @@ Metadata: AWS::CloudFormation::Interface: ParameterGroups: - Label: - default: Select whether to create secrets, or use existing secrets + default: Which pattern are we deploying? The app with secrets, the app but using existing secrets, or just the secrets. Parameters: - - ValuesOrArns + - DeployPattern - Label: default: AWS IAM Identity Center (Successor to AWS Single Sign-On) Parameters: @@ -57,25 +57,34 @@ Metadata: SourceCodeUrl: https://github.com/awslabs/ssosync/tree/1.0.0-rc.10 Parameters: - ValuesOrArns: + DeployPattern: Type: String - Description: Decide whether to provide values for the secrets or an arn for an existing secret, that contains the value. + Description: | + Full (default); you provide the values for the secrets and the everything is setup. + App only (local secrets); Deploys the app and grants access to the secrets you provide the arn for. + App only (remote secrets); Deploys the app and you have to grant to the secrets you provide the arn for. + Secret-only; Does not deploy the app just creates the secrets. AllowedValues: - - secrets - - values - Default: values + - Full + - App only (local secrets) + - App only (remote secrets) + - Secrets only + Default: Full FunctionName: Type: String - Description: Specify the Function you want to us for this deployment, leave empty for default behaviour. + Description: | + [optional] Specify the Function you want to us for this deployment. Recommended if using App only (remote secrets), leave empty for default behaviour. AllowedPattern: '(?!.*\s)|[a-zA-Z0-9-_]{1,140}' ScheduleExpression: Type: String - Description: Schedule for trigger the execution of ssosync (see CloudWatch schedule expressions) + Description: | + [optional] Schedule for trigger the execution of ssosync (see CloudWatch schedule expressions), leave empty if you want to trigger execution by another method such as AWS CodePipeline. Default: rate(15 minutes) AllowedPattern: '(?!.*\s)|rate\(\d{1,3} (minutes|hours|days)\)|(cron\((([0-9]|[1-5][0-9]|60)|\d\/([0-9]|[1-5][0-9]|60)|\*) (([0-9]|[1][0-9]|[2][0-3])|(\d\/([0-9]|[1][0-9]|[2][0-3]))|(([0-9]|[1][0-9]|[2][0-3])-([0-9]|[1][0-9]|[2][0-3]))|\*) (([1-9]|[1-2][0-9]|[3][0-1])|\d\/([1-9]|[1-2][0-9]|[3][0-1])|[1-5]W|L|\*|\?) (([1-9]|[1][1-2])|(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)|((JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV)-(FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC))|(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV)(,(FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)){0,11}|\d\/([0-9]|[1][0-2])|\?|\*) ((MON|TUE|WED|THU|FRI|SAT|SUN)|(MON|TUE|WED|THU|FRI|SAT)-(TUE|WED|THU|FRI|SAT|SUN)|(MON|TUE|WED|THU|FRI|SAT)(,(TUE|WED|THU|FRI|SAT|SUN)){0,6}|[1-7]L|[1-7]#[1-5]|\?|\*) ((19[7-9][0-9]|2[0-1]\d\d)|(19[7-9][0-9]|2[0-1]\d\d)-(19[7-9][0-9]|2[0-1]\d\d)|(19[7-9][0-9]|2[0-1]\d\d)(,(19[7-9][0-9]|2[0-1]\d\d))*|\*)\))' LogLevel: Type: String - Description: Log level for Lambda function logging + Description: | + [required] Log level for Lambda function logging Default: warn AllowedValues: - panic @@ -87,83 +96,90 @@ Parameters: - trace LogFormat: Type: String - Description: Log format for Lambda function logging + Description: | + [required] Log format for Lambda function logging Default: json AllowedValues: - json - text TimeOut: Type: Number - Description: Timeout for the Lambda function + Description: | + [required] Timeout for the Lambda function Default: 300 MinValue: 1 MaxValue: 900 GoogleCredentials: Type: String - Description: Credentials to log into Google (content of credentials.json) + Description: | + [Secret] Credentials to log into Google (content of credentials.json) or the ARN for a secret that contains this. AllowedPattern: '(\{(\s)*(".*")(\s)*:(\s)*(".*")(\s)*\})|(arn:aws:secretsmanager:us-east-2:[0-9]{8,12}:secret:[a-zA-Z0-9/_+=.@-]{1,512})' NoEcho: true GoogleAdminEmail: Type: String - Description: Google Admin email + Description: | + [Secret] Google Admin email address or the ARN for a secret that contains this. AllowedPattern: '(([a-zA-Z0-9.+=_-]{0,61})@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*)|(arn:aws:secretsmanager:us-east-2:[0-9]{8,12}:secret:[a-zA-Z0-9/_+=.@-]{1,512})' SCIMEndpointUrl: Type: String - Description: AWS IAM Identity Center - SCIM Endpoint Url + Description: | + [Secret] AWS IAM Identity Center - SCIM Endpoint Url or the ARN for a secret that contains this. AllowedPattern: '(https://scim.(us(-gov)?|ap|ca|cn|eu|sa)-(central|(north|south)?(east|west)?)-([0-9]{1}).amazonaws.com/(.*)-([a-z0-9]{4})-([a-z0-9]{4})-([a-z0-9]{12})/scim/v2/)|(arn:aws:secretsmanager:us-east-2:[0-9]{8,12}:secret:[a-zA-Z0-9/_+=.@-]{1,512})' SCIMEndpointAccessToken: Type: String - Description: AWS IAM Identity Center - SCIM AccessToken + Description: | + [Secret] AWS IAM Identity Center - SCIM AccessToken or the ARN for a secret that contains this. AllowedPattern: '([0-9a-zA-Z/=+-\\]{500,600})|(arn:aws:secretsmanager:us-east-2:[0-9]{8,12}:secret:[a-zA-Z0-9/_+=.@-]{1,512})' NoEcho: true Region: Type: String - Description: AWS Region where AWS IAM Identity Center is enabled + Description: | + [Secret] AWS Region where AWS IAM Identity Center is enabled or the ARN for a secret that contains this. AllowedPattern: '(us(-gov)?|ap|ca|cn|eu|sa)-(central|(north|south)?(east|west)?)-\d|(arn:aws:secretsmanager:us-east-2:[0-9]{8,12}:secret:[a-zA-Z0-9/_+=.@-]{1,512})' IdentityStoreID: Type: String - Description: Identifier of Identity Store in AWS IAM Identity Center + Description: | + [Secret] Identifier of Identity Store in AWS IAM Identity Center or the ARN for a secret that contains this. AllowedPattern: 'd-[1-z0-9]{10}|(arn:aws:secretsmanager:us-east-2:[0-9]{8,12}:secret:[a-zA-Z0-9/_+=.@-]{1,512})' GoogleUserMatch: Type: String Description: | - Google Workspace user filter query parameter, example: 'name:John* email:admin*', see: https://developers.google.com/admin-sdk/directory/v1/guides/search-users + [optional] Google Workspace user filter query parameter, example: 'name:John* email:admin*', see: https://developers.google.com/admin-sdk/directory/v1/guides/search-users Default: "" AllowedPattern: '(?!.*\s)|(name|Name|NAME)(:([a-zA-Z0-9]{1,64})(\*))|(name|Name|NAME)(=([a-zA-Z0-9 ]{1,64}))|(email|Email|EMAIL)(:([a-zA-Z0-9.-_]{1,64})(\*))|(email|Email|EMAIL)(=([a-zA-Z0-9.-_]{1,64})@([a-zA-Z0-9.-]{5,260}))' GoogleGroupMatch: Type: String Description: | - Google Workspace group filter query parameter, example: 'name:Admin* email:aws-*', see: https://developers.google.com/admin-sdk/directory/v1/guides/search-groups + [optional] Google Workspace group filter query parameter, example: 'name:Admin* email:aws-*', see: https://developers.google.com/admin-sdk/directory/v1/guides/search-groups Default: 'name:AWS*' AllowedPattern: '(?!.*\s)|(name|Name|NAME)(:([a-zA-Z0-9]{1,64})\*)|(name|Name|NAME)(=([a-zA-Z0-9 ]{1,64}))|(email|Email|EMAIL)(:([a-zA-Z0-9.-_]{1,64})\*)|(email|Email|EMAIL)(=([a-zA-Z0-9.-_]{1,64})@([a-zA-Z0-9.-]{5,260}))' IgnoreGroups: Type: String Description: | - Ignore these Google Workspace groups, leave empty if not required + [optional] Ignore these Google Workspace groups, leave empty if not required Default: "" AllowedPattern: '(?!.*\s)|([0-9a-zA-Z-= _]*)(,[0-9a-zA-Z-=@. _]*)*' IgnoreUsers: Type: String Description: | - Ignore these Google Workspace users, leave empty if not required + [optional] Ignore these Google Workspace users, leave empty if not required Default: "" AllowedPattern: '(?!.*\s)|([0-9a-zA-Z-= _]*)(,[0-9a-zA-Z-=@. _]*)*' IncludeGroups: Type: String Description: | - Include only these Google Workspace groups, leave empty if not required. (Only applicable for SyncMethod user_groups) + [optional] Include only these Google Workspace groups, leave empty if not required. (Only applicable for SyncMethod user_groups) Default: "" AllowedPattern: '(?!.*\s)|([0-9a-zA-Z-= _]*)(,[0-9a-zA-Z-=@. _]*)*' SyncMethod: Type: String - Description: Sync method to use or whether to create just the secrets, for use with a function deployed in a separate stack + Description: Sync method to use Default: groups AllowedValues: - groups - users_groups - - secrets only Conditions: SetFunctionName: !Not [!Equals [!Ref "FunctionName", ""]] @@ -173,27 +189,16 @@ Conditions: SetIgnoreGroups: !Not [!Equals [!Ref "IgnoreGroups", ""]] SetIgnoreUsers: !Not [!Equals [!Ref "IgnoreUsers", ""]] SetIncludeGroups: !Or [!Not [!Equals [!Ref "IncludeGroups", ""]], !Equals [!Ref "SyncMethod", groups]] - CreateFunction: !Not [!Equals [!Ref "SyncMethod", "secrets only"]] - CreateSecrets: !Or [!Equals [!Ref "SyncMethod", "secrets only"], !Equals [!Ref "ValuesOrArns", "value"]] - LocalGoogleCredentials: !And [!Equals [!Ref "ValuesOrArns", "secrets"], !Equals [ AWS::AccountId, !Select [5, !Split [":", !Ref "GoogleCredentials"]]]] - LocalGoogleAdminEmail: !And [!Equals [!Ref "ValuesOrArns", "secrets"], !Equals [ AWS::AccountId, !Select [5, !Split [":", !Ref "GoogleAdminEmail"]]]] - LocalSCIMEndpointUrl: !And [!Equals [!Ref "ValuesOrArns", "secrets"], !Equals [ AWS::AccountId, !Select [5, !Split [":", !Ref "SCIMEndpointUrl"]]]] - LocalSCIMEndpointAccessToken: !And [!Equals [!Ref "ValuesOrArns", "secrets"], !Equals [ AWS::AccountId, !Select [5, !Split [":", !Ref "SCIMEndpointAccessToken"]]]] - LocalRegion: !And [!Equals [!Ref "ValuesOrArns", "secrets"], !Equals [ AWS::AccountId, !Select [5, !Split [":", !Ref "Region"]]]] - LocalIdentityStoreID: !And [!Equals [!Ref "ValuesOrArns", "secrets"], !Equals [ AWS::AccountId, !Select [5, !Split [":", !Ref "IdentityStoreID"]]]] - CreateOutputs: !And [!Not [!Equals [!Ref "SyncMethod", "secrets only"]], !Equals [!Ref "FunctionName", ""]] + CreateSecrets: !Or [!Equals [!Ref "DeployPattern", "Full"], !Equals [!Ref "DeployPattern", "Secrets only"]] + CreateOutputs: !And [!Equals [!Ref "FunctionName", ""], !Or [!Equals [!Ref "DeployPattern", "Full"], !Equals [!Ref "DeployPattern", "App only (local secrets)"]]] + CreateFunctionLocal: !Or [!Equals [!Ref "DeployPattern", "Full"], !Equals [!Ref "DeployPattern", "App only (local secrets)"]] + CreateFunctionRemote: !Equals [!Ref "DeployPattern", "App only (remote secrets)"] -Rules: - SecretsOnlyValues: - RuleCondition: !Equals [!Ref "SyncMethod", "secrets only"] - Assertions: - - Assert: !Equals [!Ref "ValuesOrArns", "value"] - AssertDescription: If creating secrets only then values have to be supplied. Resources: - SSOSyncFunction: + SSOSyncFunctionLocal: Type: AWS::Serverless::Function - Condition: CreateFunction + Condition: CreateFunctionLocal Properties: FunctionName: !If [SetFunctionName, !Ref FunctionName, AWS::NoValue] Runtime: provided.al2 @@ -221,17 +226,74 @@ Resources: - Version: '2012-10-17' Statement: - Sid: SSMGetParameterPolicy - Condition: LocalSecrets Effect: Allow Action: - "secretsmanager:Get*" Resource: - - !If [CreateSecrets, !Ref SecretGoogleCredentials, !If [LocalGoogleCredentials, !Ref GoogleCredentials, AWS::NoValue]] - - !If [CreateSecrets, !Ref SecretGoogleAdminEmail, !If [LocalGoogleAdminEmail, !Ref GoogleAdminEmail, AWS::NoValue]] - - !If [CreateSecrets, !Ref SecretSCIMEndpoint, !If [LocalSCIMEndpointUrl, !Ref SCIMEndpointUrl, AWS::NoValue]] - - !If [CreateSecrets, !Ref SecretSCIMAccessToken, !If [LocalSCIMEndpointAccessToken, !Ref SCIMEndpointAccessToken, AWS::NoValue]] - - !If [CreateSecrets, !Ref SecretRegion, !If [LocalRegion, !Ref Region, AWS::NoValue]] - - !If [CreateSecrets, !Ref SecretIdentityStoreID, !If [LocalIdentityStoreID, !Ref IdentityStoreID, AWS::NoValue]] + - !If [CreateSecrets, !Ref SecretGoogleCredentials, !Ref GoogleCredentials] + - !If [CreateSecrets, !Ref SecretGoogleAdminEmail, !Ref GoogleAdminEmail] + - !If [CreateSecrets, !Ref SecretSCIMEndpoint, !Ref SCIMEndpointUrl] + - !If [CreateSecrets, !Ref SecretSCIMAccessToken, !Ref SCIMEndpointAccessToken] + - !If [CreateSecrets, !Ref SecretRegion, !Ref Region] + - !If [CreateSecrets, !Ref SecretIdentityStoreID, !Ref IdentityStoreID] + - Sid: IdentityStoreAccesPolicy + Effect: Allow + Action: + - "identitystore:DeleteUser" + - "identitystore:CreateGroup" + - "identitystore:CreateGroupMembership" + - "identitystore:ListGroups" + - "identitystore:ListUsers" + - "identitystore:ListGroupMemberships" + - "identitystore:IsMemberInGroups" + - "identitystore:GetGroupMembershipId" + - "identitystore:DeleteGroupMembership" + - "identitystore:DeleteGroup" + Resource: + - "*" + - Sid: CodePipelinePolicy + Effect: Allow + Action: + - codepipeline:PutJobSuccessResult + - codepipeline:PutJobFailureResult + Resource: "*" + Events: + SyncScheduledEvent: + Type: Schedule + Name: AWSSyncSchedule + Properties: + Enabled: !If [OnSchedule, false, true] + Schedule: !If [OnSchedule, !Ref ScheduleExpression, "rate(15 minutes)"] + + SSOSyncFunctionRemote: + Type: AWS::Serverless::Function + Condition: CreateFunctionRemote + Properties: + FunctionName: !Ref FunctionName + Runtime: provided.al2 + Handler: bootstrap + Architectures: + - arm64 + Timeout: !Ref TimeOut + Environment: + Variables: + SSOSYNC_LOG_LEVEL: !Ref LogLevel + SSOSYNC_LOG_FORMAT: !Ref LogFormat + SSOSYNC_GOOGLE_CREDENTIALS: !Ref GoogleCredentials + SSOSYNC_GOOGLE_ADMIN: !Ref GoogleAdminEmail + SSOSYNC_SCIM_ENDPOINT: !Ref SCIMEndpointUrl + SSOSYNC_SCIM_ACCESS_TOKEN: !Ref SCIMEndpointAccessToken + SSOSYNC_REGION: !Ref Region + SSOSYNC_IDENTITY_STORE_ID: !Ref IdentityStoreID + SSOSYNC_USER_MATCH: !If [SetGoogleUserMatch, !Ref GoogleUserMatch, AWS::NoValue] + SSOSYNC_GROUP_MATCH: !If [SetGoogleGroupMatch, !Ref GoogleGroupMatch, AWS::NoValue] + SSOSYNC_SYNC_METHOD: !Ref SyncMethod + SSOSYNC_IGNORE_GROUPS: !If [SetIgnoreGroups, !Ref IgnoreGroups, AWS::NoValue] + SSOSYNC_IGNORE_USERS: !If [SetIgnoreUsers, !Ref IgnoreUsers, AWS::NoValue] + SSOSYNC_INCLUDE_GROUPS: !If [SetIncludeGroups, !Ref IncludeGroups, AWS::NoValue] + Policies: + - Version: '2012-10-17' + Statement: - Sid: IdentityStoreAccesPolicy Effect: Allow Action: @@ -307,6 +369,6 @@ Outputs: FunctionArn: Condition: CreateOutputs Description: "The Arn of the deployed lambda function" - Value: !GetAtt SSOSyncFunction.Arn + Value: !GetAtt SSOSyncFunctionLocal.Arn Export: Name: SSOSyncFunctionARN