Hikaru's notes

A collection of notes and resources

View the Project on GitHub HikaruMizoe/notes

4.3 AWS リソースのセキュリティを確保する

タスクステートメント

AWS リソースのセキュリティを確保する

対象知識

AWS のサービスへのアクセスを制御する IAM ロール、ポリシー、グループ

IAM ロール

IAM ポリシー

IAM グループ

バケットポリシー

SageMaker Role Manager

SageMaker のセキュリティ機能とコンプライアンス機能

ネットワークセキュリティ

データセキュリティ

コンプライアンス

ML リソースへのネットワークアクセスの制御

VPC (Virtual Private Cloud)

セキュリティグループ

ネットワーク ACL

VPC エンドポイント

CI/CD パイプラインのセキュリティのベストプラクティス

シークレット管理

コードセキュリティ

アクセス制御

対象スキル

1. ML アーティファクトへの最小権限アクセスを設定する

S3 バケットポリシー

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowSageMakerReadWrite",
      "Effect": "Allow",
      "Principal": {
        "Service": "sagemaker.amazonaws.com"
      },
      "Action": [
        "s3:GetObject",
        "s3:PutObject"
      ],
      "Resource": "arn:aws:s3:::my-ml-bucket/models/*",
      "Condition": {
        "StringEquals": {
          "aws:SourceAccount": "123456789012"
        }
      }
    }
  ]
}

KMS キーポリシー

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "Allow SageMaker to use the key",
      "Effect": "Allow",
      "Principal": {
        "Service": "sagemaker.amazonaws.com"
      },
      "Action": [
        "kms:Decrypt",
        "kms:GenerateDataKey"
      ],
      "Resource": "*",
      "Condition": {
        "StringEquals": {
          "kms:ViaService": [
            "s3.us-east-1.amazonaws.com",
            "sagemaker.us-east-1.amazonaws.com"
          ]
        }
      }
    }
  ]
}

2. ML システムとやり取りするユーザーとアプリケーションの IAM ポリシーとロールを設定する

SageMaker 実行ロール

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:PutObject",
        "s3:DeleteObject"
      ],
      "Resource": [
        "arn:aws:s3:::my-ml-bucket/*"
      ]
    },
    {
      "Effect": "Allow",
      "Action": [
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::my-ml-bucket"
      ]
    },
    {
      "Effect": "Allow",
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents"
      ],
      "Resource": "arn:aws:logs:*:*:log-group:/aws/sagemaker/*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "ecr:GetDownloadUrlForLayer",
        "ecr:BatchGetImage",
        "ecr:BatchCheckLayerAvailability"
      ],
      "Resource": "*"
    }
  ]
}

データサイエンティスト用ポリシー

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "sagemaker:CreateTrainingJob",
        "sagemaker:DescribeTrainingJob",
        "sagemaker:StopTrainingJob",
        "sagemaker:CreateModel",
        "sagemaker:DescribeModel"
      ],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "sagemaker:CreateEndpoint",
        "sagemaker:UpdateEndpoint",
        "sagemaker:DeleteEndpoint"
      ],
      "Resource": "*",
      "Condition": {
        "StringEquals": {
          "aws:RequestedRegion": "us-east-1"
        }
      }
    },
    {
      "Effect": "Allow",
      "Action": "iam:PassRole",
      "Resource": "arn:aws:iam::123456789012:role/SageMakerExecutionRole",
      "Condition": {
        "StringEquals": {
          "iam:PassedToService": "sagemaker.amazonaws.com"
        }
      }
    }
  ]
}

SageMaker Role Manager の使用

import boto3

sagemaker = boto3.client('sagemaker')

# 事前設定されたロールの作成
response = sagemaker.create_role(
    RoleName='DataScientistRole',
    PersonaArn='arn:aws:sagemaker:us-east-1::persona/data-scientist',
    Activities=[
        'ml.sagemaker.training-job.create',
        'ml.sagemaker.model.create',
        'ml.sagemaker.endpoint.create'
    ]
)

3. ML システムのモニタリング、監査、ログ記録により、継続的なセキュリティとコンプライアンスを確保する

CloudTrail によるAPI監査

import boto3

cloudtrail = boto3.client('cloudtrail')

# SageMaker API 呼び出しのログ取得
response = cloudtrail.lookup_events(
    LookupAttributes=[
        {
            'AttributeKey': 'EventSource',
            'AttributeValue': 'sagemaker.amazonaws.com'
        }
    ],
    MaxResults=50
)

for event in response['Events']:
    print(f"Event: {event['EventName']}")
    print(f"User: {event['Username']}")
    print(f"Time: {event['EventTime']}")
    print(f"Resources: {event.get('Resources', [])}")

