亚麻云之身份安全卫士——IAM权限管理入门

本文作者: 封磊

Eclicktech SA | AWS Community Builder DevTool | AWS UGL | 亚马逊云科技云博主

阿里云&InfoQ&CSDN签约作者

在这里插入图片描述

前言

经过前五篇文章的学习,我们已经构建了一个功能完整的Web应用架构:EC2运行应用,RDS管理数据,S3存储资源,CloudFront提供全球加速。但是,随着架构的复杂化,一个关键问题浮现出来:如何安全地管理这些资源的访问权限?

想象一下:开发人员需要访问S3上传文件,运维人员需要管理EC2实例,财务人员需要查看账单,但每个人都不应该有超出职责范围的权限。今天,让我们请出"身份安全卫士"——AWS IAM(Identity and Access Management),为我们的云端架构构建一道坚固的安全防线。

权限管理的现实挑战

在没有合理权限管理的情况下,我们可能面临这些问题:

安全风险

# 危险的做法:使用root账户进行日常操作
aws s3 ls --profile root
# 风险:root账户拥有所有权限,一旦泄露后果严重

# 危险的做法:共享访问密钥
export AWS_ACCESS_KEY_ID="AKIA..."
export AWS_SECRET_ACCESS_KEY="..."
# 风险:密钥泄露、难以追踪操作来源

# 危险的做法:过度授权
aws iam attach-user-policy \
    --user-name developer \
    --policy-arn arn:aws:iam::aws:policy/AdministratorAccess
# 风险:开发人员获得管理员权限,可能误操作生产环境

管理复杂性

  • 权限混乱:不清楚谁有什么权限
  • 难以审计:无法追踪谁做了什么操作
  • 权限膨胀:用户权限只增不减,越来越大
  • 合规困难:无法满足安全合规要求

运维困扰

  • 密钥管理:大量密钥难以管理和轮换
  • 权限故障:权限不足导致应用无法正常工作
  • 临时访问:难以为临时需求提供合适的权限

什么是AWS IAM?

AWS IAM是AWS的身份和访问管理服务,就像企业的"门禁系统",控制谁可以访问什么资源,以及可以执行什么操作。

IAM核心概念

用户(Users)

  • 代表个人或应用程序
  • 拥有永久的访问凭证
  • 可以直接附加权限策略

组(Groups)

  • 用户的集合
  • 简化权限管理
  • 用户可以属于多个组

角色(Roles)

  • 临时身份
  • 可以被用户、服务或外部身份承担
  • 基于信任关系工作

策略(Policies)

  • 定义权限的JSON文档
  • 可以附加到用户、组或角色
  • 支持精细的权限控制

AWS安全模型

AWS共享责任模型:

AWS负责:
├── 物理安全(数据中心、硬件)
├── 网络基础设施安全
├── 虚拟化层安全
└── 服务本身的安全

客户负责:
├── 操作系统安全(EC2)
├── 应用程序安全
├── 数据加密
├── 网络配置(VPC、安全组)
└── 身份和访问管理(IAM)

IAM最佳实践原则

1. 最小权限原则

只授予完成任务所需的最小权限:

// 错误示例:过度授权
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "*",
            "Resource": "*"
        }
    ]
}

// 正确示例:精确权限
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:PutObject"
            ],
            "Resource": "arn:aws:s3:::my-wordpress-assets-20231201/wp-content/uploads/*"
        }
    ]
}

2. 使用组管理权限

通过组简化权限管理:

# 创建开发组
aws iam create-group --group-name Developers

# 创建运维组
aws iam create-group --group-name Operations

# 创建只读组
aws iam create-group --group-name ReadOnly

3. 启用MFA多因素认证

为敏感操作添加额外安全层:

# 为用户启用MFA
aws iam enable-mfa-device \
    --user-name john.doe \
    --serial-number arn:aws:iam::123456789012:mfa/john.doe \
    --authentication-code1 123456 \
    --authentication-code2 789012

4. 定期轮换访问密钥

# 创建新的访问密钥
aws iam create-access-key --user-name john.doe

# 停用旧的访问密钥
aws iam update-access-key \
    --user-name john.doe \
    --access-key-id AKIA... \
    --status Inactive

# 删除旧的访问密钥
aws iam delete-access-key \
    --user-name john.doe \
    --access-key-id AKIA...

实战案例:为WordPress架构配置IAM

让我们为之前搭建的WordPress架构配置合理的IAM权限体系。

步骤1:创建用户组

开发人员组
# 创建开发人员组
aws iam create-group --group-name WordPress-Developers

