IAM ユーザーのアクセスキーを使って S3 バケットへのアクセスに必要な IAM ポリシーを IAM ユーザー付与すれば、アプリケーションとしては動作します。ローカル PC 上での開発時などは、自分の IAM ユーザーの権限を利用して開発すると思います。作成したアプリケーションを EC2 インスタンスや Lambda 上で動かす時は、自分の IAM ユーザーのアクセスキーは使用せず、EC2 インスタンスロールなど AWS サービスが使用する IAM ロールで実行することになるため、実際に試してみました。
検証用の S3 バケットとオブジェクトを作成
$ export AWS_ACCESS_KEY_ID="your-access-key"
$ export AWS_SECRET_ACCESS_KEY="your-secret-key"
$ aws s3api create-bucket \
--bucket mnrst-test-bucket \
--region us-east-1
$ echo test > test.txt
$ aws s3api put-object \
--bucket mnrst-test-bucket \
--key test.txt \
--body test.txt
$ aws s3api list-objects \
--bucket mnrst-test-bucket \
--query "Contents[].Key"
[
"test.txt"
]
.NET 8 で検証用アプリケーションを作成
$ dotnet new console -o awss3test --use-program-main
$ cd awss3test
$ dotnet add package AWSSDK.S3
$ code Program.cs
using System;
using System.Threading.Tasks;
using Amazon;
using Amazon.Runtime;
using Amazon.S3;
using Amazon.S3.Model;
class Program
{
static async Task Main(string[] args)
{
string bucketName = "mnrst-test-bucket";
try
{
IAmazonS3 s3Client = new AmazonS3Client(RegionEndpoint.USEast1);
ListObjectsResponse response = await s3Client.ListObjectsAsync(new ListObjectsRequest
{
BucketName = bucketName,
MaxKeys = 10
});
foreach (S3Object entry in response.S3Objects)
{
Console.WriteLine($"Key: {entry.Key}");
}
}
catch (Exception e)
{
Console.WriteLine($"Exception: {e.Message}");
}
}
}
検証用アプリケーションで動作確認
$ dotnet run
Key: test.txt
$ unset AWS_ACCESS_KEY_ID
$ unset AWS_SECRET_ACCESS_KEY
$ dotnet run
Exception: Unable to get IAM security credentials from EC2 Instance Metadata Service.
EC2 インスタンスロールを作成
$ export AWS_ACCESS_KEY_ID="your-access-key"
$ export AWS_SECRET_ACCESS_KEY="your-secret-key"
$ aws iam create-role \
--role-name mnrst-test-ec2-role \
--assume-role-policy-document '{
"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
}'
$ aws iam attach-role-policy \
--role-name mnrst-test-ec2-role \
--policy-arn arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
$ aws iam create-instance-profile \
--instance-profile-name mnrst-test-instance-profile
$ aws iam add-role-to-instance-profile \
--instance-profile-name mnrst-test-instance-profile \
--role-name mnrst-test-ec2-role
EC2 インスタンスを作成
$ aws ec2 run-instances \
--image-id ami-023ff3d4ab11b2525 \
--instance-type t2.micro \
--iam-instance-profile Name=mnrst-test-instance-profile
別ターミナルで EC2 インスタンスにログイン
$ aws ssm start-session \
--target i-038aff30e485e26a5 \
--region ap-northeast-1
Amazon Linux に .NET 8 SDK をインストール
$ sudo su - ec2-user
$ sudo yum install -y dotnet-sdk-8.0
EC2 内に検証用アプリケーションを作成
$ dotnet new console -o awss3test --use-program-main
$ cd awss3test
$ dotnet add package AWSSDK.S3
$ cat <<EOF > Program.cs
using System;
using System.Threading.Tasks;
using Amazon;
using Amazon.Runtime;
using Amazon.S3;
using Amazon.S3.Model;
class Program
{
static async Task Main(string[] args)
{
string bucketName = "mnrst-test-bucket";
try
{
IAmazonS3 s3Client = new AmazonS3Client(RegionEndpoint.USEast1);
ListObjectsResponse response = await s3Client.ListObjectsAsync(new ListObjectsRequest
{
BucketName = bucketName,
MaxKeys = 10
});
foreach (S3Object entry in response.S3Objects)
{
Console.WriteLine($"Key: {entry.Key}");
}
}
catch (Exception e)
{
Console.WriteLine($"Exception: {e.Message}");
}
}
}
EOF
EC2 内でアプリケーションの動作確認
$ dotnet run
Exception: User: arn:aws:sts::123456789012:assumed-role/mnrst-test-ec2-role/i-038aff30e485e26a5 is not authorized to perform: s3:ListBucket on resource: "arn:aws:s3:::mnrst-test-bucket" because no identity-based policy allows the s3:ListBucket action
EC2 インスタンスロールに S3 権限を付与
$ aws iam put-role-policy \
--role-name mnrst-test-ec2-role \
--policy-name ListBucketPolicy \
--policy-document '{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::mnrst-test-bucket"
}
]
}'
もう一度 EC2 内でアプリケーションの動作確認
$ dotnet run
Key: test.txt
(おまけ)Lambda の Python で動作確認
import json
import boto3
print('Loading function')
def lambda_handler(event, context):
s3 = boto3.client('s3')
bucket_name = 'mnrst-test-bucket'
try:
response = s3.list_objects_v2(Bucket=bucket_name)
if 'Contents' in response:
for obj in response['Contents']:
print(f"Object Key: {obj['Key']}")
except Exception as e:
print(f"Error: {e}")
return "Done"
Test Event Name
test
Response
"Done"
Function Logs
Loading function
START RequestId: 338b53b9-025b-40fd-b815-c9a1d28c1212 Version: $LATEST
Object Key: test.txt
END RequestId: 338b53b9-025b-40fd-b815-c9a1d28c1212
REPORT RequestId: 338b53b9-025b-40fd-b815-c9a1d28c1212 Duration: 2880.13 ms Billed Duration: 2881 ms Memory Size: 128 MB Max Memory Used: 80 MB Init Duration: 334.51 ms
Request ID
338b53b9-025b-40fd-b815-c9a1d28c1212
タグ: .NET, AWS, aws cli