IAM: Quản lý Identity và Access Control

Users, Groups, Roles, Policies - Tất cả những gì bạn cần biết về IAM và bảo mật access.

AWS IAM là gì?

IAM (Identity and Access Management) kiểm soát ai có thể truy cập những gì trong AWS. Đây là nền tảng security quan trọng nhất.

Các thành phần chính

ComponentMô tả
UserIdentity cho người dùng
GroupTập hợp users với cùng permissions
RoleIdentity cho AWS services hoặc cross-account
PolicyJSON document định nghĩa permissions

IAM Policies

Policy Structure

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DescriptiveName",
      "Effect": "Allow",
      "Action": ["s3:GetObject", "s3:ListBucket"],
      "Resource": [
        "arn:aws:s3:::my-bucket",
        "arn:aws:s3:::my-bucket/*"
      ],
      "Condition": {
        "IpAddress": {
          "aws:SourceIp": "192.168.1.0/24"
        }
      }
    }
  ]
}

Các loại Policies

TypeMô tả
AWS ManagedDo AWS tạo và quản lý
Customer ManagedBạn tự tạo, reusable
InlineEmbed trực tiếp vào user/role

Triển khai IAM với Terraform

IAM User

# IAM User
resource "aws_iam_user" "developer" {
  name = "developer"
  path = "/developers/"

  tags = {
    Team = "Engineering"
  }
}

# Access Key (lưu ý: nên dùng IAM Identity Center thay vì access keys)
resource "aws_iam_access_key" "developer" {
  user = aws_iam_user.developer.name
}

# Attach existing policy
resource "aws_iam_user_policy_attachment" "developer_readonly" {
  user       = aws_iam_user.developer.name
  policy_arn = "arn:aws:iam::aws:policy/ReadOnlyAccess"
}

IAM Group

# IAM Group
resource "aws_iam_group" "developers" {
  name = "developers"
  path = "/teams/"
}

# Add user to group
resource "aws_iam_user_group_membership" "developer" {
  user = aws_iam_user.developer.name
  groups = [aws_iam_group.developers.name]
}

# Group policy
resource "aws_iam_group_policy" "developers" {
  name  = "developers-policy"
  group = aws_iam_group.developers.name

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect = "Allow"
        Action = [
          "ec2:Describe*",
          "s3:List*",
          "s3:Get*"
        ]
        Resource = "*"
      }
    ]
  })
}

IAM Role (quan trọng nhất!)

# IAM Role cho EC2 instance
resource "aws_iam_role" "ec2_app" {
  name = "${var.project_name}-ec2-role"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Action = "sts:AssumeRole"
        Effect = "Allow"
        Principal = {
          Service = "ec2.amazonaws.com"
        }
      }
    ]
  })
}

# Custom policy
resource "aws_iam_policy" "s3_access" {
  name        = "${var.project_name}-s3-access"
  description = "Allow access to specific S3 bucket"

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect = "Allow"
        Action = [
          "s3:GetObject",
          "s3:PutObject",
          "s3:DeleteObject"
        ]
        Resource = "${aws_s3_bucket.app.arn}/*"
      },
      {
        Effect = "Allow"
        Action = ["s3:ListBucket"]
        Resource = aws_s3_bucket.app.arn
      }
    ]
  })
}

# Attach policy to role
resource "aws_iam_role_policy_attachment" "ec2_s3" {
  role       = aws_iam_role.ec2_app.name
  policy_arn = aws_iam_policy.s3_access.arn
}

# Instance Profile (để gắn role vào EC2)
resource "aws_iam_instance_profile" "ec2_app" {
  name = "${var.project_name}-ec2-profile"
  role = aws_iam_role.ec2_app.name
}

Cross-Account Role

# Role cho phép account khác assume
resource "aws_iam_role" "cross_account" {
  name = "cross-account-readonly"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect = "Allow"
        Principal = {
          AWS = "arn:aws:iam::123456789012:root"  # Account ID khác
        }
        Action = "sts:AssumeRole"
        Condition = {
          StringEquals = {
            "sts:ExternalId" = var.external_id  # Extra security
          }
        }
      }
    ]
  })
}

AWS CLI Commands

# Liệt kê users
aws iam list-users

# Tạo user
aws iam create-user --user-name developer

# Tạo access key
aws iam create-access-key --user-name developer

# Attach policy
aws iam attach-user-policy \
  --user-name developer \
  --policy-arn arn:aws:iam::aws:policy/ReadOnlyAccess

# Tạo role
aws iam create-role \
  --role-name MyRole \
  --assume-role-policy-document file://trust-policy.json

# Assume role (lấy temporary credentials)
aws sts assume-role \
  --role-arn arn:aws:iam::123456789012:role/MyRole \
  --role-session-name MySession

Best Practices

1. Principle of Least Privilege

# ❌ Quá rộng
resource "aws_iam_policy" "bad" {
  policy = jsonencode({
    Statement = [{
      Effect   = "Allow"
      Action   = "*"
      Resource = "*"
    }]
  })
}

# ✅ Cụ thể resources và actions
resource "aws_iam_policy" "good" {
  policy = jsonencode({
    Statement = [{
      Effect   = "Allow"
      Action   = ["s3:GetObject"]
      Resource = "arn:aws:s3:::my-bucket/public/*"
    }]
  })
}

2. Sử dụng Roles thay vì Access Keys

# EC2 với IAM Role - không cần hardcode credentials
resource "aws_instance" "app" {
  ami                  = data.aws_ami.amazon_linux.id
  instance_type        = "t3.micro"
  iam_instance_profile = aws_iam_instance_profile.app.name
}

3. Enable MFA

# Policy yêu cầu MFA
resource "aws_iam_policy" "require_mfa" {
  policy = jsonencode({
    Statement = [{
      Effect = "Deny"
      Action = "*"
      Resource = "*"
      Condition = {
        BoolIfExists = {
          "aws:MultiFactorAuthPresent" = "false"
        }
      }
    }]
  })
}

4. Không dùng Root Account

# Tạo admin user thay vì dùng root
resource "aws_iam_user" "admin" {
  name = "admin"
}

resource "aws_iam_user_policy_attachment" "admin" {
  user       = aws_iam_user.admin.name
  policy_arn = "arn:aws:iam::aws:policy/AdministratorAccess"
}

IAM Security Tools

ToolMô tả
IAM Access AnalyzerPhát hiện public/shared resources
IAM Policy SimulatorTest policies trước khi apply
Credential ReportCSV report tất cả users và credentials

Bài tiếp theo: Security Services - Bảo vệ hạ tầng với GuardDuty, WAF, Shield.