Vô hiệu hóa IAM user unused trong một khoảng thời gian nhất định bằng auto remediation của AWS Config Rules (P2)

Vô hiệu hóa IAM user unused trong một khoảng thời gian nhất định bằng auto remediation của AWS Config Rules (P2)

avatar

Phong Nguyen

2025.08.10

Thử vô hiệu hóa IAM user không sử dụng trong một khoảng thời gian nhất định bằng cách sử dụng auto remediation của AWS Config Rules kết hợp Event bridge và step function

Lab Introduction

  • AWS experience: Intermediate
  • Time to complete: 30 minutes
  • AWS Region: Osaka - ap-northeast-3
  • Cost to complete: Dường như Free
  • Services used: AWS Config, SNS, EventBridge, IAM, Step Function, System Manager

Giới thiệu

Là một biện pháp bảo mật, việc định kỳ vô hiệu hóa thông tin credential của IAM user không được sử dụng trong thời gian dài là rất quan trọng.

Bằng cách sử dụng AWS Config Rule (iam-user-unused-credentials-check) và AWS Systems Manager Automation, có thể tự động vô hiệu hóa thông tin xác thực của IAM user mà các thông tin xác thực (access key, console password) không được sử dụng trong một khoảng thời gian nhất định.

Trong vận hành thông thường, có thể xem xét trường hợp vô hiệu hóa khi không sử dụng từ 90 ngày trở lên. Trong trường hợp này, nếu bị vô hiệu hóa đột ngột sẽ gây khó khăn cho user, nên đôi khi cũng muốn thông báo trước.

Bài viết này sẽ giải thích cách thông báo cho user và quản trị viên trước vài ngày trước khi vô hiệu hóa.

Architecture Diagram

Chúng ta giả định muốn thông báo theo từng giai đoạn vào 7 ngày trước và 14 ngày trước ngày dự kiến vô hiệu hóa. Để thực hiện yêu cầu này, chúng ta sẽ tạo 2 Config Rules với các parameter số ngày khác nhau.

Lý do cần 2 rules là vì EventBridge chỉ trigger 1 lần duy nhất khi thay đổi từ compliant sang non-compliant. Nghĩa là, để đảm bảo thông báo chính xác 1 lần cho mỗi timing thông báo (7 ngày trước, 14 ngày trước), cần có rule chuyên dụng cho từng timing.

Khi rule trở thành non-compliant, sẽ trigger thay đổi compliance status của AWS Config, qua EventBridge khởi động AWS Step Functions và thực hiện thông báo email qua Amazon SNS.

Lựa chọn phương thức thông báo

  • Lần này chúng ta sẽ thông báo đến email address cố định qua SNS topic

Task Details

  1. Tạo AWS Config rule
  2. Tạo State Machine
  3. Tạo EventBridge
  4. Kiểm chứng

Prerequisites

Trước khi start theo hướng dẫn này bạn cần chuẩn bị ở Region Osaka các resource sau:

  • SNS Topic đã Subscriptions bằng email

  • AWS Config đã được setting Recording is on

  • Không cần Delivery đến SNS để tránh nhận nhiều email thay đổi resource

1. Tạo AWS Config rule

Tạo AWS Config Rules.

Sử dụng AWS Managed Rule có tên iam-user-unused-credentials-check.

Tạo 2 Rule như sau:

  1. Rule Name: iam-user-unused-credentials-check-1
    • Parameters
      • maxCredentialUsageAge: 83
  2. Rule Name: iam-user-unused-credentials-check-2
    • Parameters
      • maxCredentialUsageAge: 76

2. Tạo State Machine

Name: d-tepfunc-soa-unused-credentials-notification

Input xử lý Step Function bên dưới vào mục Code:

Thay thế TopicArn bằng giá trị môi trường của bạn

