A collection of notes and resources
AWS リソースのセキュリティを確保する
{
"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"
}
}
}
]
}
{
"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"
]
}
}
}
]
}
{
"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"
}
}
}
]
}
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'
]
)
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', [])}")
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)
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'
}
}
)
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 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
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'}]
}
]
)
# 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
)
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]
}
)
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'
)