CloudWatch Logs によるログ記録

import boto3

logs = boto3.client('logs')

# ログクエリの実行
query_id = logs.start_query(
    logGroupName='/aws/sagemaker/Endpoints/production',
    startTime=int((datetime.now() - timedelta(hours=1)).timestamp()),
    endTime=int(datetime.now().timestamp()),
    queryString='''
        fields @timestamp, @message
        | filter @message like /ERROR/
        | sort @timestamp desc
        | limit 20
    '''
)

# 結果の取得
import time
while True:
    result = logs.get_query_results(queryId=query_id)
    if result['status'] == 'Complete':
        break
    time.sleep(1)

for record in result['results']:
    print(record)

AWS Config によるコンプライアンス監視

import boto3

config = boto3.client('config')

# Config ルールの作成
response = config.put_config_rule(
    ConfigRule={
        'ConfigRuleName': 'sagemaker-endpoint-encryption',
        'Description': 'Checks that SageMaker endpoints have encryption enabled',
        'Source': {
            'Owner': 'AWS',
            'SourceIdentifier': 'SAGEMAKER_ENDPOINT_CONFIGURATION_KMS_KEY_CONFIGURED'
        }
    }
)

4. セキュリティの問題をトラブルシューティングおよびデバッグする

アクセス拒否のトラブルシューティング

import boto3

# IAM Policy Simulator を使用
iam = boto3.client('iam')

response = iam.simulate_principal_policy(
    PolicySourceArn='arn:aws:iam::123456789012:role/SageMakerRole',
    ActionNames=[
        's3:GetObject',
        's3:PutObject'
    ],
    ResourceArns=[
        'arn:aws:s3:::my-ml-bucket/models/*'
    ]
)

for result in response['EvaluationResults']:
    print(f"Action: {result['EvalActionName']}")
    print(f"Decision: {result['EvalDecision']}")
    if result['EvalDecision'] == 'denied':
        print(f"Reason: {result.get('MissingContextValues', 'No specific reason')}")

VPC 接続のトラブルシューティング

# VPC Reachability Analyzer
aws ec2 create-network-insights-path \
    --source eni-xxxxx \
    --destination eni-yyyyy \
    --protocol tcp \
    --destination-port 443

aws ec2 start-network-insights-analysis \
    --network-insights-path-id nip-xxxxx

aws ec2 describe-network-insights-analyses \
    --network-insights-analysis-ids nia-xxxxx

5. ML システムをセキュアに分離するために VPC、サブネット、セキュリティグループを構築する

VPC とサブネットの作成

import boto3

ec2 = boto3.client('ec2')

# VPC の作成
vpc_response = ec2.create_vpc(
    CidrBlock='10.0.0.0/16',
    TagSpecifications=[
        {
            'ResourceType': 'vpc',
            'Tags': [
                {'Key': 'Name', 'Value': 'ML-VPC'}
            ]
        }
    ]
)
vpc_id = vpc_response['Vpc']['VpcId']

# プライベートサブネットの作成
subnet_response = ec2.create_subnet(
    VpcId=vpc_id,
    CidrBlock='10.0.1.0/24',
    AvailabilityZone='us-east-1a',
    TagSpecifications=[
        {
            'ResourceType': 'subnet',
            'Tags': [
                {'Key': 'Name', 'Value': 'ML-Private-Subnet'}
            ]
        }
    ]
)
subnet_id = subnet_response['Subnet']['SubnetId']

セキュリティグループの作成

# セキュリティグループの作成
sg_response = ec2.create_security_group(
    GroupName='ML-SecurityGroup',
    Description='Security group for ML workloads',
    VpcId=vpc_id
)
sg_id = sg_response['GroupId']

# インバウンドルールの追加(HTTPS のみ)
ec2.authorize_security_group_ingress(
    GroupId=sg_id,
    IpPermissions=[
        {
            'IpProtocol': 'tcp',
            'FromPort': 443,
            'ToPort': 443,
            'IpRanges': [
                {
                    'CidrIp': '10.0.0.0/16',
                    'Description': 'HTTPS from VPC'
                }
            ]
        }
    ]
)

# アウトバウンドルールの設定(デフォルトですべて許可されているため、制限する場合)
ec2.revoke_security_group_egress(
    GroupId=sg_id,
    IpPermissions=[
        {
            'IpProtocol': '-1',
            'IpRanges': [{'CidrIp': '0.0.0.0/0'}]
        }
    ]
)