{
  "Comment": "IAM User Credential Auto-Disable Alert Workflow - Send SNS notifications to target users based on Config Rule evaluation results",
  "QueryLanguage": "JSONata",
  "StartAt": "Initialize Configuration",
  "States": {
    "Initialize Configuration": {
      "Type": "Pass",
      "Comment": "Define initial configuration values: AWS Account ID, Config Rule name, and maximum unused days",
      "Assign": {
        "awsAccountId": "{% $states.input.detail.awsAccountId %}",
        "configRuleName": "{% $states.input.detail.configRuleName %}",
        "maxUnusedDays": "{% 90 %}"
      },
      "Next": "Calculate Days"
    },
    "Calculate Days": {
      "Type": "Pass",
      "Comment": "Calculate remaining days based on Config Rule name: 7 days for check-1, 14 days for check-2",
      "Assign": {
        "remainingDays": "{% $configRuleName = \"iam-credential-expiry-check-1\" ? 7 : $configRuleName = \"iam-credential-expiry-check-2\" ? 14 %}"
      },
      "Next": "Calculate Disable Deadline"
    },
    "Calculate Disable Deadline": {
      "Type": "Pass",
      "Comment": "Calculate disable deadline: current datetime + remaining days to generate YYYY/MM/DD format string",
      "Assign": {
        "disableDeadline": "{% (\n  $remainingDays := (\n    $configRuleName = \"iam-credential-expiry-check-1\" ? 7 :\n    $configRuleName = \"iam-credential-expiry-check-2\" ? 14\n  );\n  $targetDate := $toMillis($now()) + ($remainingDays * 24 * 60 * 60 * 1000);\n  $dateStr := $substring($fromMillis($targetDate), 0, 10);\n  $replace($replace($dateStr, \"-\", \"/\"), /^(\\d{4})\\/(\\d{2})\\/(\\d{2})$/, \"$1/$2/$3\")\n) %}"
      },
      "Next": "ListUsers"
    },
    "ListUsers": {
      "Comment": "Retrieve all users list and identify the user name corresponding to the user ID (resourceId)",
      "Arguments": {},
      "Assign": {
        "userName": "{% $states.result.Users[UserId=$states.input.detail.resourceId].UserName[0] %}"
      },
      "Next": "SNS Publish",
      "Resource": "arn:aws:states:::aws-sdk:iam:listUsers",
      "Type": "Task"
    },
    "SNS Publish": {
      "Arguments": {
        "TopicArn": "arn:aws:sns:ap-northeast-3:{Account-ID}:d-sns-soa-config-topic",
        "Subject": "{% 'IAM Credential Disable Notification - ' & $userName %}",
        "Message": "{% 'IAM User \"' & $userName & '\" credentials (console password or access key) will be automatically disabled in ' & $string($remainingDays) & ' days (' & $disableDeadline & ').\n\n▼ Actions required for continued use:\n・Login to AWS Management Console\n・Execute AWS operations using access keys\n\n※Credentials unused for ' & $string($maxUnusedDays) & ' days will be automatically disabled as a security measure.\n\n■ Target Information\n- AWS Account ID: ' & $awsAccountId & '\n- IAM User Name: ' & $userName & '\n- Disable Date: ' & $disableDeadline & '\n- Days Remaining: ' & $string($remainingDays) & ' days\n\nThis email is automatically generated.' %}"
      },
      "End": true,
      "Resource": "arn:aws:states:::sns:publish",
      "Type": "Task"
    }
  }
}

Created

Khi tạo State Machine, IAM role và một phần IAM policy cũng sẽ được tạo tự động.

Hoạt động của State Machine như sau:

  • Lấy AWS Account ID và Config Rule name từ event nhận được qua EventBridge từ AWS Config Rule
  • Tính số ngày còn lại dựa trên Config Rule name (7 ngày nếu là check-1, 14 ngày nếu là check-2)
  • Tính ngày dự kiến vô hiệu hóa và tạo ra định dạng YYYY/MM/DD
  • Thực hiện IAM ListUsers API để xác định user name từ resource ID
  • Gửi thông báo email qua SNS

Khi tạo State Machine, IAM role và một phần IAM policy cũng sẽ được tạo tự động. Tuy nhiên Action List User vẫn còn chưa có quyền nên chúng ta sẽ thực hiện tạo thêm policy này.

Thêm Inline policy

Sử dụng policy sau:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "iam:ListUsers"
            ],
            "Resource": "*"
        }
    ]
}

Đặt tên StepFunctionListUser và Create

3. Tạo EventBridge

Tạo EventBridge với các parameter sau

  • Rule Name: d-event-rule-soa-unused-credentials-notification-before-disable

  • Rule type: Rule with an event pattern

  • Event Pattern

    {
      "detail-type": ["Config Rules Compliance Change"],
      "source": ["aws.config"],
      "detail": {
        "configRuleName": ["iam-credential-expiry-check-1", "iam-credential-expiry-check-2"],
        "messageType": ["ComplianceChangeNotification"],
        "newEvaluationResult": {
          "complianceType": ["NON_COMPLIANT"]
        }
      }
    }
    
  • Target

    • Target types: AWS service
    • Select a target: Step Function state machine
    • State machine: d-tepfunc-soa-unused-credentials-notification

Next -> Next -> Create Rule

