AWS code-library medium security documentation change
Summary
Enhanced the DynamoDB tutorial script with security best practices including secure log handling, AWS credential validation, improved error checking, input sanitization, and automated resource cleanup.
Security assessment
The changes implement multiple security enhancements: 1) Sets strict permissions (chmod 700/600) for log files to prevent unauthorized access 2) Validates AWS credentials before execution to prevent misconfigured operations 3) Adds table name validation to prevent potential injection attacks 4) Secures temporary file handling with automatic removal 5) Implements error handling that prevents sensitive data leakage by redirecting errors to stderr. These collectively mitigate risks like credential exposure, log tampering, and resource sprawl.
Diff
diff --git a/code-library/latest/ug/dynamodb_example_dynamodb_GettingStarted_070_section.md b/code-library/latest/ug/dynamodb_example_dynamodb_GettingStarted_070_section.md index 841afa439..10582ba63 100644 --- a//code-library/latest/ug/dynamodb_example_dynamodb_GettingStarted_070_section.md +++ b//code-library/latest/ug/dynamodb_example_dynamodb_GettingStarted_070_section.md @@ -46,2 +46,9 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - # Set up logging - LOG_FILE="dynamodb-tutorial-$(date +%Y%m%d-%H%M%S).log" + set -euo pipefail + + # Set up logging with secure permissions + LOG_DIR="${XDG_STATE_HOME:-.}/dynamodb-tutorial-logs" + mkdir -p "$LOG_DIR" + LOG_FILE="$LOG_DIR/dynamodb-tutorial-$(date +%Y%m%d-%H%M%S).log" + chmod 700 "$LOG_DIR" + touch "$LOG_FILE" + chmod 600 "$LOG_FILE" @@ -52,0 +60,12 @@ There's more on GitHub. Find the complete example and learn how to set up and ru + # Validate AWS CLI is configured + if ! command -v aws &> /dev/null; then + echo "ERROR: AWS CLI is not installed or not in PATH" + exit 1 + fi + + # Check AWS credentials are available + if ! aws sts get-caller-identity &> /dev/null; then + echo "ERROR: AWS credentials not configured or invalid" + exit 1 + fi + @@ -58,4 +77,4 @@ 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 - echo "ERROR detected in $cmd_name command:" - echo "$output" - exit 1 + if echo "$output" | grep -qi "error\|failed"; then + echo "ERROR detected in $cmd_name command:" >&2 + echo "$output" >&2 + return 1 @@ -62,0 +82 @@ There's more on GitHub. Find the complete example and learn how to set up and ru + return 0 @@ -67,0 +88,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru + local max_attempts=60 + local attempt=0 @@ -72 +94 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - while [[ "$status" != "ACTIVE" ]]; do + while [[ "$status" != "ACTIVE" && $attempt -lt $max_attempts ]]; do @@ -74 +96 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - status=$(aws dynamodb describe-table --table-name "$table_name" --query "Table.TableStatus" --output text) + status=$(aws dynamodb describe-table --table-name "$table_name" --query "Table.TableStatus" --output text 2>/dev/null || echo "UNKNOWN") @@ -75,0 +98 @@ There's more on GitHub. Find the complete example and learn how to set up and ru + ((attempt++)) @@ -77,0 +101,5 @@ There's more on GitHub. Find the complete example and learn how to set up and ru + if [[ "$status" != "ACTIVE" ]]; then + echo "ERROR: Table $table_name did not become ACTIVE within timeout period" >&2 + return 1 + fi + @@ -78,0 +107 @@ There's more on GitHub. Find the complete example and learn how to set up and ru + return 0 @@ -82 +111,53 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - RESOURCES=() + declare -a RESOURCES=() + + # Cleanup function + cleanup() { + local exit_code=$? + + if [[ $exit_code -ne 0 ]]; then + echo "Script encountered an error (exit code: $exit_code)" >&2 + fi + + echo "" + echo "===========================================" + echo "CLEANUP" + echo "===========================================" + echo "Resources to clean up:" + for resource in "${RESOURCES[@]+"${RESOURCES[@]}"}"; do + echo "- $resource" + done + echo "" + + if [[ ${#RESOURCES[@]} -gt 0 ]]; then + echo "Proceeding with cleanup of all created resources..." + + for resource in "${RESOURCES[@]+"${RESOURCES[@]}"}"; do + if [[ "$resource" == Table:* ]]; then + local table_name="${resource#Table:}" + echo "Deleting table: $table_name" + if aws dynamodb delete-table --table-name "$table_name" 2>/dev/null; then + echo "Waiting for table deletion to complete..." + aws dynamodb wait table-not-exists --table-name "$table_name" 2>/dev/null || true + else + echo "Warning: Failed to delete table $table_name" >&2 + fi + fi + done + + echo "Cleanup completed." + fi + + return $exit_code + } + + trap cleanup EXIT + + # Validate table name + validate_table_name() { + local name=$1 + if [[ ! $name =~ ^[a-zA-Z0-9._-]+$ ]] || [[ ${#name} -gt 255 ]]; then + echo "ERROR: Invalid table name: $name" >&2 + return 1 + fi + return 0 + } @@ -86,0 +168,3 @@ There's more on GitHub. Find the complete example and learn how to set up and ru + TABLE_NAME="Music" + validate_table_name "$TABLE_NAME" + @@ -88 +172 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - --table-name Music \ + --table-name "$TABLE_NAME" \ @@ -94 +178,4 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - --table-class STANDARD) + --table-class STANDARD 2>&1) || { + echo "ERROR: Failed to create table" >&2 + exit 1 + } @@ -100 +187 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - RESOURCES+=("Table:Music") + RESOURCES+=("Table:$TABLE_NAME") @@ -103 +190 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - wait_for_table_active "Music" + wait_for_table_active "$TABLE_NAME" @@ -106 +193 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - echo "Enabling point-in-time recovery for the Music table..." + echo "Enabling point-in-time recovery for the $TABLE_NAME table..." @@ -109,2 +196,5 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - --table-name Music \ - --point-in-time-recovery-specification PointInTimeRecoveryEnabled=true) + --table-name "$TABLE_NAME" \ + --point-in-time-recovery-specification PointInTimeRecoveryEnabled=true 2>&1) || { + echo "ERROR: Failed to enable PITR" >&2 + exit 1 + } @@ -116,37 +206,25 @@ There's more on GitHub. Find the complete example and learn how to set up and ru - echo "Step 2: Writing data to the Music table..." - - # Add first item - ITEM1_OUTPUT=$(aws dynamodb put-item \ - --table-name Music \ - --item \ - '{"Artist": {"S": "No One You Know"}, "SongTitle": {"S": "Call Me Today"}, "AlbumTitle": {"S": "Somewhat Famous"}, "Awards": {"N": "1"}}') - - check_error "$ITEM1_OUTPUT" "put-item (item 1)" - echo "$ITEM1_OUTPUT" - - # Add second item - ITEM2_OUTPUT=$(aws dynamodb put-item \ - --table-name Music \ - --item \ - '{"Artist": {"S": "No One You Know"}, "SongTitle": {"S": "Howdy"}, "AlbumTitle": {"S": "Somewhat Famous"}, "Awards": {"N": "2"}}') - - check_error "$ITEM2_OUTPUT" "put-item (item 2)" - echo "$ITEM2_OUTPUT" - - # Add third item - ITEM3_OUTPUT=$(aws dynamodb put-item \ - --table-name Music \ - --item \ - '{"Artist": {"S": "Acme Band"}, "SongTitle": {"S": "Happy Day"}, "AlbumTitle": {"S": "Songs About Life"}, "Awards": {"N": "10"}}') - - check_error "$ITEM3_OUTPUT" "put-item (item 3)" - echo "$ITEM3_OUTPUT" - - # Add fourth item - ITEM4_OUTPUT=$(aws dynamodb put-item \ - --table-name Music \ - --item \ - '{"Artist": {"S": "Acme Band"}, "SongTitle": {"S": "PartiQL Rocks"}, "AlbumTitle": {"S": "Another Album Title"}, "Awards": {"N": "8"}}') - - check_error "$ITEM4_OUTPUT" "put-item (item 4)" - echo "$ITEM4_OUTPUT" + echo "Step 2: Writing data to the $TABLE_NAME table..." + + # Use a temporary file for item data + ITEMS_TEMP=$(mktemp) + trap "rm -f '$ITEMS_TEMP'" EXIT + + cat > "$ITEMS_TEMP" << 'EOF' + {"Artist": {"S": "No One You Know"}, "SongTitle": {"S": "Call Me Today"}, "AlbumTitle": {"S": "Somewhat Famous"}, "Awards": {"N": "1"}} + {"Artist": {"S": "No One You Know"}, "SongTitle": {"S": "Howdy"}, "AlbumTitle": {"S": "Somewhat Famous"}, "Awards": {"N": "2"}} + {"Artist": {"S": "Acme Band"}, "SongTitle": {"S": "Happy Day"}, "AlbumTitle": {"S": "Songs About Life"}, "Awards": {"N": "10"}} + {"Artist": {"S": "Acme Band"}, "SongTitle": {"S": "PartiQL Rocks"}, "AlbumTitle": {"S": "Another Album Title"}, "Awards": {"N": "8"}} + EOF + + declare -i item_num=0 + while IFS= read -r item_data; do + ((item_num++)) + ITEM_OUTPUT=$(aws dynamodb put-item \ + --table-name "$TABLE_NAME" \