# 必要なアウトバウンドのみ許可
ec2.authorize_security_group_egress(
    GroupId=sg_id,
    IpPermissions=[
        {
            'IpProtocol': 'tcp',
            'FromPort': 443,
            'ToPort': 443,
            'IpRanges': [{'CidrIp': '0.0.0.0/0', 'Description': 'HTTPS to internet'}]
        }
    ]
)

VPC エンドポイントの作成

# S3 用ゲートウェイエンドポイント
s3_endpoint = ec2.create_vpc_endpoint(
    VpcId=vpc_id,
    ServiceName='com.amazonaws.us-east-1.s3',
    RouteTableIds=['rtb-xxxxx'],
    VpcEndpointType='Gateway'
)

# SageMaker Runtime 用インターフェースエンドポイント
sagemaker_endpoint = ec2.create_vpc_endpoint(
    VpcId=vpc_id,
    ServiceName='com.amazonaws.us-east-1.sagemaker.runtime',
    VpcEndpointType='Interface',
    SubnetIds=[subnet_id],
    SecurityGroupIds=[sg_id],
    PrivateDnsEnabled=True
)

SageMaker での VPC 設定

from sagemaker.tensorflow import TensorFlow

# VPC 設定でトレーニング
estimator = TensorFlow(
    entry_point='train.py',
    role=role,
    instance_count=1,
    instance_type='ml.p3.2xlarge',
    framework_version='2.12',
    subnets=[subnet_id],
    security_group_ids=[sg_id]
)

# VPC 設定でエンドポイントデプロイ
predictor = model.deploy(
    initial_instance_count=1,
    instance_type='ml.m5.xlarge',
    vpc_config={
        'SecurityGroupIds': [sg_id],
        'Subnets': [subnet_id]
    }
)

セキュリティのベストプラクティス

データ保護

  1. 保存時の暗号化
    • S3: SSE-S3, SSE-KMS
    • EBS: KMS 暗号化
    • SageMaker: KMS キーの指定
  2. 転送中の暗号化
    • TLS 1.2 以上
    • VPC エンドポイント経由の通信
  3. データアクセス制御
    • 最小権限の原則
    • バケットポリシーと IAM ポリシーの組み合わせ

アクセス管理

  1. IAM ベストプラクティス
    • ルートユーザーの使用を避ける
    • MFA を有効化
    • 定期的なキーローテーション
  2. ロールベースアクセス
    • ユーザーグループの活用
    • サービスロールの使用
    • クロスアカウントアクセスの制限

ネットワークセキュリティ

  1. VPC 分離
    • プライベートサブネット使用
    • NAT ゲートウェイ経由でのインターネットアクセス
    • VPC エンドポイントの活用
  2. セキュリティグループ
    • 最小限のポート開放
    • 送信元の明示的な指定
    • 定期的なレビュー

モニタリングと監査

  1. ログ記録
    • CloudTrail: API 監査
    • CloudWatch Logs: アプリケーションログ
    • VPC Flow Logs: ネットワークトラフィック
  2. 継続的監視
    • AWS Config: コンプライアンス
    • GuardDuty: 脅威検出
    • Security Hub: セキュリティ状態の集約

コンプライアンスチェックリスト

セキュリティ違反時の対応

インシデント対応プロセス

  1. 検出: CloudWatch Alarms, GuardDuty
  2. 封じ込め: セキュリティグループ変更、IAM 無効化
  3. 調査: CloudTrail ログ分析
  4. 復旧: バックアップからの復元
  5. 事後分析: 原因究明と再発防止

自動化された対応

import boto3

def lambda_handler(event, context):
    # GuardDuty の検出に対する自動対応
    finding = event['detail']
    
    if finding['severity'] >= 7:  # 高リスク
        ec2 = boto3.client('ec2')
        iam = boto3.client('iam')
        
        # 侵害されたインスタンスを隔離
        instance_id = finding['resource']['instanceDetails']['instanceId']
        ec2.modify_instance_attribute(
            InstanceId=instance_id,
            Groups=['sg-quarantine']  # 隔離用セキュリティグループ
        )
        
        # 侵害された IAM ユーザーを無効化
        if 'userName' in finding['resource']:
            user_name = finding['resource']['userName']
            iam.attach_user_policy(
                UserName=user_name,
                PolicyArn='arn:aws:iam::aws:policy/DenyAll'
            )
        
        # SNS 通知
        sns = boto3.client('sns')
        sns.publish(
            TopicArn='arn:aws:sns:us-east-1:123456789012:security-alerts',
            Message=f'Security incident detected: {finding}',
            Subject='URGENT: Security Alert'
        )

関連リンク