AWS S3 にアクセスする際、異なる認証方法を選択できます。具体的なユースケースとセキュリティ要件に応じて、以下の2つの主要な方法があります。
1. AWS SDK と IAM ユーザー/ロールを使用したアクセス
AWS SDK と IAM ユーザーまたはロールを使用する方法は、一般的かつ安全な方法です。この方法では通常、アクセスキー(Access Key)とシークレットキー(Secret Key)が必要で、適切な権限を得るために IAM ロールを指定することもあります。
利点:
詳細な権限制御:IAM ポリシーを通じて、誰がどのリソースにアクセスできるか、どの操作を実行できるかを細かく制御できます。
高いセキュリティ:ロールや一時的なセキュリティ認証情報(例:STS)を使用してセキュリティを強化できます。
複雑な権限要件やマルチユーザー環境に適しています。
方法①
下記のやり方はこちら側が検証されていませんので。一旦記録します
public class AwsS3Access {
private static final String ACCESS_KEY = 'YOUR_ACCESS_KEY';
private static final String SECRET_KEY = 'YOUR_SECRET_KEY';
private static final String REGION = 'YOUR_REGION';
public void listS3Buckets() {
String service = 's3';
String host = 's3.' + REGION + '.amazonaws.com';
String endpoint = 'https://' + host + '/';
// Create date for headers and the credential string
Datetime now = Datetime.now();
String amzDate = now.formatGmt('yyyyMMdd\'T\'HHmmss\'Z\'');
String dateStamp = now.formatGmt('yyyyMMdd'); // Date w/o time, used in credential scope
// ************* TASK 1: CREATE A CANONICAL REQUEST *************
String method = 'GET';
String canonicalUri = '/';
String canonicalQuerystring = '';
String canonicalHeaders = 'host:' + host + '\n' + 'x-amz-date:' + amzDate + '\n';
String signedHeaders = 'host;x-amz-date';
String payloadHash = EncodingUtil.convertToHex(Crypto.generateDigest('SHA-256', Blob.valueOf('')));
String canonicalRequest = method + '\n' + canonicalUri + '\n' + canonicalQuerystring + '\n' + canonicalHeaders + '\n' + signedHeaders + '\n' + payloadHash;
// ************* TASK 2: CREATE THE STRING TO SIGN *************
String algorithm = 'AWS4-HMAC-SHA256';
String credentialScope = dateStamp + '/' + REGION + '/' + service + '/' + 'aws4_request';
String stringToSign = algorithm + '\n' + amzDate + '\n' + credentialScope + '\n' + EncodingUtil.convertToHex(Crypto.generateDigest('SHA-256', Blob.valueOf(canonicalRequest)));
// ************* TASK 3: CALCULATE THE SIGNATURE *************
Blob signingKey = getSignatureKey(SECRET_KEY, dateStamp, REGION, service);
String signature = EncodingUtil.convertToHex(Crypto.generateMac('HMACSHA256', Blob.valueOf(stringToSign), signingKey));
// ************* TASK 4: ADD SIGNING INFORMATION TO THE REQUEST *************
String authorizationHeader = algorithm + ' ' + 'Credential=' + ACCESS_KEY + '/' + credentialScope + ', ' + 'SignedHeaders=' + signedHeaders + ', ' + 'Signature=' + signature;
HttpRequest req = new HttpRequest();
req.setEndpoint(endpoint);
req.setMethod(method);
req.setHeader('x-amz-date', amzDate);
req.setHeader('Authorization', authorizationHeader);
Http http = new Http();
HttpResponse res = http.send(req);
if (res.getStatusCode() == 200) {
System.debug('Response: ' + res.getBody());
} else {
System.debug('Error: ' + res.getStatus() + ' ' + res.getBody());
}
}
private static Blob getSignatureKey(String key, String dateStamp, String regionName, String serviceName) {
Blob kDate = Crypto.generateMac('HMACSHA256', Blob.valueOf(dateStamp), Blob.valueOf('AWS4' + key));
Blob kRegion = Crypto.generateMac('HMACSHA256', Blob.valueOf(regionName), kDate);
Blob kService = Crypto.generateMac('HMACSHA256', Blob.valueOf(serviceName), kRegion);
Blob kSigning = Crypto.generateMac('HMACSHA256', Blob.valueOf('aws4_request'), kService);
return kSigning;
}
}
方法➁
指定ログイン情報を作成し、AWS S3 APIをアクセス
APEX側コードが減らす
//APEX
public class C_AWSS3Connecter {
public static HTTPResponse fileUpload(String contentType,Blob dataBlob,String kmsKeyId,String filename){
HttpRequest req = new HttpRequest();
req.setEndpoint('callout:AWSConnectTest/' + fileName);
req.setHeader('Content-Type',contentType);
req.setBodyAsBlob(dataBlob);
req.setMethod('PUT');
Http http = new Http();
HTTPResponse res = http.send(req);
return res;
}
}
AWSConnectTestは指定ログイン情報の名前
指定ログイン情報の作成は下記のblogを参照してください
https://qiita.com/shinsaka/items/a1e6dce886697f175af9
リンク
Salesforceヘルプ:指定ログイン情報と外部ログイン情報
https://help.salesforce.com/s/articleView?id=sf.nc_named_creds_and_ext_creds.htm&type=5
Amazon S3 APIリファレンス
https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListBuckets.html
従来機能で試した過去のポスト
https://qiita.com/shinsaka/items/f11cf54373c4fe49b0a9
Winter '23から変更になったということのようですね。
https://developer.salesforce.com/blogs/2022/10/announcing-the-next-generation-of-named-credentials
2. API Gateway *REST API を使用したアクセス
x-api-key を使用する方法は、通常 API Gateway を経由した REST API に対して使われます。API Gateway は S3 へのリクエストのフロントエンドとして機能し、x-api-key の設定を通じて認証を行うことで、アクセスを簡略化します。
利点:
簡単なアクセス制御:API Gateway はリクエストのフロントエンドとして機能し、x-api-key を設定することで簡単に認証を行えます。
管理が容易:API Gateway を利用した公開アクセスやサードパーティアプリケーションに適しています。
柔軟性:API Gateway は他の認証方法(例:Cognito ユーザープール)とも統合可能です。
方法①
ApexでURL、Headerを組み合わせて、requestする(検証済み、OK)
HttpRequest req = new HttpRequest();
req.setEndpoint('https://api.example.com/your-endpoint');
req.setMethod('POST');
req.setHeader('Content-Type', 'application/json');
req.setHeader('x-api-key', 'YOUR_API_KEY_HERE');
// リクエストボディを構築し、リクエストを送信
方法➁
指定ログイン情報を作成し、AWS APIをアクセス(検証されていない,できると思います)
HttpRequest req = new HttpRequest();
req.setEndpoint('callout:AWSMasterAPI/');
req.setMethod('GET');
Http http = new Http();
HttpResponse res = http.send(req);
System.debug(res.getBody());
最後の最後,1でも、2でも salesforceにRemote Siteの設定が必要です。
3. Amazon Cognito を使用したアクセス
これはしばらく紹介しない