사물 인터넷(IoT) 장치 보호 시작하기
사물 인터넷(IoT) 장치 보호 시작하기
이 코드 예제에서는 AWS IoT Device Defender를 사용해 감사(audit) 검사를 활성화하고, 결과를 확인하며, 완화(mitigation) 조치를 만드는 방법을 보여드려요.
출처: 문서
본문
다음 작업을 다루어요.
- 필요한 IAM 역할 생성
- IoT Device Defender 감사 검사 활성화
- 주문형(On-Demand) 감사 실행
- 완화 조치(Mitigation Action) 생성
- 감사 결과(finding)에 완화 조치 적용
- SNS 알림 설정(선택)
- IoT 로깅 활성화
Bash (AWS CLI with Bash script)
Note GitHub에 더 많은 내용이 있어요. 전체 예제와 설정·실행 방법은 Sample developer tutorials 저장소에서 확인할 수 있어요.
이 스크립트는 IoT 감사·로깅·완화 작업에 필요한 IAM 역할을 만들고, 감사 검사를 활성화한 뒤 주문형 감사를 실행하고 완화 조치를 적용해요.
#!/bin/bash
# AWS IoT Device Defender Getting Started Script
# This script demonstrates how to use AWS IoT Device Defender to enable audit checks,
# view audit results, create mitigation actions, and apply them to findings.
set -euo pipefail
# Set up logging
LOG_FILE="iot-device-defender-script-$(date +%Y%m%d%H%M%S).log"
exec > >(tee -a "$LOG_FILE") 2>&1
echo "==================================================="
echo "AWS IoT Device Defender Getting Started Script"
echo "==================================================="
echo "Starting script execution at $(date)"
echo ""
# Function to check for errors in command output
check_error() {
if echo "$1" | grep -iE "An error occurred|Exception|Failed|usage: aws" > /dev/null; then
echo "ERROR: Command failed with the following output:"
echo "$1"
return 1
fi
return 0
}
# Function to safely extract JSON values using jq
extract_json_value() {
local json="$1"
local key="$2"
echo "$json" | jq -r ".${key} // empty" 2>/dev/null || echo ""
}
# Function to validate JSON
validate_json() {
local json="$1"
echo "$json" | jq empty 2>/dev/null
}
# Function to check AWS CLI availability
check_aws_cli() {
if ! command -v aws &> /dev/null; then
echo "ERROR: AWS CLI is not installed or not in PATH"
return 1
fi
if ! command -v jq &> /dev/null; then
echo "ERROR: jq is not installed or not in PATH"
return 1
fi
return 0
}
# Function to get AWS account ID
get_account_id() {
local account_id
account_id=$(aws sts get-caller-identity --query 'Account' --output text 2>/dev/null) || true
if [ -z "$account_id" ]; then
echo "ERROR: Could not retrieve AWS account ID"
return 1
fi
echo "$account_id"
return 0
}
# Function to create IAM roles with retry logic
create_iam_role() {
local ROLE_NAME=$1
local TRUST_POLICY=$2
local MANAGED_POLICY=$3
local RETRY_COUNT=0
local MAX_RETRIES=3
echo "Creating IAM role: $ROLE_NAME"
# Validate trust policy JSON
if ! validate_json "$TRUST_POLICY"; then
echo "ERROR: Invalid trust policy JSON for role $ROLE_NAME"
return 1
fi
# Check if role already exists
if aws iam get-role --role-name "$ROLE_NAME" >/dev/null 2>&1; then
echo "Role $ROLE_NAME already exists, skipping creation"
ROLE_ARN=$(aws iam get-role --role-name "$ROLE_NAME" --query 'Role.Arn' --output text 2>/dev/null) || true
if [ -z "$ROLE_ARN" ]; then
echo "ERROR: Could not retrieve ARN for existing role $ROLE_NAME"
return 1
fi
echo "Role ARN: $ROLE_ARN"
return 0
fi
# Create the role with trust policy and retry logic
while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do
ROLE_RESULT=$(aws iam create-role \
--role-name "$ROLE_NAME" \
--assume-role-policy-document "$TRUST_POLICY" 2>&1) || true
if check_error "$ROLE_RESULT"; then
break
fi
RETRY_COUNT=$((RETRY_COUNT + 1))
if [ $RETRY_COUNT -lt $MAX_RETRIES ]; then
echo "Retrying role creation (attempt $((RETRY_COUNT + 1))/$MAX_RETRIES)..."
sleep $((RETRY_COUNT * 2))
fi
done
if ! check_error "$ROLE_RESULT"; then
echo "Failed to create role $ROLE_NAME after $MAX_RETRIES attempts"
return 1
fi
aws iam tag-role --role-name "$ROLE_NAME" --tags Key=project,Value=doc-smith Key=tutorial,Value=aws-iot-device-defender-gs 2>&1 || true
# For IoT logging role, create an inline policy instead of using a managed policy
if [[ "$ROLE_NAME" == "AWSIoTLoggingRole" ]]; then
local LOGGING_POLICY
LOGGING_POLICY=$(cat <<'EOF'
{
"Version":"2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents",
"logs:PutMetricFilter",
"logs:PutRetentionPolicy",
"logs:GetLogEvents",
"logs:DescribeLogStreams"
],
"Resource": "arn:aws:logs:*:*:*"
}
]
}
EOF
)
if ! validate_json "$LOGGING_POLICY"; then
echo "ERROR: Invalid logging policy JSON"
return 1
fi
POLICY_RESULT=$(aws iam put-role-policy \
--role-name "$ROLE_NAME" \
--policy-name "${ROLE_NAME}Policy" \
--policy-document "$LOGGING_POLICY" 2>&1) || true
if ! check_error "$POLICY_RESULT"; then
echo "Failed to attach inline policy to role $ROLE_NAME"
return 1
fi
elif [[ "$ROLE_NAME" == "IoTMitigationActionErrorLoggingRole" ]]; then
local MITIGATION_POLICY
MITIGATION_POLICY=$(cat <<'EOF'
{
"Version":"2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"iot:UpdateCACertificate",
"iot:UpdateCertificate",
"iot:SetV2LoggingOptions",
"iot:SetLoggingOptions",
"iot:AddThingToThingGroup"
],
"Resource": "arn:aws:iot:*:*:*"
},
{
"Effect": "Allow",
"Action": "iam:PassRole",
"Resource": "*",
"Condition": {
"StringEquals": {
"iam:PassedToService": "iot.amazonaws.com"
}
}
}
]
}
EOF
)
if ! validate_json "$MITIGATION_POLICY"; then
echo "ERROR: Invalid mitigation policy JSON"
return 1
fi
POLICY_RESULT=$(aws iam put-role-policy \
--role-name "$ROLE_NAME" \
--policy-name "${ROLE_NAME}Policy" \
--policy-document "$MITIGATION_POLICY" 2>&1) || true
if ! check_error "$POLICY_RESULT"; then
echo "Failed to attach inline policy to role $ROLE_NAME"
return 1
fi
else
# Attach managed policy to role if provided
if [ -n "$MANAGED_POLICY" ]; then
ATTACH_RESULT=$(aws iam attach-role-policy \
--role-name "$ROLE_NAME" \
--policy-arn "$MANAGED_POLICY" 2>&1) || true
if ! check_error "$ATTACH_RESULT"; then
echo "Failed to attach policy to role $ROLE_NAME"
return 1
fi
fi
fi
echo "Role $ROLE_NAME created successfully"
# Get the role ARN with error handling
ROLE_ARN=$(aws iam get-role --role-name "$ROLE_NAME" --query 'Role.Arn' --output text 2>/dev/null) || true
if [ -z "$ROLE_ARN" ]; then
echo "ERROR: Could not retrieve ARN for newly created role $ROLE_NAME"
return 1
fi
echo "Role ARN: $ROLE_ARN"
return 0
}
# Array to store created resources for cleanup
declare -a CREATED_RESOURCES
# Validate prerequisites
echo "Validating prerequisites..."
if ! check_aws_cli; then
echo "ERROR: Prerequisites not met"
exit 1
fi
ACCOUNT_ID=$(get_account_id) || exit 1
echo "AWS Account ID: $ACCOUNT_ID"
echo ""
# Step 1: Create IAM roles needed for the tutorial
echo "==================================================="
echo "Step 1: Creating required IAM roles"
echo "==================================================="
# Create IoT Device Defender Audit role
IOT_DEFENDER_AUDIT_TRUST_POLICY=$(cat <<'EOF'
{
"Version":"2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "iot.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
EOF
)
if ! create_iam_role "AWSIoTDeviceDefenderAuditRole" "$IOT_DEFENDER_AUDIT_TRUST_POLICY" "arn:aws:iam::aws:policy/service-role/AWSIoTDeviceDefenderAudit"; then
echo "ERROR: Failed to create audit role"
exit 1
fi
AUDIT_ROLE_ARN=$ROLE_ARN
CREATED_RESOURCES+=("IAM Role: AWSIoTDeviceDefenderAuditRole")
# Create IoT Logging role
IOT_LOGGING_TRUST_POLICY=$(cat <<'EOF'
{
"Version":"2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "iot.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
EOF
)
if ! create_iam_role "AWSIoTLoggingRole" "$IOT_LOGGING_TRUST_POLICY" ""; then
echo "ERROR: Failed to create logging role"
exit 1
fi
LOGGING_ROLE_ARN=$ROLE_ARN
CREATED_RESOURCES+=("IAM Role: AWSIoTLoggingRole")
# Create IoT Mitigation Action role
IOT_MITIGATION_TRUST_POLICY=$(cat <<'EOF'
{
"Version":"2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "iot.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
EOF
)
if ! create_iam_role "IoTMitigationActionErrorLoggingRole" "$IOT_MITIGATION_TRUST_POLICY" ""; then
echo "ERROR: Failed to create mitigation role"
exit 1
fi
MITIGATION_ROLE_ARN=$ROLE_ARN
CREATED_RESOURCES+=("IAM Role: IoTMitigationActionErrorLoggingRole")
# Wait for IAM role propagation
echo "Waiting for IAM role propagation..."
sleep 5
# Step 2: Enable audit checks
echo ""
echo "==================================================="
echo "Step 2: Enabling AWS IoT Device Defender audit checks"
echo "==================================================="
# Get current audit configuration
echo "Getting current audit configuration..."
CURRENT_CONFIG=$(aws iot describe-account-audit-configuration --output json 2>&1) || true
if validate_json "$CURRENT_CONFIG"; then
echo "$CURRENT_CONFIG" | jq '.' 2>/dev/null || echo "Could not parse current configuration"
fi
# Enable specific audit checks with proper JSON escaping
echo "Enabling audit checks..."
AUDIT_CONFIG='{"LOGGING_DISABLED_CHECK":{"enabled":true}}'
if ! validate_json "$AUDIT_CONFIG"; then
echo "ERROR: Invalid audit configuration JSON"
exit 1
fi
UPDATE_RESULT=$(aws iot update-account-audit-configuration \
--role-arn "$AUDIT_ROLE_ARN" \
--audit-check-configurations "$AUDIT_CONFIG" 2>&1) || true
if ! check_error "$UPDATE_RESULT"; then
echo "Failed to update audit configuration"
exit 1
fi
echo "Audit checks enabled successfully"
# Step 3: Run an on-demand audit
echo ""
echo "==================================================="
echo "Step 3: Running an on-demand audit"
echo "==================================================="
echo "Starting on-demand audit task..."
AUDIT_TASK_RESULT=$(aws iot start-on-demand-audit-task \
--target-check-names LOGGING_DISABLED_CHECK --output json 2>&1) || true
if ! check_error "$AUDIT_TASK_RESULT"; then
echo "Failed to start on-demand audit task"
exit 1
fi
TASK_ID=$(extract_json_value "$AUDIT_TASK_RESULT" "taskId")
if [ -z "$TASK_ID" ]; then
echo "ERROR: Could not extract task ID from response"
exit 1
fi
echo "Audit task started with ID: $TASK_ID"
CREATED_RESOURCES+=("Audit Task: $TASK_ID")
# Tag the audit task via IoT service
aws iot tag-resource --resource-arn "arn:aws:iot:$(aws configure get region):${ACCOUNT_ID}:audittask/${TASK_ID}" --tags Key=project,Value=doc-smith Key=tutorial,Value=aws-iot-device-defender-gs 2>&1 || true
# Wait for the audit task to complete
echo "Waiting for audit task to complete (this may take a few minutes)..."
TASK_STATUS="IN_PROGRESS"
TIMEOUT=0
MAX_TIMEOUT=600
POLL_INTERVAL=15
while [ "$TASK_STATUS" != "COMPLETED" ]; do
if [ $TIMEOUT -ge $MAX_TIMEOUT ]; then
echo "WARNING: Audit task did not complete within ${MAX_TIMEOUT} seconds, continuing..."
break
fi
sleep "$POLL_INTERVAL"
TIMEOUT=$((TIMEOUT + POLL_INTERVAL))
TASK_DETAILS=$(aws iot describe-audit-task --task-id "$TASK_ID" --output json 2>&1) || true
if validate_json "$TASK_DETAILS"; then
TASK_STATUS=$(extract_json_value "$TASK_DETAILS" "taskStatus")
echo "Current task status: $TASK_STATUS (elapsed: ${TIMEOUT}s)"
if [ "$TASK_STATUS" = "FAILED" ]; then
echo "WARNING: Audit task failed, continuing with script..."
FAILURE_REASON=$(extract_json_value "$TASK_DETAILS" "taskStatistics.failedChecksNotApplicable")
if [ -n "$FAILURE_REASON" ]; then
echo "Reason: $FAILURE_REASON"
fi
break
fi
else
echo "WARNING: Could not parse task details, retrying..."
fi
done
echo "Audit task processing completed"
# Get audit findings (non-blocking)
echo "Getting audit findings..."
FINDINGS=$(aws iot list-audit-findings \
--task-id "$TASK_ID" --output json 2>&1) || true
if validate_json "$FINDINGS"; then
FINDING_COUNT=$(echo "$FINDINGS" | jq '.findings | length' 2>/dev/null || echo "0")
echo "Audit findings count: $FINDING_COUNT"
if [ "$FINDING_COUNT" -gt 0 ]; then
echo "Sample finding:"
echo "$FINDINGS" | jq '.findings[0]' 2>/dev/null || echo "Could not parse finding"
fi
else
echo "WARNING: Could not parse audit findings response"
FINDINGS='{"findings":[]}'
fi
# Check if we have any non-compliant findings
FINDING_ID=$(extract_json_value "$FINDINGS" "findings[0].findingId")
if [ -n "$FINDING_ID" ]; then
echo "Found non-compliant finding with ID: $FINDING_ID"
HAS_FINDINGS=true
else
echo "No non-compliant findings detected"
HAS_FINDINGS=false
fi
# Step 4: Create a mitigation action
echo ""
echo "==================================================="
echo "Step 4: Creating a mitigation action"
echo "==================================================="
# Check if mitigation action already exists and delete it
if aws iot describe-mitigation-action --action-name "EnableErrorLoggingAction" >/dev/null 2>&1; then
echo "Mitigation action 'EnableErrorLoggingAction' already exists, deleting it first..."
aws iot delete-mitigation-action --action-name "EnableErrorLoggingAction" 2>&1 || true
sleep 2
fi
echo "Creating mitigation action to enable AWS IoT logging..."
# Build mitigation action parameters JSON
MITIGATION_PARAMS=$(cat <<EOF
{
"enableIoTLoggingParams": {
"roleArnForLogging": "$LOGGING_ROLE_ARN",
"logLevel": "ERROR"
}
}
EOF
)
if ! validate_json "$MITIGATION_PARAMS"; then
echo "ERROR: Invalid mitigation parameters JSON"
exit 1
fi
MITIGATION_RESULT=$(aws iot create-mitigation-action \
--action-name "EnableErrorLoggingAction" \
--role-arn "$MITIGATION_ROLE_ARN" \
--action-params "$MITIGATION_PARAMS" --output json 2>&1) || true
if ! check_error "$MITIGATION_RESULT"; then
echo "Failed to create mitigation action"
exit 1
fi
if validate_json "$MITIGATION_RESULT"; then
echo "Mitigation action created successfully"
MITIGATION_ACTION_ARN=$(extract_json_value "$MITIGATION_RESULT" "actionArn")
if [ -n "$MITIGATION_ACTION_ARN" ]; then
echo "Mitigation Action ARN: $MITIGATION_ACTION_ARN"
aws iot tag-resource --resource-arn "$MITIGATION_ACTION_ARN" --tags Key=project,Value=doc-smith Key=tutorial,Value=aws-iot-device-defender-gs 2>&1 || true
fi
else
echo "WARNING: Could not validate mitigation action response, but action may have been created"
fi
CREATED_RESOURCES+=("Mitigation Action: EnableErrorLoggingAction")
# Step 5: Apply mitigation action to findings (if any)
if [ "$HAS_FINDINGS" = true ]; then
echo ""
echo "==================================================="
echo "Step 5: Applying mitigation action to findings"
echo "==================================================="
MITIGATION_TASK_ID="MitigationTask-$(date +%s)"
echo "Starting mitigation actions task with ID: $MITIGATION_TASK_ID"
# Build target JSON
TARGET_JSON=$(cat <<EOF
{
"findingIds": ["$FINDING_ID"]
}
EOF
)
if ! validate_json "$TARGET_JSON"; then
echo "ERROR: Invalid target JSON"
exit 1
fi
# Build audit check to actions mapping JSON
AUDIT_CHECK_MAPPING=$(cat <<EOF
{
"LOGGING_DISABLED_CHECK": ["EnableErrorLoggingAction"]
}
EOF
)
if ! validate_json "$AUDIT_CHECK_MAPPING"; then
echo "ERROR: Invalid audit check mapping JSON"
exit 1
fi
MITIGATION_TASK_RESULT=$(aws iot start-audit-mitigation-actions-task \
--task-id "$MITIGATION_TASK_ID" \
--target "$TARGET_JSON" \
--audit-check-to-actions-mapping "$AUDIT_CHECK_MAPPING" --output json 2>&1) || true
if ! check_error "$MITIGATION_TASK_RESULT"; then
echo "WARNING: Failed to start mitigation actions task, continuing..."
else
echo "Mitigation actions task started successfully"
CREATED_RESOURCES+=("Mitigation Task: $MITIGATION_TASK_ID")
fi
else
echo ""
echo "==================================================="
echo "Step 5: Skipping mitigation action application (no findings)"
echo "==================================================="
fi
# Step 6: Set up SNS notifications (optional)
echo ""
echo "==================================================="
echo "Step 6: Setting up SNS notifications"
echo "==================================================="
# Check if SNS topic already exists
SNS_TOPICS=$(aws sns list-topics --output json 2>&1) || true
TOPIC_ARN=""
if validate_json "$SNS_TOPICS"; then
TOPIC_ARN=$(echo "$SNS_TOPICS" | jq -r '.Topics[] | select(.TopicArn | contains("IoTDDNotifications")) | .TopicArn' 2>/dev/null | head -1 || echo "")
fi
if [ -n "$TOPIC_ARN" ]; then
echo "SNS topic 'IoTDDNotifications' already exists, using existing topic..."
echo "Topic ARN: $TOPIC_ARN"
else
echo "Creating SNS topic for notifications..."
SNS_RESULT=$(aws sns create-topic --name "IoTDDNotifications" --tags Key=project,Value=doc-smith Key=tutorial,Value=aws-iot-device-defender-gs --output json 2>&1) || true
if ! check_error "$SNS_RESULT"; then
echo "WARNING: Failed to create SNS topic, continuing..."
SNS_RESULT=""
else
TOPIC_ARN=$(extract_json_value "$SNS_RESULT" "TopicArn")
if [ -n "$TOPIC_ARN" ]; then
echo "SNS topic created with ARN: $TOPIC_ARN"
CREATED_RESOURCES+=("SNS Topic: IoTDDNotifications")
fi
fi
fi
if [ -n "$TOPIC_ARN" ]; then
echo "Updating audit configuration to enable SNS notifications..."
# Build SNS notification configuration JSON
SNS_CONFIG=$(cat <<EOF
{
"SNS": {
"targetArn": "$TOPIC_ARN",
"roleArn": "$AUDIT_ROLE_ARN",
"enabled": true
}
}
EOF
)
if ! validate_json "$SNS_CONFIG"; then
echo "ERROR: Invalid SNS configuration JSON"
exit 1
fi
SNS_UPDATE_RESULT=$(aws iot update-account-audit-configuration \
--audit-notification-target-configurations "$SNS_CONFIG" 2>&1) || true
if ! check_error "$SNS_UPDATE_RESULT"; then
echo "WARNING: Failed to update audit configuration for SNS notifications"
else
echo "SNS notifications enabled successfully"
fi
else
echo "Skipping SNS configuration due to topic creation failure"
fi
# Step 7: Enable AWS IoT logging
echo ""
echo "==================================================="
echo "Step 7: Enabling AWS IoT logging"
echo "==================================================="
echo "Setting up AWS IoT logging options..."
LOGGING_RESULT=$(aws iot set-v2-logging-options \
--role-arn "$LOGGING_ROLE_ARN" \
--default-log-level "ERROR" 2>&1) || true
if ! check_error "$LOGGING_RESULT"; then
echo "V2 logging setup failed, trying v1 logging..."
V1_LOGGING_CONFIG=$(cat <<EOF
{
"roleArn": "$LOGGING_ROLE_ARN",
"logLevel": "ERROR"
}
EOF
)
if ! validate_json "$V1_LOGGING_CONFIG"; then
echo "ERROR: Invalid v1 logging configuration JSON"
exit 1
fi
LOGGING_RESULT_V1=$(aws iot set-logging-options \
--logging-options-payload "$V1_LOGGING_CONFIG" 2>&1) || true
if ! check_error "$LOGGING_RESULT_V1"; then
echo "WARNING: Failed to set up AWS IoT logging with both v1 and v2 methods, continuing..."
else
echo "AWS IoT v1 logging enabled successfully"
fi
else
echo "AWS IoT v2 logging enabled successfully"
fi
# Verify logging is enabled
echo "Verifying logging configuration..."
LOGGING_CONFIG=$(aws iot get-v2-logging-options --output json 2>&1) || true
if [ -n "$LOGGING_CONFIG" ] && ! check_error "$LOGGING_CONFIG" && validate_json "$LOGGING_CONFIG"; then
echo "Logging configuration verified"
echo "$LOGGING_CONFIG" | jq '.' 2>/dev/null || echo "Configuration retrieved but could not display details"
else
echo "Could not verify logging configuration, but setup completed"
fi
# Script completed successfully
echo ""
echo "==================================================="
echo "AWS IoT Device Defender setup completed successfully!"
echo "==================================================="
echo "The following resources were created:"
for resource in "${CREATED_RESOURCES[@]+"${CREATED_RESOURCES[@]}"}"; do
echo "- $resource"
done
echo ""
# Cleanup phase
echo "==========================================="
echo "CLEANUP"
echo "==========================================="
echo "Starting automatic cleanup of resources..."
echo "Waiting 10 seconds before cleanup to allow resource stabilization..."
sleep 10
# Disable AWS IoT logging
echo "Disabling AWS IoT logging..."
DISABLE_V2_RESULT=$(aws iot set-v2-logging-options \
--default-log-level "DISABLED" 2>&1) || true
if check_error "$DISABLE_V2_RESULT"; then
echo "V2 logging disabled successfully"
else
echo "Attempting v1 logging disable..."
V1_DISABLE_CONFIG=$(cat <<'EOF'
{
"logLevel": "DISABLED"
}
EOF
)
DISABLE_V1_RESULT=$(aws iot set-logging-options \
--logging-options-payload "$V1_DISABLE_CONFIG" 2>&1) || true
if check_error "$DISABLE_V1_RESULT"; then
echo "V1 logging disabled successfully"
else
echo "WARNING: Could not disable logging"
fi
fi
# Delete mitigation action
echo "Deleting mitigation action..."
aws iot delete-mitigation-action --action-name "EnableErrorLoggingAction" 2>&1 || true
# Reset audit configuration
echo "Resetting IoT Device Defender audit configuration..."
RESET_AUDIT_CONFIG='{"LOGGING_DISABLED_CHECK":{"enabled":false}}'
aws iot update-account-audit-configuration \
--audit-check-configurations "$RESET_AUDIT_CONFIG" 2>&1 || true
# Delete SNS topic
echo "Deleting SNS topic..."
if [ -n "${TOPIC_ARN:-}" ] && [ "$TOPIC_ARN" != "null" ]; then
aws sns delete-topic --topic-arn "$TOPIC_ARN" 2>&1 || true
fi
# Clean up IAM roles with improved error handling
echo "Cleaning up IAM roles..."
cleanup_role() {
local role_name=$1
echo "Cleaning up role: $role_name"
if aws iam get-role --role-name "$role_name" >/dev/null 2>&1; then
ROLE_POLICIES=$(aws iam list-role-policies --role-name "$role_name" --output json 2>&1 || echo '{"PolicyNames":[]}')
if validate_json "$ROLE_POLICIES"; then
while IFS= read -r policy_name; do
if [ -n "$policy_name" ] && [ "$policy_name" != "null" ]; then
echo " Deleting inline policy: $policy_name"
aws iam delete-role-policy \
--role-name "$role_name" \
--policy-name "$policy_name" 2>&1 || true
fi
done < <(echo "$ROLE_POLICIES" | jq -r '.PolicyNames[]' 2>/dev/null || echo "")
fi
ATTACHED_POLICIES=$(aws iam list-attached-role-policies --role-name "$role_name" --output json 2>&1 || echo '{"AttachedPolicies":[]}')
if validate_json "$ATTACHED_POLICIES"; then
while IFS= read -r policy_arn; do
if [ -n "$policy_arn" ] && [ "$policy_arn" != "null" ]; then
echo " Detaching managed policy: $policy_arn"
aws iam detach-role-policy \
--role-name "$role_name" \
--policy-arn "$policy_arn" 2>&1 || true
fi
done < <(echo "$ATTACHED_POLICIES" | jq -r '.AttachedPolicies[].PolicyArn' 2>/dev/null || echo "")
fi
echo " Deleting role: $role_name"
aws iam delete-role --role-name "$role_name" 2>&1 || true
else
echo " Role $role_name does not exist or already deleted"
fi
}
cleanup_role "AWSIoTDeviceDefenderAuditRole"
cleanup_role "AWSIoTLoggingRole"
cleanup_role "IoTMitigationActionErrorLoggingRole"
echo "Cleanup completed successfully"
echo ""
echo "Script execution completed at $(date)"
echo "Log file: $LOG_FILE"
API 상세는 AWS CLI Command Reference의 다음 항목을 참고해요.
AttachRolePolicy,CreateMitigationAction,CreateRole,CreateTopic,DeleteAccountAuditConfiguration,DeleteMitigationAction,DeleteRole,DeleteRolePolicy,DeleteTopic,DescribeAccountAuditConfiguration,DescribeAuditTask,DetachRolePolicy,GetLoggingOptions,GetRole,GetV2LoggingOptions,ListAuditFindings,ListAuditMitigationActionsTasks,ListMitigationActions,ListRolePolicies,ListTopics,PutRolePolicy,SetLoggingOptions,SetV2LoggingOptions,StartAuditMitigationActionsTask,StartOnDemandAuditTask,UpdateAccountAuditConfiguration