Open3

監査要件の為のAWSアクセス制限方法

dehio3dehio3

複数のAWSアカウントを運用しており、ユーザー管理をAWS SSOを利用、許可セットによるアカウント毎の権限管理を実施している前提での実装方法を調べる

  • 基本的な考え方
    • まずはアクセスさせない
      • 監査ログとるにもコストが掛かるので、アクセスする要件がないものはアクセスさせない
  • S3へのアクセス制限できるものはS3バケットポリシーによる設定での設定が単純そう
  • 監査ログの取得手段はどうするか?
    • 監査観点だとCloudTrailが良さそう。
    • すでに S3アクセスログを取得している場合は、二重での実装にならないよう要件を整理する
dehio3dehio3

S3アクセス制御の各パターンまとめ

各方法のメリット・デメリット

方法 メリット デメリット 主な用途 運用負荷軽減の観点
S3バケットポリシー - バケット単位で細かい制御が可能
- 明示的なDenyが設定可能
- 他のアプリケーションやサービスへの影響を考慮が必要 バケット全体や特定リソースへのアクセス制御 バケットごとの設定が必要なため、管理の一元化が難しい。各チームでの対応が発生する可能性がある。
サービスコントロールポリシー(SCP) - アカウントやOU全体で制御可能
- IAMポリシーや許可セットに依存しない
- アカウント全体に影響を与える可能性がある
- AWS Organizationsが必要
組織全体での統制が必要な場合 監査チームが一元管理しやすい。各機能チームごとの設定不要で、全体の統制が取りやすい。
タグベースの制限 - リソース単位で柔軟な制御が可能
- SSO許可セットを変更せずに対応可能
- タグの管理が複雑になる
- 全リソースにタグ付けが必要
リソースのスコープを明確に制御したい場合 各チームでタグ管理が必要であるため、管理負荷が高くなる可能性がある。タグの整合性を保つ必要がある。
ロールベースの制限 - AWS SSO許可セットを変更せず、特定用途での制限が可能 - ロール管理が増える
- SSOの一元管理と分離される
特定の操作だけを許可するIAMロールを設ける場合 各チームで独自のロール管理が必要となり、ロールの管理が複雑化しやすい。
S3アクセス制御リスト(ACL) - オブジェクト単位で簡単な制御が可能
- バケットポリシーを変更しない
- 明示的なDenyが設定できない
- IAMポリシーやバケットポリシーに比べ柔軟性が低い
単純な所有者ベースの制御が必要な場合 ACL管理が分散するため、監査チームの負荷が増加する可能性がある。

各方法のTerraform設定例

1. S3バケットポリシー

特定のIAMユーザー(SSOロール)に対して、S3のアクセスを拒否する例。

resource "aws_s3_bucket_policy" "example" {
  bucket = "example-bucket"

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Sid       = "DenyReadAccessForSpecificUsers"
        Effect    = "Deny"
        Action    = ["s3:GetObject", "s3:ListBucket"]
        Resource  = [
          "arn:aws:s3:::example-bucket",
          "arn:aws:s3:::example-bucket/*"
        ]
        Condition = {
          StringLike = {
            "aws:PrincipalArn" : "arn:aws:iam::*:role/AWSReservedSSO_ReadOnlyAccess_*"
          }
        }
      }
    ]
  })
}

2. サービスコントロールポリシー(SCP)

特定アカウントやOU全体でアクセスを制限する例。

resource "aws_organizations_policy" "deny_s3_read" {
  name        = "DenyS3ReadAccess"
  description = "Deny S3 Read Access to specific bucket"
  content     = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Sid      = "DenyReadAccessToSpecificBucket"
        Effect   = "Deny"
        Action   = "s3:GetObject"
        Resource = "arn:aws:s3:::example-bucket/*"
      }
    ]
  })
}

resource "aws_organizations_policy_attachment" "attach_scp" {
  policy_id = aws_organizations_policy.deny_s3_read.id
  target_id = "ou-1234-example" # 対象のOUまたはアカウントIDを指定
}

3. タグベースの制限

S3バケットにタグを設定し、タグを条件にアクセスを制限する例。

resource "aws_s3_bucket" "example" {
  bucket = "example-bucket"

  tags = {
    Environment = "Production"
  }
}

resource "aws_iam_policy" "deny_s3_read_by_tag" {
  name        = "DenyS3ReadOnTaggedBucket"
  description = "Deny S3 read access for buckets tagged as Production"

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Sid       = "DenyReadOnTaggedBuckets"
        Effect    = "Deny"
        Action    = ["s3:GetObject", "s3:ListBucket"]
        Resource  = "*"
        Condition = {
          StringEquals = {
            "s3:ResourceTag/Environment": "Production"
          }
        }
      }
    ]
  })
}

