aws-samples / aws-secrets-manager-rotation-lambdas

Contains Lambda functions to be used for automatic rotation of secrets stored in AWS Secrets Manager
MIT No Attribution
324 stars 279 forks source link

Password length #51

Open dmfilipenko opened 3 years ago

dmfilipenko commented 3 years ago

Almost all of their lambdas dont take into account the password length parameter. Only four of lambdas use password length as argument, but it's hardcoded. Can we pass password length as env variable, as it's done with excluded character?

dmfilipenko commented 3 years ago

@jpeddicord @hyandell @zebehringer @zebehringer @parimaldeshmukh anyone can help with this?

florentcuret commented 3 years ago

maybe it should handle all parameters https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-secretsmanager-secret-generatesecretstring.html and not only the password length

whygoyal commented 2 years ago

Thank you for your feedback. We have noted this as a feature request.

JensRoland commented 2 years ago

This seems like a bug - if a GenerateSecretString config is provided for the Secret, it seems a rotation mechanism should honor this config.

Also, the current workaround of providing an environment variable 'EXCLUDE_CHARACTERS' doesn't even seem to help if you're deploying the secret with Cloudformation, since there doesn't seem to be any way to define environment variables for a HostedRotationLambda.

ben-eb commented 11 months ago

Do you have any update on this please? We have a hard requirement on 30 characters for password length and are not able to specify this as an input parameter to this application.

ben-eb commented 11 months ago

Suggested patch:

From 41b89b9a0c60fc97e7988200d2c5ddb3b905c17c Mon Sep 17 00:00:00 2001
From: Ben Briggs <ben.briggs@york.ac.uk>
Date: Thu, 19 Oct 2023 12:34:49 +0100
Subject: [PATCH] add support for password length environment variable

---
 .../lambda_function.py                                       | 5 ++++-
 SecretsManagerMongoDBRotationMultiUser/lambda_function.py    | 4 +++-
 SecretsManagerMongoDBRotationSingleUser/lambda_function.py   | 4 +++-
 SecretsManagerRDSMariaDBRotationMultiUser/lambda_function.py | 4 +++-
 .../lambda_function.py                                       | 4 +++-
 SecretsManagerRDSMySQLRotationMultiUser/lambda_function.py   | 4 +++-
 SecretsManagerRDSMySQLRotationSingleUser/lambda_function.py  | 4 +++-
 SecretsManagerRDSOracleRotationMultiUser/lambda_function.py  | 4 +++-
 SecretsManagerRDSOracleRotationSingleUser/lambda_function.py | 4 +++-
 .../lambda_function.py                                       | 4 +++-
 .../lambda_function.py                                       | 4 +++-
 .../lambda_function.py                                       | 4 +++-
 .../lambda_function.py                                       | 4 +++-
 SecretsManagerRedshiftRotationMultiUser/lambda_function.py   | 4 +++-
 SecretsManagerRedshiftRotationSingleUser/lambda_function.py  | 4 +++-
 SecretsManagerRotationTemplate/lambda_function.py            | 4 +++-
 16 files changed, 49 insertions(+), 16 deletions(-)