Rule này sẽ được trigger khi status thay đổi từ compliant sang non-compliant. Sau khi đã trigger một lần, Config rule vẫn sẽ check hàng ngày, nhưng ngay cả khi trạng thái non-compliant tiếp tục, cũng sẽ không trigger lại.

Target của EventBridge rule sẽ được set vào state machine đã tạo trước đó.

4. Kiểm chứng

4.1 Tạo user

Chúng ta sẽ tạo 1 user để test (để nếu xảy ra sai sót cũng không ảnh hưởng đến user hiện tại)

  • Name: cloudmentorpro-test1

Lấy thông tin UserId

Chạy lệnh sau ở CloudShell

aws iam get-user --user-name cloudmentorpro-test1

Lấy thông tin Config rule arn

aws configservice describe-config-rules \
  --config-rule-names "iam-user-unused-credentials-check-2" \
  --query 'ConfigRules[0].ConfigRuleArn' \
  --output text

Vì sao cần lấy 2 thông tin này thì mình sẽ giải thích sau đây.

4.2 Kiểm chứng thực thi State Machine

Để chờ đến khi State machine tự động thực thi chúng ta sẽ cần 76 và 83 ngày nữa. Để kiểm chứng xem nó work đúng mong đợi không chúng ta sẽ chạy thủ công.

Để chạy với parameter truyền vào đúng như giả lập EventBridge bắt sự kiên Non-compliant xảy ra bạn cần truyền Input khi chạy State Machine như sau:

Thay thế các thông tin sau:

  • Account ID
  • ResourceId
  • configRuleARN
{
 "version": "0",
 "id": "3262a2d6-39ab-714f-158e-00d29af1402f",
 "detail-type": "Config Rules Compliance Change",
 "source": "aws.config",
 "account": "067057696393",
 "time": "2025-07-30T07:21:24Z",
 "region": "ap-northeast-3",
 "resources": [],
 "detail": {
   "resourceId": "AIDAQ7HHTH2EWNI4RVJZY",
   "awsRegion": "ap-northeast-3",
   "awsAccountId": "067057696393",
   "configRuleName": "iam-credential-expiry-check-2",
   "recordVersion": "1.0",
   "configRuleARN": "arn:aws:config:ap-northeast-3:067057696393:config-rule/config-rule-c720nr",
   "messageType": "ComplianceChangeNotification",
   "newEvaluationResult": {
     "evaluationResultIdentifier": {
       "evaluationResultQualifier": {
         "configRuleName": "iam-credential-expiry-check-2",
         "resourceType": "AWS::IAM::User",
         "resourceId": "AIDAQ7HHTH2EWNI4RVJZY",
         "evaluationMode": "DETECTIVE"
       },
       "orderingTimestamp": "2025-07-30T07:20:49.600Z"
     },
     "complianceType": "NON_COMPLIANT",
     "resultRecordedTime": "2025-07-30T07:21:24.168Z",
     "configRuleInvokedTime": "2025-07-30T07:20:53.047Z"
   },
   "notificationCreationTime": "2025-07-30T07:21:24.867Z",
   "resourceType": "AWS::IAM::User"
 }
}

Run State machine

Vậy là các Step trong state machine đã run thành công

Kiểm tra email

Challenge

Cũng sử dụng AWS managed rule: iam-user-unused-credentials-check, trường hợp User không hoạt động quá 90 ngày, bằng cách kết hợp AWS Config Rules và Systems Manager Automation, có thể vô hiệu hóa console password và access key của IAM user không được sử dụng trong 90 ngày

Cách làm

  1. Tạo Config rule: am-user-unused-credentials-check
    • maxCredentialUsageAge: 90
  2. Tạo Remediation action cho rule này
    • Action: AWSConfigRemediation-RevokeUnusedIAMUserCredentials
    • Có 1 điều đang tiếc là Document này không có ở Region Osaka, Vậy nên nếu để làm Challenge này bạn phải chuyển Sang Region khác như Tokyo hay N. Virginia
    • Document này cần các Param như
      • IAMResourceId: Truyền từ AWS Config
      • MaxCredentialUsageAge: 90
      • AutomationAssumeRole: Chúng ta cần truyền Arn của Role có quyền cho Document này. Required IAM permissions

Clean up resources

  • Delete AWS config rule

    • iam-user-unused-credentials-check-1
    • iam-user-unused-credentials-check-2
  • Delete sns topic: d-sns-soa-config-topic

  • Delete EventBridge rule: d-event-rule-soa-unused-credentials-notification-before-disable

  • Delete state machine: d-tepfunc-soa-unused-credentials-notification

  • Delete IAM User: cloudmentorpro-test1

  • Stop recording config