4. ロールベースの制限

特定のロールにのみ制限を付ける例。

resource "aws_iam_role" "restricted_role" {
  name               = "RestrictedS3AccessRole"
  assume_role_policy = <<EOF
  {
    "Version": "2012-10-17",
    "Statement": [
      {
        "Effect": "Allow",
        "Principal": { "Service": "sso.amazonaws.com" },
        "Action": "sts:AssumeRole"
      }
    ]
  }
  EOF
}

resource "aws_iam_policy" "restricted_s3_policy" {
  name        = "RestrictedS3Policy"
  description = "Restrict access to specific S3 buckets"

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Sid      = "AllowAccessToAllBucketsExceptExample"
        Effect   = "Deny"
        Action   = "s3:GetObject"
        Resource = "arn:aws:s3:::example-bucket/*"
      }
    ]
  })
}

resource "aws_iam_role_policy_attachment" "attach_policy" {
  role       = aws_iam_role.restricted_role.name
  policy_arn = aws_iam_policy.restricted_s3_policy.arn
}

5. S3アクセス制御リスト(ACL)

バケットやオブジェクト単位で簡易なアクセス制御を行う例。

バケット全体にACLを適用

resource "aws_s3_bucket" "example" {
  bucket = "example-bucket"
  acl    = "private" # バケット所有者のみアクセス可能
}

オブジェクト単位でACLを適用

resource "aws_s3_object" "example_object" {
  bucket = aws_s3_bucket.example.bucket
  key    = "example-key"
  source = "example-file.txt"
  acl    = "private" # オブジェクト所有者のみアクセス可能
}

dehio3dehio3

S3アクセス履歴の取得方法

1. AWS CloudTrail

AWS CloudTrailは、S3バケットやオブジェクトに対する操作履歴を記録するサービスです。S3へのアクセスについても、CloudTrailを使うことで、オブジェクトの操作履歴(読み取り、書き込み、削除など)を取得できます。

取得できる情報

  • 誰が?(ユーザー情報): アクセスしたIAMユーザー、AWSアカウント、ロールの情報。
  • いつ?(タイムスタンプ): リクエストが行われた日時。
  • どのオブジェクトに?(リソース情報): アクセスしたS3バケット名、オブジェクトのキー名。
  • どのような操作?(イベント情報): GetObject(読み取り)、PutObject(書き込み)、DeleteObject(削除)などの操作内容。

設定方法

  1. CloudTrailのトレイルを作成・編集: マネジメントコンソールからCloudTrailを設定し、S3に対するすべてのAPI呼び出しを記録するようにトレイルを設定します。
  2. S3イベントの選択: CloudTrailの設定で、「管理イベント」や「データイベント」のオプションを選択し、S3のデータアクセス(オブジェクト操作)を監査します。

特定バケットの選択

CloudTrailのデータイベントは特定のS3バケットを対象にすることができます。これにより、必要なバケットだけを監査対象にすることでコストを最適化できます。


2. S3アクセスログ(Server Access Logging)

S3アクセスログを有効にすることで、S3バケットへのリクエストに関するログを取得することができます。このログには、リクエストがどのように行われたか、リクエスト元の情報などが含まれます。

取得できる情報

  • 誰が?(リクエスト元情報): リクエストの発信元IPアドレス、リクエストの発信者などの情報。
  • いつ?(タイムスタンプ): リクエストの日時。
  • どのオブジェクトに?: アクセスされたS3オブジェクト。
  • どのような操作?: GET(読み取り)、PUT(書き込み)、DELETE(削除)などの操作。

設定方法

  1. アクセスログの有効化: S3バケットのプロパティから「サーバーアクセスログ」を有効にします。
  2. ログの保存先バケットの指定: アクセスログを保存するための別のS3バケットを指定します。

3. AWS Config

AWS ConfigはAWSリソースの設定の変更を追跡し、リソースの構成や設定がどのように変更されたかを記録するサービスです。S3バケットの設定変更なども記録することが可能です。

取得できる情報

  • 設定の変更: S3バケットのポリシーやACL、バージョニング設定などが変更された場合、その履歴を取得可能。
  • 変更のトリガー: 誰がいつどのように設定を変更したかの履歴。

AWS ConfigはS3への個別オブジェクトの操作よりも、バケット全体の設定の変更を監査するために利用されます。


まとめ

  • CloudTrail: S3オブジェクトに対するすべての操作を詳細に記録でき、監査に最適です。特定バケットに限定することでコストを抑えることが可能です。
  • S3アクセスログ: バケットレベルでのリクエスト概要を記録するのに有効です。
  • AWS Config: バケット設定の変更を追跡し、構成の整合性を保つために利用します。

これらのサービスを組み合わせることで、S3アクセスに関する完全な監査を実現できます。