Có 2 tài khoản aws khác nhau, làm sao để từ EC2 trong tài khoản A có thể access vào S3 của tài khoản B. Chúng ta hoàn toàn có thể làm được điều này khi cấu hình cross-account access giữa hai tài khoản aws.
External ID
.)Trong phần Permissions policies, thêm quyền s3:PutObject
cho bucket trong Account B để cho phép Elastic Beanstalk của Account A tải file lên bucket. Tạo một chính sách tùy chỉnh với nội dung sau:
// Thêm quyền cho role để có thể truy cập đến toàn bộ bucket s3 của tài khoản B
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:ListAllMyBuckets",
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject"
],
"Resource": "arn:aws:s3:::*"
}
]
}
// Chỉ cho phép access đến 1 số bucket
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::your-bucket-name",
"arn:aws:s3:::your-bucket-name/*"
]
}
]
}
Thay your-bucket-name bằng tên bucket của bạn trong Account B.
Đặt tên cho IAM Role, ví dụ: AccountA-Upload-To-S3-AccountB, và nhấn Create role để hoàn tất.
Trong Account A, vào IAM console, tạo một IAM Role dành cho EC2. Gán cho role này quyền sts:AssumeRole để assume role vừa tạo trong Account B. Bạn có thể tạo một chính sách tùy chỉnh như sau:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam:::role/AccountA-Upload-To-S3-AccountB"
}
]
}
Thay bằng Account ID của Account B và AccountA-Upload-To-S3-AccountB là tên IAM Role đã tạo trong Account B.
Gán IAM Role này cho EC2 trong Account A.
ROLE_ARN="arn:aws:iam::{AccountIdAccountB}:role/{RoleCreateFromAccountB}"
CREDS=$(aws sts assume-role --role-arn $ROLE_ARN --role-session-name "EC2ToS3Session")
export AWS_ACCESS_KEY_ID=$(echo $CREDS | jq -r '.Credentials.AccessKeyId')
export AWS_SECRET_ACCESS_KEY=$(echo $CREDS | jq -r '.Credentials.SecretAccessKey')
export AWS_SESSION_TOKEN=$(echo $CREDS | jq -r '.Credentials.SessionToken')
Các lệnh trên sẽ assume role và thiết lập thông tin xác thực tạm thời. Sau đó đùng awl cli để kiểm tra xem có access được đến các bucket của account B không?
aws s3 ls
aws s3 ls s3://your-bucket-name
Nếu liệt kê được các bucket của account B thì config đã thành công.
<?php
require 'vendor/autoload.php';
use Aws\Sts\StsClient;
use Aws\S3\S3Client;
use Aws\Exception\AwsException;
function uploadFileToS3($filePath, $bucketName, $key)
{
// 1. Assume Role
$stsClient = new StsClient([
'version' => 'latest',
'region' => 'ap-northeast-1', // Thay đổi nếu cần
]);
try {
$result = $stsClient->assumeRole([
'RoleArn' => 'arn:aws:iam::{accountIdAccountB}:role/EC2UploaderRoleAccountB', // Role ARN của Account B
'RoleSessionName' => 'PHPAppS3UploadSession',
]);
$credentials = $result->get('Credentials');
// 2. Tạo S3 client với thông tin xác thực tạm thời từ Assume Role
$s3Client = new S3Client([
'version' => 'latest',
'region' => 'ap-northeast-1',
'credentials' => [
'key' => $credentials['AccessKeyId'],
'secret' => $credentials['SecretAccessKey'],
'token' => $credentials['SessionToken'],
],
]);
// 3. Upload file lên S3 bucket trong Account B
$s3Client->putObject([
'Bucket' => $bucketName,
'Key' => $key,
'SourceFile' => $filePath,
]);
echo "File uploaded successfully to {$bucketName}/{$key}";
} catch (AwsException $e) {
// Hiển thị lỗi nếu quá trình assume role hoặc tải lên gặp lỗi
echo "Error: " . $e->getMessage();
}
}
// Gọi hàm để tải file
$filePath = '/path/to/local-file.png'; // Đường dẫn tới file cục bộ
$bucketName = 'bucket-cua-ban'; // Thay bằng tên S3 bucket trong Account B
$key = 'duong-dan-luu-file.png'; // Đường dẫn mong muốn lưu file trên S3
uploadFileToS3($filePath, $bucketName, $key);