#目的
- ソースにアクセスキーを書かない
- ローカルにセキュリティキーをそのまま置かない <- 開発環境
- スイッチ先のRDSに接続したい、S3のデータを取りたい ...
#プロフィール準備
ローカルまたは運用サーバにAWS1のUSERのプロフィールを作成
(ECSのようなサーバレスは環境変数にSSMを利用)
STS(Security Token Service)を使用してスイッチ先のクレデンシャル取得
クレデンシャル取得フロー
AWS1(IAM USER) -> スイッチ先:AWS{2-N}(IAM ROLE)
IAM
AWS1 IAM USER
arn:aws:iam::012345678:user/aspnet
ポリシー
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"sts:AssumeRole"
],
"Resource": [
"*"
]
}
]
}
スイッチ先 IAM Role
arn:aws:iam::123456789:role/aspnet
信頼関係
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::012345678:user/aspnet",
]
},
"Action": "sts:AssumeRole"
}
]
}
例).NET Application
プロファイル追加
Set-AWSCredentials -AccessKey XXXXX -SecretKey XXXXX -StoreAs aspnet -ProfileLocation C:\workspace\ps1\credentials
app.config
<appSettings>
<add key="AwsRoleArnBaseProfile" value="aspnet"/> ← IAM USER
<add key="AwsRoleArnAws1" value="arn:aws:iam::123456789:role/aspnet"/> ← スイッチ先Role
<add key="AwsRoleArnAws2" value="arn:aws:iam::234567891:role/aspnet"/>
...
<!-- サーバ側はユーザプロファイルではないフォルダを指定 -->
<add key="AWSProfilesLocation" value="C:\workspace\ps1\credentials" />
...
</appSettings>
AmazonConfig.cs
using Amazon;
using Amazon.SecurityToken;
using Amazon.SecurityToken.Model;
using Amazon.Runtime;
using Amazon.Runtime.CredentialManagement;
//スイッチ先
public enum AccountNo
{
AWS1 = 1,
AWS2 = 2,
...
}
function ... (AccountNo accountNo){
var roleArn = $"AwsRoleArnAws{(byte)accountNo}"; //accountNo: 1~N
var chain = new CredentialProfileStoreChain();
AWSCredentials awsCredentials;
var profile = System.Configuration.ConfigurationManager.AppSettings["AwsRoleArnBaseProfile"];
if (chain.TryGetAWSCredentials(profile, out awsCredentials))
{
var sts = new AmazonSecurityTokenServiceClient(awsCredentials);
var arn = System.Configuration.ConfigurationManager.AppSettings[roleArn];
var stsreq = new AssumeRoleRequest
{
RoleArn = arn,
RoleSessionName = $"{(byte)accountNo}_{region.SystemName}_{DateTime.Now.ToString("yyyyMMddHHmmsssss")}",
DurationSeconds = 900
};
var stsres = sts.AssumeRole(stsreq);
StsCredentials = stsres.Credentials;
}
}
Ec2Service.cs
using Amazon;
using Amazon.EC2;
using Amazon.EC2.Model;
...
aconf = new AmazonConfig(accountNo);
IAmazonEC2 client = new AmazonEC2Client(aconf.StsCredentials, RegionEndpoint.APNortheast1);
...
参考
-
https://docs.aws.amazon.com/ja_jp/sdk-for-net/v3/developer-guide/net-dg-config-creds.html
-
https://dev.classmethod.jp/articles/sts-temporality-credential/
-
名前付きプロファイル
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-configure-profiles.html
https://docs.aws.amazon.com/ja_jp/powershell/latest/userguide/specifying-your-aws-credentials.html
(Windowsはオプションでセキュリティキーが暗号化され保存される <-開発環境) -
AWS SDK for .NET can't access credentials with IIS
https://stackoverflow.com/questions/25560545/aws-sdk-for-net-cant-access-credentials-with-iis
バグ対応
リリースすると本番環境のみ、下記のエラーが、
アセンブリ 'AWSSDK.Core, Version=3.3.0.0, Culture=neutral, PublicKeyToken=885c28607f98e604' から型 'Amazon.Runtime.SharedInterfaces.ICoreAmazonSTS_WebIdentity' を読み込めませんでした。
説明: 現在の Web 要求を実行中に、ハンドルされていない例外が発生しました。エラーに関する詳細および例外の発生場所については、スタック トレースを参照してください。
例外の詳細: System.TypeLoadException: アセンブリ 'AWSSDK.Core, Version=3.3.0.0, Culture=neutral, PublicKeyToken=885c28607f98e604' から型 'Amazon.Runtime.SharedInterfaces.ICoreAmazonSTS_WebIdentity' を読み込めませんでした。
STSを実装したアセンブリを参照するプロジェクトに古いAWSSDK.SecurityTokenが残っていた。削除で解決。半日飛んだー
https://hydracards.hydratecinc.com/cards/card-839