구성 관리 시작하기
구성 관리 시작하기
이 코드 예제에서는 AWS CLI로 AWS Config를 설정하는 방법을 보여드려요.
출처: 문서
본문
다음 작업을 다루어요.
- Amazon S3 버킷 생성
- Amazon SNS 주제 생성
- Config용 IAM 역할 생성
- Config 구성 레코더(configuration recorder) 설정
- Config 전달 채널(delivery channel) 설정
- 구성 레코더 시작
- Config 설정 검증
Bash (AWS CLI with Bash script)
Note GitHub에 더 많은 내용이 있어요. 전체 예제와 설정·실행 방법은 Sample developer tutorials 저장소에서 확인할 수 있어요.
이 스크립트는 S3 버킷과 SNS 주제, IAM 역할을 만들고 AWS Config의 구성 레코더·전달 채널을 설정해요.
#!/bin/bash
# AWS Config Setup Script (v2)
# This script sets up AWS Config with the AWS CLI
# Error handling
set -e
LOGFILE="aws-config-setup-v2.log"
touch $LOGFILE
exec > >(tee -a $LOGFILE)
exec 2>&1
# Function to handle errors
handle_error() {
echo "ERROR: An error occurred at line $1"
echo "Attempting to clean up resources..."
cleanup_resources
exit 1
}
# Set trap for error handling
trap 'handle_error $LINENO' ERR
# Function to generate random identifier
generate_random_id() {
echo $(openssl rand -hex 6)
}
# Function to check if command was successful
check_command() {
if echo "$1" | grep -i "error" > /dev/null; then
echo "ERROR: $1"
return 1
fi
return 0
}
# Function to clean up resources
cleanup_resources() {
if [ -n "$CONFIG_RECORDER_NAME" ]; then
echo "Stopping configuration recorder..."
aws configservice stop-configuration-recorder --configuration-recorder-name "$CONFIG_RECORDER_NAME" 2>/dev/null || true
fi
# Check if we created a new delivery channel before trying to delete it
if [ -n "$DELIVERY_CHANNEL_NAME" ] && [ "$CREATED_NEW_DELIVERY_CHANNEL" = "true" ]; then
echo "Deleting delivery channel..."
aws configservice delete-delivery-channel --delivery-channel-name "$DELIVERY_CHANNEL_NAME" 2>/dev/null || true
fi
if [ -n "$CONFIG_RECORDER_NAME" ] && [ "$CREATED_NEW_CONFIG_RECORDER" = "true" ]; then
echo "Deleting configuration recorder..."
aws configservice delete-configuration-recorder --configuration-recorder-name "$CONFIG_RECORDER_NAME" 2>/dev/null || true
fi
if [ -n "$ROLE_NAME" ]; then
if [ -n "$POLICY_NAME" ]; then
echo "Detaching custom policy from role..."
aws iam delete-role-policy --role-name "$ROLE_NAME" --policy-name "$POLICY_NAME" 2>/dev/null || true
fi
if [ -n "$MANAGED_POLICY_ARN" ]; then
echo "Detaching managed policy from role..."
aws iam detach-role-policy --role-name "$ROLE_NAME" --policy-arn "$MANAGED_POLICY_ARN" 2>/dev/null || true
fi
echo "Deleting IAM role..."
aws iam delete-role --role-name "$ROLE_NAME" 2>/dev/null || true
fi
if [ -n "$SNS_TOPIC_ARN" ]; then
echo "Deleting SNS topic..."
aws sns delete-topic --topic-arn "$SNS_TOPIC_ARN" 2>/dev/null || true
fi
if [ -n "$S3_BUCKET_NAME" ]; then
echo "Emptying S3 bucket..."
aws s3 rm "s3://$S3_BUCKET_NAME" --recursive 2>/dev/null || true
echo "Deleting S3 bucket..."
if [ "$BUCKET_IS_SHARED" = "false" ]; then
aws s3api delete-bucket --bucket "$S3_BUCKET_NAME" 2>/dev/null || true
fi
fi
}
# Function to display created resources
display_resources() {
echo ""
echo "==========================================="
echo "CREATED RESOURCES"
echo "==========================================="
echo "S3 Bucket: $S3_BUCKET_NAME"
echo "SNS Topic ARN: $SNS_TOPIC_ARN"
echo "IAM Role: $ROLE_NAME"
if [ "$CREATED_NEW_CONFIG_RECORDER" = "true" ]; then
echo "Configuration Recorder: $CONFIG_RECORDER_NAME (newly created)"
else
echo "Configuration Recorder: $CONFIG_RECORDER_NAME (existing)"
fi
if [ "$CREATED_NEW_DELIVERY_CHANNEL" = "true" ]; then
echo "Delivery Channel: $DELIVERY_CHANNEL_NAME (newly created)"
else
echo "Delivery Channel: $DELIVERY_CHANNEL_NAME (existing)"
fi
echo "==========================================="
}
# Get AWS account ID
echo "Getting AWS account ID..."
ACCOUNT_ID=$(aws sts get-caller-identity --query "Account" --output text)
if [ -z "$ACCOUNT_ID" ]; then
echo "ERROR: Failed to get AWS account ID"
exit 1
fi
echo "AWS Account ID: $ACCOUNT_ID"
# Generate random identifier for resources
RANDOM_ID=$(generate_random_id)
echo "Generated random identifier: $RANDOM_ID"
# Step 1: Create an S3 bucket
# Check for shared prereq bucket
PREREQ_BUCKET=$(aws cloudformation describe-stacks --stack-name tutorial-prereqs-bucket \
--query 'Stacks[0].Outputs[?OutputKey==`BucketName`].OutputValue' --output text 2>/dev/null)
if [ -n "$PREREQ_BUCKET" ] && [ "$PREREQ_BUCKET" != "None" ]; then
S3_BUCKET_NAME="$PREREQ_BUCKET"
BUCKET_IS_SHARED=true
echo "Using shared bucket: $S3_BUCKET_NAME"
else
BUCKET_IS_SHARED=false
S3_BUCKET_NAME="configservice-${RANDOM_ID}"
echo "Creating S3 bucket: $S3_BUCKET_NAME"
fi
# Get the current region
AWS_REGION=$(aws configure get region)
if [ -z "$AWS_REGION" ]; then
AWS_REGION="us-east-1" # Default to us-east-1 if no region is configured
fi
echo "Using AWS Region: $AWS_REGION"
# Create bucket with appropriate command based on region
if [ "$BUCKET_IS_SHARED" = "false" ]; then
if [ "$AWS_REGION" = "us-east-1" ]; then
BUCKET_RESULT=$(aws s3api create-bucket --bucket "$S3_BUCKET_NAME")
else
BUCKET_RESULT=$(aws s3api create-bucket --bucket "$S3_BUCKET_NAME" --create-bucket-configuration LocationConstraint="$AWS_REGION")
fi
check_command "$BUCKET_RESULT"
echo "S3 bucket created: $S3_BUCKET_NAME"
aws s3api put-bucket-tagging --bucket "$S3_BUCKET_NAME" --tagging 'TagSet=[{Key=project,Value=doc-smith},{Key=tutorial,Value=aws-config-gs}]'
echo "Tags applied to S3 bucket"
else
echo "Using shared bucket: $S3_BUCKET_NAME (skipping creation)"
fi
# Block public access for the bucket
aws s3api put-public-access-block \
--bucket "$S3_BUCKET_NAME" \
--public-access-block-configuration "BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true"
echo "Public access blocked for bucket"
# Step 2: Create an SNS topic
TOPIC_NAME="config-topic-${RANDOM_ID}"
echo "Creating SNS topic: $TOPIC_NAME"
SNS_RESULT=$(aws sns create-topic --name "$TOPIC_NAME" --tags Key=project,Value=doc-smith Key=tutorial,Value=aws-config-gs)
check_command "$SNS_RESULT"
SNS_TOPIC_ARN=$(echo "$SNS_RESULT" | grep -o 'arn:aws:sns:[^"]*')
echo "SNS topic created: $SNS_TOPIC_ARN"
# Step 3: Create an IAM role for AWS Config
ROLE_NAME="config-role-${RANDOM_ID}"
POLICY_NAME="config-delivery-permissions"
MANAGED_POLICY_ARN="arn:aws:iam::aws:policy/service-role/AWS_ConfigRole"
echo "Creating trust policy document..."
cat > config-trust-policy.json << EOF
{
"Version":"2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "config.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
EOF
echo "Creating IAM role: $ROLE_NAME"
ROLE_RESULT=$(aws iam create-role --role-name "$ROLE_NAME" --assume-role-policy-document file://config-trust-policy.json)
check_command "$ROLE_RESULT"
ROLE_ARN=$(echo "$ROLE_RESULT" | grep -o 'arn:aws:iam::[^"]*' | head -1)
echo "IAM role created: $ROLE_ARN"
aws iam tag-role --role-name "$ROLE_NAME" --tags Key=project,Value=doc-smith Key=tutorial,Value=aws-config-gs
echo "Tags applied to IAM role"
echo "Attaching AWS managed policy to role..."
ATTACH_RESULT=$(aws iam attach-role-policy --role-name "$ROLE_NAME" --policy-arn "$MANAGED_POLICY_ARN")
check_command "$ATTACH_RESULT"
echo "AWS managed policy attached"
echo "Creating custom policy document for S3 and SNS access..."
cat > config-delivery-permissions.json << EOF
{
"Version":"2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:PutObject"
],
"Resource": "arn:aws:s3:::${S3_BUCKET_NAME}/AWSLogs/${ACCOUNT_ID}/*",
"Condition": {
"StringLike": {
"s3:x-amz-acl": "bucket-owner-full-control"
}
}
},
{
"Effect": "Allow",
"Action": [
"s3:GetBucketAcl"
],
"Resource": "arn:aws:s3:::${S3_BUCKET_NAME}"
},
{
"Effect": "Allow",
"Action": [
"sns:Publish"
],
"Resource": "${SNS_TOPIC_ARN}"
}
]
}
EOF
echo "Attaching custom policy to role..."
POLICY_RESULT=$(aws iam put-role-policy --role-name "$ROLE_NAME" --policy-name "$POLICY_NAME" --policy-document file://config-delivery-permissions.json)
check_command "$POLICY_RESULT"
echo "Custom policy attached"
# Wait for IAM role to propagate
echo "Waiting for IAM role to propagate (15 seconds)..."
sleep 15
# Step 4: Check if configuration recorder already exists
CONFIG_RECORDER_NAME="default"
CREATED_NEW_CONFIG_RECORDER="false"
echo "Checking for existing configuration recorder..."
EXISTING_RECORDERS=$(aws configservice describe-configuration-recorders 2>/dev/null || echo "")
if echo "$EXISTING_RECORDERS" | grep -q "name"; then
echo "Configuration recorder already exists. Will update it."
# Get the name of the existing recorder
CONFIG_RECORDER_NAME=$(echo "$EXISTING_RECORDERS" | grep -o '"name": "[^"]*"' | head -1 | cut -d'"' -f4)
echo "Using existing configuration recorder: $CONFIG_RECORDER_NAME"
else
echo "No existing configuration recorder found. Will create a new one."
CREATED_NEW_CONFIG_RECORDER="true"
fi
echo "Creating configuration recorder configuration..."
cat > configurationRecorder.json << EOF
{
"name": "${CONFIG_RECORDER_NAME}",
"roleARN": "${ROLE_ARN}",
"recordingMode": {
"recordingFrequency": "CONTINUOUS"
}
}
EOF
echo "Creating recording group configuration..."
cat > recordingGroup.json << EOF
{
"allSupported": true,
"includeGlobalResourceTypes": true
}
EOF
echo "Setting up configuration recorder..."
RECORDER_RESULT=$(aws configservice put-configuration-recorder --configuration-recorder file://configurationRecorder.json --recording-group file://recordingGroup.json)
check_command "$RECORDER_RESULT"
echo "Configuration recorder set up"
if [ "$CREATED_NEW_CONFIG_RECORDER" = "true" ]; then
aws configservice tag-resource --resource-arn "arn:aws:config:${AWS_REGION}:${ACCOUNT_ID}:config-recorder/${CONFIG_RECORDER_NAME}" --tags Key=project,Value=doc-smith Key=tutorial,Value=aws-config-gs
echo "Tags applied to configuration recorder"
fi
# Step 5: Check if delivery channel already exists
DELIVERY_CHANNEL_NAME="default"
CREATED_NEW_DELIVERY_CHANNEL="false"
echo "Checking for existing delivery channel..."
EXISTING_CHANNELS=$(aws configservice describe-delivery-channels 2>/dev/null || echo "")
if echo "$EXISTING_CHANNELS" | grep -q "name"; then
echo "Delivery channel already exists."
# Get the name of the existing channel
DELIVERY_CHANNEL_NAME=$(echo "$EXISTING_CHANNELS" | grep -o '"name": "[^"]*"' | head -1 | cut -d'"' -f4)
echo "Using existing delivery channel: $DELIVERY_CHANNEL_NAME"
# Update the existing delivery channel
echo "Creating delivery channel configuration for update..."
cat > deliveryChannel.json << EOF
{
"name": "${DELIVERY_CHANNEL_NAME}",
"s3BucketName": "${S3_BUCKET_NAME}",
"snsTopicARN": "${SNS_TOPIC_ARN}",
"configSnapshotDeliveryProperties": {
"deliveryFrequency": "Six_Hours"
}
}
EOF
echo "Updating delivery channel..."
CHANNEL_RESULT=$(aws configservice put-delivery-channel --delivery-channel file://deliveryChannel.json)
check_command "$CHANNEL_RESULT"
echo "Delivery channel updated"
else
echo "No existing delivery channel found. Will create a new one."
CREATED_NEW_DELIVERY_CHANNEL="true"
echo "Creating delivery channel configuration..."
cat > deliveryChannel.json << EOF
{
"name": "${DELIVERY_CHANNEL_NAME}",
"s3BucketName": "${S3_BUCKET_NAME}",
"snsTopicARN": "${SNS_TOPIC_ARN}",
"configSnapshotDeliveryProperties": {
"deliveryFrequency": "Six_Hours"
}
}
EOF
echo "Creating delivery channel..."
CHANNEL_RESULT=$(aws configservice put-delivery-channel --delivery-channel file://deliveryChannel.json)
check_command "$CHANNEL_RESULT"
echo "Delivery channel created"
aws configservice tag-resource --resource-arn "arn:aws:config:${AWS_REGION}:${ACCOUNT_ID}:delivery-channel/${DELIVERY_CHANNEL_NAME}" --tags Key=project,Value=doc-smith Key=tutorial,Value=aws-config-gs
echo "Tags applied to delivery channel"
fi
# Step 6: Start the configuration recorder
echo "Checking configuration recorder status..."
RECORDER_STATUS=$(aws configservice describe-configuration-recorder-status 2>/dev/null || echo "")
if echo "$RECORDER_STATUS" | grep -q '"recording": true'; then
echo "Configuration recorder is already running."
else
echo "Starting configuration recorder..."
START_RESULT=$(aws configservice start-configuration-recorder --configuration-recorder-name "$CONFIG_RECORDER_NAME")
check_command "$START_RESULT"
echo "Configuration recorder started"
fi
# Step 7: Verify the AWS Config setup
echo "Verifying delivery channel..."
VERIFY_CHANNEL=$(aws configservice describe-delivery-channels)
check_command "$VERIFY_CHANNEL"
echo "$VERIFY_CHANNEL"
echo "Verifying configuration recorder..."
VERIFY_RECORDER=$(aws configservice describe-configuration-recorders)
check_command "$VERIFY_RECORDER"
echo "$VERIFY_RECORDER"
echo "Verifying configuration recorder status..."
VERIFY_STATUS=$(aws configservice describe-configuration-recorder-status)
check_command "$VERIFY_STATUS"
echo "$VERIFY_STATUS"
# Display created resources
display_resources
# Ask if user wants to clean up resources
echo ""
echo "==========================================="
echo "CLEANUP CONFIRMATION"
echo "==========================================="
echo "Do you want to clean up all created resources? (y/n): "
CLEANUP_CHOICE='y'
if [[ "$CLEANUP_CHOICE" =~ ^[Yy]$ ]]; then
echo "Cleaning up resources..."
cleanup_resources
echo "Cleanup completed."
else
echo "Resources will not be cleaned up. You can manually clean them up later."
fi
echo "Script completed successfully!"
API 상세는 AWS CLI Command Reference의 다음 항목을 참고해요.
AttachRolePolicy,CreateBucket,CreateRole,CreateTopic,DeleteBucket,DeleteConfigurationRecorder,DeleteDeliveryChannel,DeleteRole,DeleteRolePolicy,DeleteTopic,DescribeConfigurationRecorderStatus,DescribeConfigurationRecorders,DescribeDeliveryChannels,DetachRolePolicy,GetCallerIdentity,PutConfigurationRecorder,PutDeliveryChannel,PutPublicAccessBlock,PutRolePolicy,Rm,StartConfigurationRecorder,StopConfigurationRecorder