diff --git a/SecretsManagerActiveDirectoryRotationSingleUser/lambda_function.py b/SecretsManagerActiveDirectoryRotationSingleUser/lambda_function.py
index 5c2a54f..a7cec51 100644
--- a/SecretsManagerActiveDirectoryRotationSingleUser/lambda_function.py
+++ b/SecretsManagerActiveDirectoryRotationSingleUser/lambda_function.py
@@ -210,9 +210,12 @@ def create_secret(secrets_manager_client, arn, token, directory_name, current_di
         logger.info("createSecret: Successfully retrieved secret for %s." % arn)
     except secrets_manager_client.exceptions.ResourceNotFoundException:
         exclude_characters = os.environ.get("EXCLUDE_CHARACTERS", EXCLUDE_CHARACTERS)
+        # Get password length from environment variable
+        password_length = int(os.environ['PASSWORD_LENGTH']) if 'PASSWORD_LENGTH' in os.environ else 32
         # Generate a random password
         passwd = secrets_manager_client.get_random_password(
-            ExcludeCharacters=exclude_characters
+            ExcludeCharacters=exclude_characters,
+            PasswordLength=password_length
         )
         current_dict[DICT_KEY_PASSWORD] = passwd["RandomPassword"]

diff --git a/SecretsManagerMongoDBRotationMultiUser/lambda_function.py b/SecretsManagerMongoDBRotationMultiUser/lambda_function.py
index af83bb7..e2d537d 100644
--- a/SecretsManagerMongoDBRotationMultiUser/lambda_function.py
+++ b/SecretsManagerMongoDBRotationMultiUser/lambda_function.py
@@ -122,8 +122,10 @@ def create_secret(service_client, arn, token):

         # Get exclude characters from environment variable
         exclude_characters = os.environ['EXCLUDE_CHARACTERS'] if 'EXCLUDE_CHARACTERS' in os.environ else '/@"\'\\'
+        # Get password length from environment variable
+        password_length = int(os.environ['PASSWORD_LENGTH']) if 'PASSWORD_LENGTH' in os.environ else 32
         # Generate a random password
-        passwd = service_client.get_random_password(ExcludeCharacters=exclude_characters)
+        passwd = service_client.get_random_password(ExcludeCharacters=exclude_characters, PasswordLength=password_length)
         current_dict['password'] = passwd['RandomPassword']

         # Put the secret
diff --git a/SecretsManagerMongoDBRotationSingleUser/lambda_function.py b/SecretsManagerMongoDBRotationSingleUser/lambda_function.py
index d2c7d29..93a929b 100644
--- a/SecretsManagerMongoDBRotationSingleUser/lambda_function.py
+++ b/SecretsManagerMongoDBRotationSingleUser/lambda_function.py
@@ -116,8 +116,10 @@ def create_secret(service_client, arn, token):
     except service_client.exceptions.ResourceNotFoundException:
         # Get exclude characters from environment variable
         exclude_characters = os.environ['EXCLUDE_CHARACTERS'] if 'EXCLUDE_CHARACTERS' in os.environ else '/@"\'\\'
+        # Get password length from environment variable
+        password_length = int(os.environ['PASSWORD_LENGTH']) if 'PASSWORD_LENGTH' in os.environ else 32
         # Generate a random password
-        passwd = service_client.get_random_password(ExcludeCharacters=exclude_characters)
+        passwd = service_client.get_random_password(ExcludeCharacters=exclude_characters, PasswordLength=password_length)
         current_dict['password'] = passwd['RandomPassword']

         # Put the secret
diff --git a/SecretsManagerRDSMariaDBRotationMultiUser/lambda_function.py b/SecretsManagerRDSMariaDBRotationMultiUser/lambda_function.py
index 5ba63cc..9c5325a 100644
--- a/SecretsManagerRDSMariaDBRotationMultiUser/lambda_function.py
+++ b/SecretsManagerRDSMariaDBRotationMultiUser/lambda_function.py
@@ -122,8 +122,10 @@ def create_secret(service_client, arn, token):

         # Get exclude characters from environment variable
         exclude_characters = os.environ['EXCLUDE_CHARACTERS'] if 'EXCLUDE_CHARACTERS' in os.environ else '/@"\'\\'
+        # Get password length from environment variable
+        password_length = int(os.environ['PASSWORD_LENGTH']) if 'PASSWORD_LENGTH' in os.environ else 32
         # Generate a random password
-        passwd = service_client.get_random_password(ExcludeCharacters=exclude_characters)
+        passwd = service_client.get_random_password(ExcludeCharacters=exclude_characters, PasswordLength=password_length)
         current_dict['password'] = passwd['RandomPassword']

         # Put the secret
diff --git a/SecretsManagerRDSMariaDBRotationSingleUser/lambda_function.py b/SecretsManagerRDSMariaDBRotationSingleUser/lambda_function.py
index 53b4622..910976d 100644
--- a/SecretsManagerRDSMariaDBRotationSingleUser/lambda_function.py
+++ b/SecretsManagerRDSMariaDBRotationSingleUser/lambda_function.py
@@ -114,8 +114,10 @@ def create_secret(service_client, arn, token):
     except service_client.exceptions.ResourceNotFoundException:
         # Get exclude characters from environment variable
         exclude_characters = os.environ['EXCLUDE_CHARACTERS'] if 'EXCLUDE_CHARACTERS' in os.environ else '/@"\'\\'
+        # Get password length from environment variable
+        password_length = int(os.environ['PASSWORD_LENGTH']) if 'PASSWORD_LENGTH' in os.environ else 32
         # Generate a random password
-        passwd = service_client.get_random_password(ExcludeCharacters=exclude_characters)
+        passwd = service_client.get_random_password(ExcludeCharacters=exclude_characters, PasswordLength=password_length)
         current_dict['password'] = passwd['RandomPassword']

         # Put the secret
diff --git a/SecretsManagerRDSMySQLRotationMultiUser/lambda_function.py b/SecretsManagerRDSMySQLRotationMultiUser/lambda_function.py
index 986e382..4cbbe33 100644
--- a/SecretsManagerRDSMySQLRotationMultiUser/lambda_function.py
+++ b/SecretsManagerRDSMySQLRotationMultiUser/lambda_function.py
@@ -122,8 +122,10 @@ def create_secret(service_client, arn, token):

         # Get exclude characters from environment variable
         exclude_characters = os.environ['EXCLUDE_CHARACTERS'] if 'EXCLUDE_CHARACTERS' in os.environ else '/@"\'\\'
+        # Get password length from environment variable
+        password_length = int(os.environ['PASSWORD_LENGTH']) if 'PASSWORD_LENGTH' in os.environ else 32
         # Generate a random password
-        passwd = service_client.get_random_password(ExcludeCharacters=exclude_characters)
+        passwd = service_client.get_random_password(ExcludeCharacters=exclude_characters, PasswordLength=password_length)
         current_dict['password'] = passwd['RandomPassword']

         # Put the secret
diff --git a/SecretsManagerRDSMySQLRotationSingleUser/lambda_function.py b/SecretsManagerRDSMySQLRotationSingleUser/lambda_function.py
index 892f743..496c06c 100644
--- a/SecretsManagerRDSMySQLRotationSingleUser/lambda_function.py
+++ b/SecretsManagerRDSMySQLRotationSingleUser/lambda_function.py
@@ -114,8 +114,10 @@ def create_secret(service_client, arn, token):
     except service_client.exceptions.ResourceNotFoundException:
         # Get exclude characters from environment variable
         exclude_characters = os.environ['EXCLUDE_CHARACTERS'] if 'EXCLUDE_CHARACTERS' in os.environ else '/@"\'\\'
+        # Get password length from environment variable
+        password_length = int(os.environ['PASSWORD_LENGTH']) if 'PASSWORD_LENGTH' in os.environ else 32
         # Generate a random password
-        passwd = service_client.get_random_password(ExcludeCharacters=exclude_characters)
+        passwd = service_client.get_random_password(ExcludeCharacters=exclude_characters, PasswordLength=password_length)
         current_dict['password'] = passwd['RandomPassword']

         # Put the secret
diff --git a/SecretsManagerRDSOracleRotationMultiUser/lambda_function.py b/SecretsManagerRDSOracleRotationMultiUser/lambda_function.py
index 90d3169..1b45f29 100644
--- a/SecretsManagerRDSOracleRotationMultiUser/lambda_function.py
+++ b/SecretsManagerRDSOracleRotationMultiUser/lambda_function.py
@@ -122,8 +122,10 @@ def create_secret(service_client, arn, token):

         # Get exclude characters from environment variable
         exclude_characters = os.environ['EXCLUDE_CHARACTERS'] if 'EXCLUDE_CHARACTERS' in os.environ else '/@"\'\\'
+        # Get password length from environment variable
+        password_length = int(os.environ['PASSWORD_LENGTH']) if 'PASSWORD_LENGTH' in os.environ else 30
         # Generate a random password
-        passwd = service_client.get_random_password(ExcludeCharacters=exclude_characters, PasswordLength=30)
+        passwd = service_client.get_random_password(ExcludeCharacters=exclude_characters, PasswordLength=password_length)
         current_dict['password'] = passwd['RandomPassword']

         # Put the secret
diff --git a/SecretsManagerRDSOracleRotationSingleUser/lambda_function.py b/SecretsManagerRDSOracleRotationSingleUser/lambda_function.py
index 42563df..ce4456d 100644
--- a/SecretsManagerRDSOracleRotationSingleUser/lambda_function.py
+++ b/SecretsManagerRDSOracleRotationSingleUser/lambda_function.py
@@ -114,8 +114,10 @@ def create_secret(service_client, arn, token):
     except service_client.exceptions.ResourceNotFoundException:
         # Get exclude characters from environment variable
         exclude_characters = os.environ['EXCLUDE_CHARACTERS'] if 'EXCLUDE_CHARACTERS' in os.environ else '/@"\'\\'
+        # Get password length from environment variable
+        password_length = int(os.environ['PASSWORD_LENGTH']) if 'PASSWORD_LENGTH' in os.environ else 30
         # Generate a random password
-        passwd = service_client.get_random_password(ExcludeCharacters=exclude_characters, PasswordLength=30)
+        passwd = service_client.get_random_password(ExcludeCharacters=exclude_characters, PasswordLength=password_length)
         current_dict['password'] = passwd['RandomPassword']

         # Put the secret
diff --git a/SecretsManagerRDSPostgreSQLRotationMultiUser/lambda_function.py b/SecretsManagerRDSPostgreSQLRotationMultiUser/lambda_function.py
index c40e25e..bb630b2 100644
--- a/SecretsManagerRDSPostgreSQLRotationMultiUser/lambda_function.py
+++ b/SecretsManagerRDSPostgreSQLRotationMultiUser/lambda_function.py
@@ -124,8 +124,10 @@ def create_secret(service_client, arn, token):

         # Get exclude characters from environment variable
         exclude_characters = os.environ['EXCLUDE_CHARACTERS'] if 'EXCLUDE_CHARACTERS' in os.environ else ':/@"\'\\'
+        # Get password length from environment variable
+        password_length = int(os.environ['PASSWORD_LENGTH']) if 'PASSWORD_LENGTH' in os.environ else 32
         # Generate a random password
-        passwd = service_client.get_random_password(ExcludeCharacters=exclude_characters)
+        passwd = service_client.get_random_password(ExcludeCharacters=exclude_characters,PasswordLength=password_length)
         current_dict['password'] = passwd['RandomPassword']

         # Put the secret
diff --git a/SecretsManagerRDSPostgreSQLRotationSingleUser/lambda_function.py b/SecretsManagerRDSPostgreSQLRotationSingleUser/lambda_function.py
index 7451bac..9ecc330 100644
--- a/SecretsManagerRDSPostgreSQLRotationSingleUser/lambda_function.py
+++ b/SecretsManagerRDSPostgreSQLRotationSingleUser/lambda_function.py
@@ -116,8 +116,10 @@ def create_secret(service_client, arn, token):
     except service_client.exceptions.ResourceNotFoundException:
         # Get exclude characters from environment variable
         exclude_characters = os.environ['EXCLUDE_CHARACTERS'] if 'EXCLUDE_CHARACTERS' in os.environ else ':/@"\'\\'
+        # Get password length from environment variable
+        password_length = int(os.environ['PASSWORD_LENGTH']) if 'PASSWORD_LENGTH' in os.environ else 32
         # Generate a random password
-        passwd = service_client.get_random_password(ExcludeCharacters=exclude_characters)
+        passwd = service_client.get_random_password(ExcludeCharacters=exclude_characters, PasswordLength=password_length)
         current_dict['password'] = passwd['RandomPassword']

         # Put the secret
diff --git a/SecretsManagerRDSSQLServerRotationMultiUser/lambda_function.py b/SecretsManagerRDSSQLServerRotationMultiUser/lambda_function.py
index d857198..47ba849 100644
--- a/SecretsManagerRDSSQLServerRotationMultiUser/lambda_function.py
+++ b/SecretsManagerRDSSQLServerRotationMultiUser/lambda_function.py
@@ -122,8 +122,10 @@ def create_secret(service_client, arn, token):

         # Get exclude characters from environment variable
         exclude_characters = os.environ['EXCLUDE_CHARACTERS'] if 'EXCLUDE_CHARACTERS' in os.environ else '/@"\'\\'
+        # Get password length from environment variable
+        password_length = int(os.environ['PASSWORD_LENGTH']) if 'PASSWORD_LENGTH' in os.environ else 32
         # Generate a random password
-        passwd = service_client.get_random_password(ExcludeCharacters=exclude_characters)
+        passwd = service_client.get_random_password(ExcludeCharacters=exclude_characters, PasswordLength=password_length)
         current_dict['password'] = passwd['RandomPassword']

         # Put the secret
diff --git a/SecretsManagerRDSSQLServerRotationSingleUser/lambda_function.py b/SecretsManagerRDSSQLServerRotationSingleUser/lambda_function.py
index 2f827bc..39c4579 100644
--- a/SecretsManagerRDSSQLServerRotationSingleUser/lambda_function.py
+++ b/SecretsManagerRDSSQLServerRotationSingleUser/lambda_function.py
@@ -114,8 +114,10 @@ def create_secret(service_client, arn, token):
     except service_client.exceptions.ResourceNotFoundException:
         # Get exclude characters from environment variable
         exclude_characters = os.environ['EXCLUDE_CHARACTERS'] if 'EXCLUDE_CHARACTERS' in os.environ else '/@"\'\\'
+        # Get password length from environment variable
+        password_length = int(os.environ['PASSWORD_LENGTH']) if 'PASSWORD_LENGTH' in os.environ else 32
         # Generate a random password
-        passwd = service_client.get_random_password(ExcludeCharacters=exclude_characters)
+        passwd = service_client.get_random_password(ExcludeCharacters=exclude_characters, PasswordLength=password_length)
         current_dict['password'] = passwd['RandomPassword']

         # Put the secret
diff --git a/SecretsManagerRedshiftRotationMultiUser/lambda_function.py b/SecretsManagerRedshiftRotationMultiUser/lambda_function.py
index 01ae0ef..0d61c92 100644
--- a/SecretsManagerRedshiftRotationMultiUser/lambda_function.py
+++ b/SecretsManagerRedshiftRotationMultiUser/lambda_function.py
@@ -121,8 +121,10 @@ def create_secret(service_client, arn, token):

         # Get exclude characters from environment variable
         exclude_characters = os.environ['EXCLUDE_CHARACTERS'] if 'EXCLUDE_CHARACTERS' in os.environ else '/@"\'\\:'
+        # Get password length from environment variable
+        password_length = int(os.environ['PASSWORD_LENGTH']) if 'PASSWORD_LENGTH' in os.environ else 32
         # Generate a random password
-        passwd = service_client.get_random_password(ExcludeCharacters=exclude_characters)
+        passwd = service_client.get_random_password(ExcludeCharacters=exclude_characters, PasswordLength=password_length)
         current_dict['password'] = passwd['RandomPassword']

         # Put the secret
diff --git a/SecretsManagerRedshiftRotationSingleUser/lambda_function.py b/SecretsManagerRedshiftRotationSingleUser/lambda_function.py
index 78ed403..5f7b6f3 100644
--- a/SecretsManagerRedshiftRotationSingleUser/lambda_function.py
+++ b/SecretsManagerRedshiftRotationSingleUser/lambda_function.py
@@ -115,8 +115,10 @@ def create_secret(service_client, arn, token):
     except service_client.exceptions.ResourceNotFoundException:
         # Get exclude characters from environment variable
         exclude_characters = os.environ['EXCLUDE_CHARACTERS'] if 'EXCLUDE_CHARACTERS' in os.environ else '/@"\'\\:'
+        # Get password length from environment variable
+        password_length = int(os.environ['PASSWORD_LENGTH']) if 'PASSWORD_LENGTH' in os.environ else 32
         # Generate a random password
-        passwd = service_client.get_random_password(ExcludeCharacters=exclude_characters)
+        passwd = service_client.get_random_password(ExcludeCharacters=exclude_characters, PasswordLength=password_length)
         current_dict['password'] = passwd['RandomPassword']

         # Put the secret
diff --git a/SecretsManagerRotationTemplate/lambda_function.py b/SecretsManagerRotationTemplate/lambda_function.py
index 82140a8..9d93964 100644
--- a/SecretsManagerRotationTemplate/lambda_function.py
+++ b/SecretsManagerRotationTemplate/lambda_function.py
@@ -96,8 +96,10 @@ def create_secret(service_client, arn, token):
     except service_client.exceptions.ResourceNotFoundException:
         # Get exclude characters from environment variable
         exclude_characters = os.environ['EXCLUDE_CHARACTERS'] if 'EXCLUDE_CHARACTERS' in os.environ else '/@"\'\\'
+        # Get password length from environment variable
+        password_length = int(os.environ['PASSWORD_LENGTH']) if 'PASSWORD_LENGTH' in os.environ else 32
         # Generate a random password
-        passwd = service_client.get_random_password(ExcludeCharacters=exclude_characters)
+        passwd = service_client.get_random_password(ExcludeCharacters=exclude_characters, PasswordLength=password_length)

         # Put the secret
         service_client.put_secret_value(SecretId=arn, ClientRequestToken=token, SecretString=passwd['RandomPassword'], VersionStages=['AWSPENDING'])
-- 
2.41.0
msambol commented 11 months ago

I investigated this from the CDK side. One blocker is see is that PasswordLength is not found here: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-secretsmanager-rotationschedule-hostedrotationlambda.html.