AWS code-library high security documentation change
Summary
Significant security enhancements to AWS Secrets Manager code examples including: improved secure random generation using openssl and Python secrets; secure password storage in temporary files with restricted permissions; immediate clearing of secrets from memory; scheduled secret deletion with recovery window; IP validation and error handling; secure certificate download with validation; least privilege resource policies; automated resource cleanup; and added security best practice recommendations
Security assessment
The changes directly address multiple security weaknesses: 1) Replaced insecure random generation with cryptographic methods (openssl/Python secrets) 2) Added secure storage of passwords in temp files (chmod 600) instead of variables 3) Implemented secret clearing from memory after use 4) Changed secret deletion to scheduled with recovery window 5) Added IP validation and timeout protections 6) Implemented least-privilege resource policies with version stage conditions 7) Added security tagging and rotation recommendations
Diff
diff --git a/code-library/latest/ug/bash_2_secrets-manager_code_examples.md b/code-library/latest/ug/bash_2_secrets-manager_code_examples.md index 37ce2ae28..d1bd58bb8 100644 --- a//code-library/latest/ug/bash_2_secrets-manager_code_examples.md +++ b//code-library/latest/ug/bash_2_secrets-manager_code_examples.md @@ -1082 +1082 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - SUFFIX=$(cat /dev/urandom | tr -dc 'a-z0-9' | fold -w 8 | head -n 1) + SUFFIX=$(LC_ALL=C tr -dc 'a-z0-9' </dev/urandom | head -c 8) @@ -1094,0 +1095 @@ There's more on GitHub. Find the complete example and learn how to set up and ru + trap 'rm -rf "$TEMP_DIR"' EXIT @@ -1137 +1137,0 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - rm -rf "$TEMP_DIR" @@ -1273 +1273 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - # Delete secret + # Delete secret with scheduled deletion instead of immediate deletion @@ -1275 +1275 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - echo "Deleting secret '${SECRET_NAME}'..." + echo "Deleting secret '${SECRET_NAME}' (scheduled for 7 days)..." @@ -1278 +1278 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - --force-delete-without-recovery 2>&1 || echo "WARNING: Failed to delete secret." + --recovery-window-in-days 7 2>&1 || echo "WARNING: Failed to delete secret." @@ -1293,2 +1293,9 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - # Generate a safe password (no / @ " or spaces) - MASTER_PASSWORD=$(cat /dev/urandom | tr -dc 'A-Za-z0-9!#$%^&*()_+=-' | fold -w 20 | head -n 1) + # Generate a strong password using openssl for better randomness + # Meets DocumentDB requirements: 8-100 chars, alphanumeric + special chars + MASTER_PASSWORD=$(openssl rand -base64 32 | tr -d '/' | cut -c1-20) + + # Securely store password in temporary file with restricted permissions + TEMP_PASS_FILE=$(mktemp) + chmod 600 "$TEMP_PASS_FILE" + echo -n "$MASTER_PASSWORD" > "$TEMP_PASS_FILE" + trap "rm -f '$TEMP_PASS_FILE'; rm -rf '$TEMP_DIR'" EXIT @@ -1299 +1306 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - --secret-string "$MASTER_PASSWORD" \ + --secret-string file://"$TEMP_PASS_FILE" \ @@ -1301,0 +1309,3 @@ There's more on GitHub. Find the complete example and learn how to set up and ru + # Securely clear password from memory + MASTER_PASSWORD="" + @@ -1404,0 +1415,3 @@ There's more on GitHub. Find the complete example and learn how to set up and ru + # Read password securely from file for cluster creation + MASTER_PASSWORD=$(cat "$TEMP_PASS_FILE") + @@ -1412,0 +1426 @@ There's more on GitHub. Find the complete example and learn how to set up and ru + --kms-key-id "alias/aws/docdb" \ @@ -1413,0 +1428 @@ There's more on GitHub. Find the complete example and learn how to set up and ru + --enable-cloudwatch-logs-exports '["audit","error","general","slowquery"]' \ @@ -1415,0 +1431,3 @@ There's more on GitHub. Find the complete example and learn how to set up and ru + # Clear password immediately after use + MASTER_PASSWORD="" + @@ -1488,7 +1506,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - # Get the user's public IP - MY_IP=$(curl -s https://checkip.amazonaws.com 2>&1) - - if echo "$MY_IP" | grep -iq "error\|could not\|failed"; then - echo "ERROR: Could not determine public IP address." - exit 1 - fi + # Get the user's public IP with timeout and error handling + MY_IP=$(timeout 5 curl -s --max-time 5 https://checkip.amazonaws.com 2>/dev/null || true) @@ -1495,0 +1509,5 @@ There's more on GitHub. Find the complete example and learn how to set up and ru + if [ -z "$MY_IP" ] || echo "$MY_IP" | grep -iq "error\|could not\|failed"; then + echo "WARNING: Could not determine public IP address. Skipping security group rule." + echo "You must manually add an ingress rule for your IP to security group $SG_ID" + MY_IP="" + else @@ -1498,0 +1517,5 @@ There's more on GitHub. Find the complete example and learn how to set up and ru + # Validate IP format (basic check) + if ! echo "$MY_IP" | grep -qE '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$'; then + echo "WARNING: Invalid IP address format: $MY_IP. Skipping security group rule." + MY_IP="" + else @@ -1516,0 +1540,3 @@ There's more on GitHub. Find the complete example and learn how to set up and ru + CREATED_RESOURCES+=("sg-rule:${SG_ID}:${MY_IP}") + fi + fi @@ -1519 +1544,0 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - CREATED_RESOURCES+=("sg-rule:${SG_ID}:${MY_IP}") @@ -1531 +1556 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - curl -s -o "$CA_CERT_PATH" https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem 2>&1 + CA_CERT_URL="https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem" @@ -1533,3 +1558,5 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - if [ ! -s "$CA_CERT_PATH" ]; then - echo "WARNING: Failed to download CA certificate." - else + if timeout 10 curl -s --max-time 10 -o "$CA_CERT_PATH" "$CA_CERT_URL" 2>&1; then + if [ -s "$CA_CERT_PATH" ]; then + # Verify it's a valid PEM file and check file permissions + if grep -q "BEGIN CERTIFICATE" "$CA_CERT_PATH"; then + chmod 644 "$CA_CERT_PATH" @@ -1536,0 +1564,3 @@ There's more on GitHub. Find the complete example and learn how to set up and ru + else + echo "WARNING: Downloaded file is not a valid PEM certificate." + CA_CERT_PATH="" @@ -1537,0 +1568,9 @@ There's more on GitHub. Find the complete example and learn how to set up and ru + else + echo "WARNING: Failed to download CA certificate (empty file)." + CA_CERT_PATH="" + fi + else + echo "WARNING: Failed to download CA certificate (timeout or network error)." + CA_CERT_PATH="" + fi + @@ -1551,0 +1591 @@ There's more on GitHub. Find the complete example and learn how to set up and ru + if [ -n "$CA_CERT_PATH" ]; then @@ -1552,0 +1593 @@ There's more on GitHub. Find the complete example and learn how to set up and ru + fi @@ -1554,0 +1596 @@ There's more on GitHub. Find the complete example and learn how to set up and ru + if [ -n "$CA_CERT_PATH" ]; then @@ -1555,0 +1598,3 @@ There's more on GitHub. Find the complete example and learn how to set up and ru + else + echo " mongosh --tls --host ${CLUSTER_ENDPOINT} \\" + fi @@ -1572,2 +1617,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - echo "Do you want to clean up all created resources? (y/n): " - read -r CLEANUP_CHOICE + echo "Automatically cleaning up all created resources..." + echo "" @@ -1575 +1619,0 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - if [ "$CLEANUP_CHOICE" = "y" ] || [ "$CLEANUP_CHOICE" = "Y" ]; then @@ -1577,21 +1620,0 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - else - echo "" - echo "Resources were NOT deleted. To clean up manually, run:" - echo "" - echo " # Revoke security group ingress rule" - echo " aws ec2 revoke-security-group-ingress --group-id ${SG_ID} --protocol tcp --port ${DOCDB_PORT} --cidr ${MY_IP}/32" - echo "" - echo " # Delete instance (wait for it to finish before deleting cluster)" - echo " aws docdb delete-db-instance --db-instance-identifier ${INSTANCE_ID}" - echo " aws docdb wait db-instance-deleted --db-instance-identifier ${INSTANCE_ID}" - echo "" - echo " # Delete cluster" - echo " aws docdb delete-db-cluster --db-cluster-identifier ${CLUSTER_ID} --skip-final-snapshot" - echo "" - echo " # Delete subnet group (after cluster is deleted)" - echo " aws docdb delete-db-subnet-group --db-subnet-group-name ${SUBNET_GROUP_NAME}" - echo "" - echo " # Delete secret" - echo " aws secretsmanager delete-secret --secret-id ${SECRET_NAME} --force-delete-without-recovery" - echo "" - fi @@ -1599 +1621,0 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - rm -rf "$TEMP_DIR" @@ -1671,0 +1693,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru + set -euo pipefail + @@ -1684 +1707 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - if echo "$output" | grep -i "error" > /dev/null; then + if echo "$output" | grep -qi "error"; then @@ -1692 +1715 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - # Function to generate a random identifier + # Function to generate a random identifier using secure method @@ -1694 +1717 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - echo "sm$(cat /dev/urandom | tr -dc 'a-z0-9' | fold -w 8 | head -n 1)" + python3 -c "import secrets; print('sm' + secrets.token_hex(4))" @@ -1697 +1720 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - # Function to clean up resources + # Function to safely clean up resources @@ -1704 +1727 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - if [ -n "$SECRET_NAME" ]; then + if [ -n "${SECRET_NAME:-}" ]; then @@ -1708 +1731 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - if [ -n "$RUNTIME_ROLE_NAME" ]; then + if [ -n "${RUNTIME_ROLE_NAME:-}" ]; then @@ -1712 +1735 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - if [ -n "$ADMIN_ROLE_NAME" ]; then + if [ -n "${ADMIN_ROLE_NAME:-}" ]; then @@ -1720,5 +1743 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - echo "Do you want to clean up all created resources? (y/n): " - read -r CLEANUP_CHOICE - - if [[ "$CLEANUP_CHOICE" =~ ^[Yy]$ ]]; then - echo "Cleaning up resources..." + echo "Cleaning up all created resources..." @@ -1727 +1746 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - if [ -n "$SECRET_NAME" ]; then + if [ -n "${SECRET_NAME:-}" ]; then @@ -1729 +1748 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - aws secretsmanager delete-secret --secret-id "$SECRET_NAME" --force-delete-without-recovery + aws secretsmanager delete-secret --secret-id "$SECRET_NAME" --force-delete-without-recovery 2>/dev/null || true @@ -1733 +1752,5 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - if [ -n "$RUNTIME_ROLE_NAME" ]; then + if [ -n "${RUNTIME_ROLE_NAME:-}" ]; then + echo "Deleting inline policies from runtime role: $RUNTIME_ROLE_NAME" + for policy in $(aws iam list-role-policies --role-name "$RUNTIME_ROLE_NAME" --query 'PolicyNames[]' --output text 2>/dev/null || true); do + aws iam delete-role-policy --role-name "$RUNTIME_ROLE_NAME" --policy-name "$policy" 2>/dev/null || true + done @@ -1735 +1758 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - aws iam delete-role --role-name "$RUNTIME_ROLE_NAME" + aws iam delete-role --role-name "$RUNTIME_ROLE_NAME" 2>/dev/null || true @@ -1739 +1762 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - if [ -n "$ADMIN_ROLE_NAME" ]; then + if [ -n "${ADMIN_ROLE_NAME:-}" ]; then @@ -1741 +1764,5 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - aws iam detach-role-policy --role-name "$ADMIN_ROLE_NAME" --policy-arn "arn:aws:iam::aws:policy/SecretsManagerReadWrite" + aws iam detach-role-policy --role-name "$ADMIN_ROLE_NAME" --policy-arn "arn:aws:iam::aws:policy/SecretsManagerReadWrite" 2>/dev/null || true +