I'm setting up an AWS DocumentDB cluster using CloudFormation. I set up a password in Secrets Manager like this:
DbClusterCredentials:
Type: AWS::SecretsManager::Secret
Properties:
Name: …
Description: …
GenerateSecretString:
SecretStringTemplate: '{"username": "admin"}'
GenerateStringKey: "password"
PasswordLength: 100
ExcludeCharacters: '/"@'
Then I reference that in my cluster:
DbCluster:
Type: AWS::DocDB::DBCluster
Properties:
DBClusterIdentifier: …
DBSubnetGroupName: …
…
MasterUsername: !Sub "{{resolve:${DbClusterCredentials}:SecretString:username}}"
MasterUserPassword: !Sub "{{resolve:${DbClusterCredentials}:SecretString:password}}"
…
When I try to deploy this with CloudFormation it rolls back with CREATE_FAILED
for DbCluster
, saying:
Property validation failure: [Length of value for property {/MasterUserPassword} is greater than maximum allowed length {100}, Length of value for property {/MasterUsername} is greater than maximum allowed length {63}]
Um, but I requested a password of exactly 100 characters (which is not greater than the maximum of 100 characters), and the username should be admin
(which is not greater than the maximum allowed length of 63). What am I doing wrong?
As @MarkB graciously pointed out, I had a typo in my code. The correct format is {{resolve:secretsmanager:…
. I was missing secretsmanager:
.
But then why was it giving me an error that the username and password were too long? Well that's the "interesting" part. It seems there was/is a bug where CloudFormation would validate the length of the reference rather than the dereferenced value. So since CloudFormation didn't recognize the reference name (even though the outer reference form {{…}}
was correct), it decided, "oh, what the heck, since I don't know how to dereference that reference I'll just validate the reference itself". As this substitution interpolated the secret ARN, the full reference was something like this:
{{resolve:arn:aws:secretsmanager:us-east-:xxxxxxxxxxxx:secret:this-is-my-secret-name-xxxxxx:SecretString:password}}
That's over 100 characters.
So I fixed the reference:
…
MasterUsername: !Sub "{{resolve:secretsmanager:${DbClusterCredentials}:SecretString:username}}"
MasterUserPassword: !Sub "{{resolve:secretsmanager:${DbClusterCredentials}:SecretString:password}}"
…
And … I get another error because the password is over 99 characters. But why? Well even though AWS::DocDB::DBCluster
says that MasterUserPassword
"Must contain from 8 to 100 characters", apparently DocumentDB interfaces with RDS in some manner, and RDS has a limitation of 99 characters for the password. (At least that's what the error message said.)
And finally the username can't be admin
for DocumentDB.
Whew! Fixing the typo, changing the password length to 99, and switching to another username finally got this working.