# 创建开发人员策略
cat > developer-policy.json << EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "EC2ReadAccess",
            "Effect": "Allow",
            "Action": [
                "ec2:DescribeInstances",
                "ec2:DescribeImages",
                "ec2:DescribeSnapshots",
                "ec2:DescribeVolumes"
            ],
            "Resource": "*"
        },
        {
            "Sid": "S3DevelopmentAccess",
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:PutObject",
                "s3:DeleteObject",
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::my-wordpress-assets-20231201/wp-content/uploads/dev/*",
                "arn:aws:s3:::my-wordpress-assets-20231201"
            ]
        },
        {
            "Sid": "RDSReadAccess",
            "Effect": "Allow",
            "Action": [
                "rds:DescribeDBInstances",
                "rds:DescribeDBSnapshots"
            ],
            "Resource": "*"
        },
        {
            "Sid": "CloudFrontReadAccess",
            "Effect": "Allow",
            "Action": [
                "cloudfront:GetDistribution",
                "cloudfront:ListDistributions"
            ],
            "Resource": "*"
        }
    ]
}
EOF

# 创建策略
aws iam create-policy \
    --policy-name WordPress-Developer-Policy \
    --policy-document file://developer-policy.json

# 附加策略到组
aws iam attach-group-policy \
    --group-name WordPress-Developers \
    --policy-arn arn:aws:iam::123456789012:policy/WordPress-Developer-Policy
运维人员组
# 创建运维人员组
aws iam create-group --group-name WordPress-Operations

# 创建运维人员策略
cat > operations-policy.json << EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "EC2FullAccess",
            "Effect": "Allow",
            "Action": [
                "ec2:*"
            ],
            "Resource": "*",
            "Condition": {
                "StringEquals": {
                    "ec2:ResourceTag/Project": "WordPress"
                }
            }
        },
        {
            "Sid": "RDSManagement",
            "Effect": "Allow",
            "Action": [
                "rds:*"
            ],
            "Resource": "*",
            "Condition": {
                "StringEquals": {
                    "rds:ResourceTag/Project": "WordPress"
                }
            }
        },
        {
            "Sid": "S3FullAccess",
            "Effect": "Allow",
            "Action": [
                "s3:*"
            ],
            "Resource": [
                "arn:aws:s3:::my-wordpress-assets-20231201",
                "arn:aws:s3:::my-wordpress-assets-20231201/*"
            ]
        },
        {
            "Sid": "CloudFrontManagement",
            "Effect": "Allow",
            "Action": [
                "cloudfront:*"
            ],
            "Resource": "*"
        },
        {
            "Sid": "IAMReadAccess",
            "Effect": "Allow",
            "Action": [
                "iam:GetRole",
                "iam:GetPolicy",
                "iam:ListRoles",
                "iam:ListPolicies"
            ],
            "Resource": "*"
        }
    ]
}
EOF

aws iam create-policy \
    --policy-name WordPress-Operations-Policy \
    --policy-document file://operations-policy.json

aws iam attach-group-policy \
    --group-name WordPress-Operations \
    --policy-arn arn:aws:iam::123456789012:policy/WordPress-Operations-Policy
只读用户组
# 创建只读用户组
aws iam create-group --group-name WordPress-ReadOnly

# 附加AWS托管的只读策略
aws iam attach-group-policy \
    --group-name WordPress-ReadOnly \
    --policy-arn arn:aws:iam::aws:policy/ReadOnlyAccess

步骤2:创建用户并分配到组

# 创建开发人员用户
aws iam create-user --user-name alice.developer
aws iam add-user-to-group \
    --user-name alice.developer \
    --group-name WordPress-Developers

# 创建运维人员用户
aws iam create-user --user-name bob.operations
aws iam add-user-to-group \
    --user-name bob.operations \
    --group-name WordPress-Operations

# 创建只读用户
aws iam create-user --user-name charlie.readonly
aws iam add-user-to-group \
    --user-name charlie.readonly \
    --group-name WordPress-ReadOnly

# 为用户创建访问密钥
aws iam create-access-key --user-name alice.developer
aws iam create-access-key --user-name bob.operations
aws iam create-access-key --user-name charlie.readonly

步骤3:配置MFA多因素认证

# 创建MFA设备
aws iam create-virtual-mfa-device \
    --virtual-mfa-device-name alice-mfa \
    --outfile alice-mfa-qr.png \
    --bootstrap-method QRCodePNG

# 启用MFA(需要用户扫描二维码后提供两个连续的验证码)
aws iam enable-mfa-device \
    --user-name alice.developer \
    --serial-number arn:aws:iam::123456789012:mfa/alice-mfa \
    --authentication-code1 123456 \
    --authentication-code2 789012

步骤4:创建服务角色

EC2实例角色
# 创建EC2信任策略
cat > ec2-trust-policy.json << EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "ec2.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}
EOF

# 创建EC2角色
aws iam create-role \
    --role-name WordPress-EC2-Role \
    --assume-role-policy-document file://ec2-trust-policy.json

# 创建EC2权限策略
cat > ec2-permissions-policy.json << EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "S3Access",
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:PutObject",
                "s3:DeleteObject"
            ],
            "Resource": "arn:aws:s3:::my-wordpress-assets-20231201/wp-content/uploads/*"
        },
        {
            "Sid": "CloudWatchLogs",
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents",
                "logs:DescribeLogStreams"
            ],
            "Resource": "arn:aws:logs:*:*:*"
        },
        {
            "Sid": "CloudWatchMetrics",
            "Effect": "Allow",
            "Action": [
                "cloudwatch:PutMetricData"
            ],
            "Resource": "*"
        }
    ]
}
EOF

aws iam create-policy \
    --policy-name WordPress-EC2-Policy \
    --policy-document file://ec2-permissions-policy.json

aws iam attach-role-policy \
    --role-name WordPress-EC2-Role \
    --policy-arn arn:aws:iam::123456789012:policy/WordPress-EC2-Policy

# 创建实例配置文件
aws iam create-instance-profile \
    --instance-profile-name WordPress-EC2-Profile

aws iam add-role-to-instance-profile \
    --instance-profile-name WordPress-EC2-Profile \
    --role-name WordPress-EC2-Role
Lambda执行角色
# 创建Lambda信任策略
cat > lambda-trust-policy.json << EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "lambda.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}
EOF

# 创建Lambda角色
aws iam create-role \
    --role-name WordPress-Lambda-Role \
    --assume-role-policy-document file://lambda-trust-policy.json

# 附加基本执行策略
aws iam attach-role-policy \
    --role-name WordPress-Lambda-Role \
    --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole

# 创建自定义Lambda权限策略
cat > lambda-permissions-policy.json << EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "S3Access",
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:PutObject"
            ],
            "Resource": "arn:aws:s3:::my-wordpress-assets-20231201/*"
        },
        {
            "Sid": "CloudFrontInvalidation",
            "Effect": "Allow",
            "Action": [
                "cloudfront:CreateInvalidation"
            ],
            "Resource": "*"
        }
    ]
}
EOF

aws iam create-policy \
    --policy-name WordPress-Lambda-Policy \
    --policy-document file://lambda-permissions-policy.json

aws iam attach-role-policy \
    --role-name WordPress-Lambda-Role \
    --policy-arn arn:aws:iam::123456789012:policy/WordPress-Lambda-Policy

步骤5:应用角色到资源

# 将角色附加到EC2实例
aws ec2 associate-iam-instance-profile \
    --instance-id i-1234567890abcdef0 \
    --iam-instance-profile Name=WordPress-EC2-Profile

# 验证角色附加
## 策略语法详解

### JSON策略结构

IAM策略使用JSON格式,包含以下关键元素:

```json
{
    "Version": "2012-10-17",           // 策略语言版本
    "Id": "PolicyId",                  // 策略ID(可选)
    "Statement": [                     // 权限声明数组
        {
            "Sid": "StatementId",      // 声明ID(可选)
            "Effect": "Allow|Deny",    // 允许或拒绝
            "Principal": {},           // 主体(谁)
            "Action": [],              // 操作(做什么)
            "Resource": [],            // 资源(对什么)
            "Condition": {}            // 条件(什么情况下)
        }
    ]
}

常用策略示例

S3访问策略
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowListBucket",
            "Effect": "Allow",
            "Action": "s3:ListBucket",
            "Resource": "arn:aws:s3:::my-wordpress-assets-20231201",
            "Condition": {
                "StringLike": {
                    "s3:prefix": [
                        "wp-content/uploads/${aws:username}/*"
                    ]
                }
            }
        },
        {
            "Sid": "AllowUserFolderAccess",
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:PutObject",
                "s3:DeleteObject"
            ],
            "Resource": "arn:aws:s3:::my-wordpress-assets-20231201/wp-content/uploads/${aws:username}/*"
        }
    ]
}
时间限制策略
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowWorkingHours",
            "Effect": "Allow",
            "Action": "ec2:*",
            "Resource": "*",
            "Condition": {
                "DateGreaterThan": {
                    "aws:CurrentTime": "08:00Z"
                },
                "DateLessThan": {
                    "aws:CurrentTime": "18:00Z"
                }
            }
        }
    ]
}
IP地址限制策略
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowFromOfficeIP",
            "Effect": "Allow",
            "Action": "*",
            "Resource": "*",
            "Condition": {
                "IpAddress": {
                    "aws:SourceIp": [
                        "203.0.113.0/24",
                        "198.51.100.0/24"
                    ]
                }
            }
        }
    ]
}

策略变量

使用策略变量实现动态权限控制:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowUserOwnFolder",
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:PutObject",
                "s3:DeleteObject"
            ],
            "Resource": "arn:aws:s3:::user-data/${aws:username}/*"
        },
        {
            "Sid": "AllowAssumeOwnRole",
            "Effect": "Allow",
            "Action": "sts:AssumeRole",
            "Resource": "arn:aws:iam::123456789012:role/${aws:username}-role"
        }
    ]
}

常用策略变量:

  • ${aws:username} - 用户名
  • ${aws:userid} - 用户ID
  • ${aws:CurrentTime} - 当前时间
  • ${aws:SourceIp} - 源IP地址
  • ${aws:RequestedRegion} - 请求的区域

权限边界(Permission Boundaries)

权限边界定义了用户或角色的最大权限范围:

# 创建权限边界策略
cat > permission-boundary.json << EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowedServices",
            "Effect": "Allow",
            "Action": [
                "s3:*",
                "ec2:Describe*",
                "rds:Describe*",
                "cloudfront:Get*",
                "cloudfront:List*"
            ],
            "Resource": "*"
        },
        {
            "Sid": "DenyDangerousActions",
            "Effect": "Deny",
            "Action": [
                "iam:*",
                "ec2:TerminateInstances",
                "rds:DeleteDBInstance",
                "s3:DeleteBucket"
            ],
            "Resource": "*"
        }
    ]
}
EOF

aws iam create-policy \
    --policy-name WordPress-Permission-Boundary \
    --policy-document file://permission-boundary.json

# 为用户设置权限边界
aws iam put-user-permissions-boundary \
    --user-name alice.developer \
    --permissions-boundary arn:aws:iam::123456789012:policy/WordPress-Permission-Boundary

跨账户访问

跨账户角色

# 在账户A中创建跨账户角色
cat > cross-account-trust-policy.json << EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::ACCOUNT-B-ID:root"
            },
            "Action": "sts:AssumeRole",
            "Condition": {
                "StringEquals": {
                    "sts:ExternalId": "unique-external-id"
                }
            }
        }
    ]
}
EOF

aws iam create-role \
    --role-name CrossAccount-WordPress-Access \
    --assume-role-policy-document file://cross-account-trust-policy.json

# 在账户B中承担角色
aws sts assume-role \
    --role-arn arn:aws:iam::ACCOUNT-A-ID:role/CrossAccount-WordPress-Access \
    --role-session-name CrossAccountSession \
    --external-id unique-external-id

资源共享策略

# S3桶跨账户访问策略
cat > cross-account-s3-policy.json << EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowCrossAccountAccess",
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "arn:aws:iam::ACCOUNT-B-ID:user/backup-user",
                    "arn:aws:iam::ACCOUNT-C-ID:role/backup-role"
                ]
            },
            "Action": [
                "s3:GetObject",
                "s3:PutObject"
            ],
            "Resource": "arn:aws:s3:::my-wordpress-assets-20231201/backups/*"
        }
    ]
}
EOF

aws s3api put-bucket-policy \
    --bucket my-wordpress-assets-20231201 \
    --policy file://cross-account-s3-policy.json

临时凭证和STS

临时访问密钥

# 获取临时凭证
aws sts get-session-token \
    --duration-seconds 3600 \
    --serial-number arn:aws:iam::123456789012:mfa/alice-mfa \
    --token-code 123456

# 使用临时凭证
export AWS_ACCESS_KEY_ID="ASIA..."
export AWS_SECRET_ACCESS_KEY="..."
export AWS_SESSION_TOKEN="..."

# 验证临时凭证
aws sts get-caller-identity

联合身份访问

# 配置SAML身份提供商
aws iam create-saml-provider \
    --saml-metadata-document file://saml-metadata.xml \
    --name CompanySAMLProvider

# 创建SAML角色
cat > saml-trust-policy.json << EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Federated": "arn:aws:iam::123456789012:saml-provider/CompanySAMLProvider"
            },
            "Action": "sts:AssumeRoleWithSAML",
            "Condition": {
                "StringEquals": {
                    "SAML:aud": "https://signin.aws.amazon.com/saml"
                }
            }
        }
    ]
}
EOF

aws iam create-role \
    --role-name SAML-WordPress-Developer \
    --assume-role-policy-document file://saml-trust-policy.json

安全监控和审计

CloudTrail日志分析

# 查看IAM相关操作
aws logs filter-log-events \
    --log-group-name CloudTrail/IAMEvents \
    --filter-pattern "{ $.eventSource = iam.amazonaws.com }" \
    --start-time 1701388800000 \
    --end-time 1701475200000

# 查看失败的登录尝试
aws logs filter-log-events \
    --log-group-name CloudTrail/IAMEvents \
    --filter-pattern "{ $.eventName = ConsoleLogin && $.errorCode EXISTS }"

# 查看权限变更
aws logs filter-log-events \
    --log-group-name CloudTrail/IAMEvents \
    --filter-pattern "{ $.eventName = AttachUserPolicy || $.eventName = DetachUserPolicy || $.eventName = PutUserPolicy }"

Access Analyzer

# 创建访问分析器
aws accessanalyzer create-analyzer \
    --analyzer-name WordPress-Access-Analyzer \
    --type ACCOUNT

# 查看发现的问题
aws accessanalyzer list-findings \
    --analyzer-arn arn:aws:access-analyzer:us-east-1:123456789012:analyzer/WordPress-Access-Analyzer

# 查看外部访问
aws accessanalyzer list-findings \
    --analyzer-arn arn:aws:access-analyzer:us-east-1:123456789012:analyzer/WordPress-Access-Analyzer \
    --filter criteria=resourceType,eq=AWS::S3::Bucket

权限使用分析

# 生成凭证报告
aws iam generate-credential-report

# 获取凭证报告
aws iam get-credential-report --output text --query Content | base64 -d > credential-report.csv

# 分析未使用的权限
aws iam generate-service-last-accessed-details \
    --arn arn:aws:iam::123456789012:user/alice.developer

# 获取服务访问详情
aws iam get-service-last-accessed-details \
    --job-id 12345678-1234-1234-1234-123456789012

自动化权限管理

使用AWS CLI脚本

#!/bin/bash
# user-lifecycle.sh - 用户生命周期管理脚本

create_user() {
    local username=$1
    local group=$2
    
    echo "Creating user: $username"
    aws iam create-user --user-name "$username"
    
    echo "Adding user to group: $group"
    aws iam add-user-to-group --user-name "$username" --group-name "$group"
    
    echo "Creating access key"
    aws iam create-access-key --user-name "$username"
    
    echo "Setting up MFA device"
    aws iam create-virtual-mfa-device \
        --virtual-mfa-device-name "${username}-mfa" \
        --outfile "${username}-mfa-qr.png" \
        --bootstrap-method QRCodePNG
}

rotate_keys() {
    local username=$1
    
    echo "Rotating access keys for: $username"
    
    # 创建新密钥
    new_key=$(aws iam create-access-key --user-name "$username" --query 'AccessKey.AccessKeyId' --output text)
    
    echo "New access key created: $new_key"
    echo "Please update applications and test before running cleanup"
    
    # 列出旧密钥(需要手动清理)
    aws iam list-access-keys --user-name "$username"
}

cleanup_user() {
    local username=$1
    
    echo "Cleaning up user: $username"
    
    # 删除访问密钥
    aws iam list-access-keys --user-name "$username" --query 'AccessKeyMetadata[].AccessKeyId' --output text | \
    while read key; do
        aws iam delete-access-key --user-name "$username" --access-key-id "$key"
    done
    
    # 分离策略
    aws iam list-attached-user-policies --user-name "$username" --query 'AttachedPolicies[].PolicyArn' --output text | \
    while read policy; do
        aws iam detach-user-policy --user-name "$username" --policy-arn "$policy"
    done
    
    # 从组中移除
    aws iam get-groups-for-user --user-name "$username" --query 'Groups[].GroupName' --output text | \
    while read group; do
        aws iam remove-user-from-group --user-name "$username" --group-name "$group"
    done
    
    # 删除用户
    aws iam delete-user --user-name "$username"
}

# 使用示例
case "$1" in
    create)
        create_user "$2" "$3"
        ;;
    rotate)
        rotate_keys "$2"
        ;;
    cleanup)
        cleanup_user "$2"
        ;;
    *)
        echo "Usage: $0 {create|rotate|cleanup} username [group]"
        exit 1
        ;;
esac

权限审计脚本

#!/bin/bash
# permission-audit.sh - 权限审计脚本

audit_unused_permissions() {
    echo "=== Unused Permissions Audit ==="
    
    # 获取所有用户
    aws iam list-users --query 'Users[].UserName' --output text | while read user; do
        echo "Auditing user: $user"
        
        # 生成服务访问详情
        job_id=$(aws iam generate-service-last-accessed-details \
            --arn "arn:aws:iam::$(aws sts get-caller-identity --query Account --output text):user/$user" \
            --query JobId --output text)
        
        # 等待作业完成
        while true; do
            status=$(aws iam get-service-last-accessed-details --job-id "$job_id" --query JobStatus --output text)
            if [ "$status" = "COMPLETED" ]; then
                break
            fi
            sleep 5
        done
        
        # 获取未使用的服务
        aws iam get-service-last-accessed-details --job-id "$job_id" \
            --query 'ServicesLastAccessed[?LastAuthenticated==null].ServiceName' --output text
    done
}

audit_overprivileged_users() {
    echo "=== Overprivileged Users Audit ==="
    
    # 查找有管理员权限的用户
    aws iam list-entities-for-policy \
        --policy-arn arn:aws:iam::aws:policy/AdministratorAccess \
        --query 'PolicyUsers[].UserName' --output text | while read user; do
        echo "WARNING: User $user has AdministratorAccess"
    done
    
    # 查找有PowerUser权限的用户
    aws iam list-entities-for-policy \
        --policy-arn arn:aws:iam::aws:policy/PowerUserAccess \
        --query 'PolicyUsers[].UserName' --output text | while read user; do
        echo "CAUTION: User $user has PowerUserAccess"
    done
}

audit_mfa_compliance() {
    echo "=== MFA Compliance Audit ==="
    
    aws iam list-users --query 'Users[].UserName' --output text | while read user; do
        mfa_devices=$(aws iam list-mfa-devices --user-name "$user" --query 'MFADevices' --output text)
        if [ -z "$mfa_devices" ]; then
            echo "WARNING: User $user does not have MFA enabled"
        fi
    done
}

audit_old_access_keys() {
    echo "=== Old Access Keys Audit ==="
    
    cutoff_date=$(date -d '90 days ago' +%Y-%m-%d)
    
    aws iam list-users --query 'Users[].UserName' --output text | while read user; do
        aws iam list-access-keys --user-name "$user" --query 'AccessKeyMetadata[]' --output json | \
        jq -r --arg cutoff "$cutoff_date" '.[] | select(.CreateDate < $cutoff) | "\(.UserName): \(.AccessKeyId) created on \(.CreateDate)"'
    done
}

# 运行所有审计
audit_unused_permissions
audit_overprivileged_users
audit_mfa_compliance
audit_old_access_keys

成本优化

权限相关成本

IAM本身是免费服务,但权限配置会影响其他服务的成本:

# 监控IAM相关的成本
aws ce get-cost-and-usage \
    --time-period Start=2023-12-01,End=2023-12-31 \
    --granularity MONTHLY \
    --metrics BlendedCost \
    --group-by Type=DIMENSION,Key=SERVICE \
    --filter file://iam-cost-filter.json

# iam-cost-filter.json
{
    "Dimensions": {
        "Key": "SERVICE",
        "Values": [
            "AWS Identity and Access Management",
            "AWS Security Token Service"
        ]
    }
}

优化建议

  1. 减少不必要的STS调用
  2. 优化临时凭证的生命周期
  3. 合理使用跨区域复制权限
  4. 定期清理未使用的角色和策略
## 故障排除

### 常见权限问题

**问题1:Access Denied错误**
```bash
# 诊断步骤
# 1. 检查用户权限
aws iam list-attached-user-policies --user-name alice.developer
aws iam list-user-policies --user-name alice.developer

# 2. 检查组权限
aws iam get-groups-for-user --user-name alice.developer
aws iam list-attached-group-policies --group-name WordPress-Developers

# 3. 检查权限边界
aws iam get-user --user-name alice.developer --query 'User.PermissionsBoundary'

# 4. 模拟策略
aws iam simulate-principal-policy \
    --policy-source-arn arn:aws:iam::123456789012:user/alice.developer \
    --action-names s3:GetObject \
    --resource-arns arn:aws:s3:::my-wordpress-assets-20231201/wp-content/uploads/test.jpg

问题2:角色承担失败

# 检查信任关系
aws iam get-role --role-name WordPress-EC2-Role --query 'Role.AssumeRolePolicyDocument'

# 检查实例配置文件
aws ec2 describe-instances --instance-ids i-1234567890abcdef0 \
    --query 'Reservations[0].Instances[0].IamInstanceProfile'

# 测试角色承担
aws sts assume-role \
    --role-arn arn:aws:iam::123456789012:role/WordPress-EC2-Role \
    --role-session-name test-session

问题3:MFA验证失败

# 检查MFA设备状态
aws iam list-mfa-devices --user-name alice.developer

# 重新同步MFA设备
aws iam resync-mfa-device \
    --user-name alice.developer \
    --serial-number arn:aws:iam::123456789012:mfa/alice-mfa \
    --authentication-code1 123456 \
    --authentication-code2 789012

调试工具

# 策略模拟器
aws iam simulate-principal-policy \
    --policy-source-arn arn:aws:iam::123456789012:user/alice.developer \
    --action-names ec2:DescribeInstances,s3:ListBucket \
    --resource-arns "*" \
    --context-entries ContextKeyName=aws:RequestedRegion,ContextKeyValues=us-east-1,ContextKeyType=string

# 解码授权消息
aws sts decode-authorization-message \
    --encoded-message "encoded-error-message-here"

# 检查当前身份
aws sts get-caller-identity

合规性和最佳实践

合规框架对照

SOC 2合规

  • 启用CloudTrail记录所有IAM操作
  • 实施最小权限原则
  • 定期权限审查
  • MFA强制执行

PCI DSS合规

  • 限制对敏感数据的访问
  • 实施强密码策略
  • 定期访问权限审查
  • 监控和日志记录

GDPR合规

  • 数据访问控制
  • 数据处理权限管理
  • 审计日志保留
  • 数据删除权限控制

企业级IAM架构

# 多账户架构示例
# 主账户:IAM用户和组管理
# 开发账户:开发环境资源
# 测试账户:测试环境资源
# 生产账户:生产环境资源

# 在主账户创建跨账户角色
cat > multi-account-trust-policy.json << EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "arn:aws:iam::MAIN-ACCOUNT:user/alice.developer",
                    "arn:aws:iam::MAIN-ACCOUNT:user/bob.operations"
                ]
            },
            "Action": "sts:AssumeRole",
            "Condition": {
                "Bool": {
                    "aws:MultiFactorAuthPresent": "true"
                },
                "NumericLessThan": {
                    "aws:MultiFactorAuthAge": "3600"
                }
            }
        }
    ]
}
EOF

# 在各环境账户创建角色
aws iam create-role \
    --role-name CrossAccount-Developer-Role \
    --assume-role-policy-document file://multi-account-trust-policy.json

自动化合规检查

#!/usr/bin/env python3
# compliance-checker.py

import boto3
import json
from datetime import datetime, timedelta

class IAMComplianceChecker:
    def __init__(self):
        self.iam = boto3.client('iam')
        self.sts = boto3.client('sts')
        
    def check_mfa_compliance(self):
        """检查MFA合规性"""
        print("=== MFA Compliance Check ===")
        
        users = self.iam.list_users()['Users']
        non_compliant_users = []
        
        for user in users:
            username = user['UserName']
            mfa_devices = self.iam.list_mfa_devices(UserName=username)['MFADevices']
            
            if not mfa_devices:
                non_compliant_users.append(username)
        
        if non_compliant_users:
            print(f"Users without MFA: {', '.join(non_compliant_users)}")
        else:
            print("All users have MFA enabled")
    
    def check_old_access_keys(self, days=90):
        """检查过期访问密钥"""
        print(f"=== Access Keys Older Than {days} Days ===")
        
        cutoff_date = datetime.now() - timedelta(days=days)
        old_keys = []
        
        users = self.iam.list_users()['Users']
        for user in users:
            username = user['UserName']
            keys = self.iam.list_access_keys(UserName=username)['AccessKeyMetadata']
            
            for key in keys:
                if key['CreateDate'].replace(tzinfo=None) < cutoff_date:
                    old_keys.append({
                        'User': username,
                        'KeyId': key['AccessKeyId'],
                        'Age': (datetime.now() - key['CreateDate'].replace(tzinfo=None)).days
                    })
        
        if old_keys:
            for key in old_keys:
                print(f"User: {key['User']}, Key: {key['KeyId']}, Age: {key['Age']} days")
        else:
            print("No old access keys found")
    
    def check_unused_roles(self, days=90):
        """检查未使用的角色"""
        print(f"=== Roles Unused for {days} Days ===")
        
        cutoff_date = datetime.now() - timedelta(days=days)
        unused_roles = []
        
        roles = self.iam.list_roles()['Roles']
        for role in roles:
            role_name = role['RoleName']
            
            try:
                # 生成服务访问详情
                response = self.iam.generate_service_last_accessed_details(
                    Arn=role['Arn']
                )
                job_id = response['JobId']
                
                # 等待作业完成
                import time
                while True:
                    details = self.iam.get_service_last_accessed_details(JobId=job_id)
                    if details['JobStatus'] == 'COMPLETED':
                        break
                    time.sleep(2)
                
                # 检查最后访问时间
                services = details['ServicesLastAccessed']
                last_used = None
                
                for service in services:
                    if 'LastAuthenticated' in service:
                        if not last_used or service['LastAuthenticated'] > last_used:
                            last_used = service['LastAuthenticated']
                
                if not last_used or last_used.replace(tzinfo=None) < cutoff_date:
                    unused_roles.append(role_name)
                    
            except Exception as e:
                print(f"Error checking role {role_name}: {e}")
        
        if unused_roles:
            print(f"Unused roles: {', '.join(unused_roles)}")
        else:
            print("No unused roles found")
    
    def check_overprivileged_policies(self):
        """检查过度授权的策略"""
        print("=== Overprivileged Policies Check ===")
        
        dangerous_actions = ['*', 'iam:*', 'sts:AssumeRole']
        overprivileged_policies = []
        
        policies = self.iam.list_policies(Scope='Local')['Policies']
        for policy in policies:
            policy_arn = policy['Arn']
            
            try:
                policy_version = self.iam.get_policy_version(
                    PolicyArn=policy_arn,
                    VersionId=policy['DefaultVersionId']
                )
                
                policy_doc = policy_version['PolicyVersion']['Document']
                statements = policy_doc.get('Statement', [])
                
                for statement in statements:
                    if statement.get('Effect') == 'Allow':
                        actions = statement.get('Action', [])
                        if isinstance(actions, str):
                            actions = [actions]
                        
                        for action in actions:
                            if action in dangerous_actions:
                                overprivileged_policies.append(policy['PolicyName'])
                                break
                                
            except Exception as e:
                print(f"Error checking policy {policy['PolicyName']}: {e}")
        
        if overprivileged_policies:
            print(f"Overprivileged policies: {', '.join(set(overprivileged_policies))}")
        else:
            print("No overprivileged policies found")

if __name__ == "__main__":
    checker = IAMComplianceChecker()
    checker.check_mfa_compliance()
    checker.check_old_access_keys()
    checker.check_unused_roles()
    checker.check_overprivileged_policies()

迁移验证清单

权限验证

  • 所有用户都能正常访问所需资源
  • 应用程序使用IAM角色正常工作
  • 跨服务访问权限配置正确
  • MFA设备正常工作
  • 临时凭证可以正常获取

安全验证

# 1. 验证最小权限原则
aws iam simulate-principal-policy \
    --policy-source-arn arn:aws:iam::123456789012:user/alice.developer \
    --action-names iam:CreateUser \
    --resource-arns "*"
# 应该返回 "denied"

# 2. 验证MFA要求
aws iam get-account-summary | grep -i mfa

# 3. 验证密码策略
aws iam get-account-password-policy

审计验证

  • CloudTrail记录IAM操作
  • Access Analyzer正常工作
  • 权限边界生效
  • 合规检查脚本运行正常

最佳实践总结

用户管理

  1. 使用组管理权限:避免直接给用户附加策略
  2. 启用MFA:为所有用户启用多因素认证
  3. 定期轮换密钥:建立访问密钥轮换机制
  4. 最小权限原则:只授予必要的最小权限

角色设计

  1. 服务角色优先:应用程序使用IAM角色而非用户密钥
  2. 跨账户访问:使用角色实现安全的跨账户访问
  3. 临时凭证:优先使用临时凭证
  4. 信任关系限制:严格控制角色的信任关系

策略管理

  1. 使用托管策略:优先使用AWS托管策略
  2. 版本控制:为自定义策略启用版本控制
  3. 条件限制:使用条件限制策略的适用范围
  4. 定期审查:定期审查和清理不需要的策略

监控审计

  1. 启用CloudTrail:记录所有IAM操作
  2. 使用Access Analyzer:发现意外的外部访问
  3. 定期审计:建立定期权限审计机制
  4. 合规检查:自动化合规性检查

下一步学习方向

掌握了IAM基础后,你可以继续探索:

  1. CloudWatch监控:监控IAM相关的安全事件(下一篇文章重点)
  2. AWS Organizations:多账户权限管理
  3. AWS SSO:单点登录解决方案
  4. AWS Secrets Manager:密钥和凭证管理
  5. AWS Config:配置合规性监控

结语

通过配置IAM权限管理,我们为整个AWS架构构建了一道坚固的安全防线。IAM不仅保护了我们的资源安全,还提供了精细的访问控制和完整的审计追踪。

从无序的权限管理到结构化的身份安全体系,这是现代云架构的必备能力。我们学会了:

  • 理解IAM的核心概念和工作原理
  • 设计合理的用户、组、角色权限体系
  • 编写精确的IAM策略
  • 实施多因素认证和权限边界
  • 建立权限审计和合规检查机制

现在我们的架构已经非常完整和安全:

  • 计算层:EC2(动态内容)
  • 数据层:RDS(数据库)
  • 存储层:S3(静态资源)
  • 加速层:CloudFront(全球CDN)
  • 安全层:IAM(身份权限管理)

在最后一篇文章中,我们将学习CloudWatch监控服务,为整个架构建立全面的监控和告警体系,确保系统的稳定运行和及时的问题发现。


安全无小事,权限需精细!IAM让你的AWS资源拥有最专业的"身份安全卫士"!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

指剑

捐点钱吧,小笼包8元一笼,谢谢

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值