EC2上のOSにAWS CLIを導入して、特定のAWSリソースに対してアクセスする際、通常ではアクセスキーとシークレットアクセスキーの両方を指定するかと思います。ただ、セキュリティの観点でキー情報をファイルに平文で記載しておくことはNGとされているので、これを回避する方法を備忘として記載したいと思います。
はじめに
EC2を使用している場合、AWS CLIが導入されているEC2にアタッチされたIAMロールを使って、認証情報(アクセスキーとシークレットアクセスキー)を渡してあげることができます。
基本的には、対象リソースに対して行いたい操作が許可されているポリシーがロールにアタッチされており、そのロールがEC2にアタッチされていれば、特にAWS CLI側のconfig等にアクセスキーやシークレットアクセスキーを記述する必要はないです。
これは、インスタンスプロファイル認証という、IAMロールの持つポリシーの範囲内であれば認証情報無しに実行権限を得られます。認証情報をAWS CLIのconfigに記述する必要がないので、認証情報の漏洩リスクを減らせるというわけです。
このあたりの手順を説明していきます!
ちなみに、今回説明する画面やコマンド結果はWindows Server 2022のものを使用していますが、Linuxでも変わらないので環境に応じて読み替えてもらえれば良いかと!
IAMロールをEC2にアタッチする
今回の構成はこんな感じ。S3バケットに対するアクセス権限のみをEC2に与える想定です。
簡単に検証するために、大元のポリシーはマネージドポリシーのAmazonS3ReadOnlyAccessを使用し、それを使ったロールをEC2にアタッチする形で実現します。
検証開始
まずはロールをアタッチする前の状態確認です。
OSにログインし、awsコマンドのパスが通ったフォルダ上で以下のようにコマンドを実行します。
PS C:\Users\Administrator> aws configure list
Name Value Type Location
---- ----- ---- --------
profile <not set> None None
access_key <not set> None None
secret_key <not set> None None
region ap-northeast-1 imds
PS C:\Users\Administrator>
aws configure list コマンドを実行すると、profile、access_key、secret_key、regionの項目が表示されます。今は~/.aws/configに何も記載しておらず、IAMロールをEC2にもアタッチしていないので、region以外は何も表示されていませんね。
regionはap-northeast-1が設定されていますが、これはEC2インスタンス自身が今どこのリージョンに存在しているかを、自身のメタデータから取得したためですね。(Typeがimdsとなっているのが目印です)
この状態で、EC2からS3バケットにアクセスを試みても、有効な認証情報がないためエラーとなります。
ということで、EC2インスタンスにIAMロール (S3ReadOnlyRole) を用意しましょうか。
アタッチするマネージドのポリシー(AmazonS3ReadOnlyAccess) はこちら。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:Get*",
"s3:List*",
"s3:Describe*",
"s3-object-lambda:Get*",
"s3-object-lambda:List*"
],
"Resource": "*"
}
]
}
ロール (S3ReadOnlyRole) の信頼されたエンティティの記述内容。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
マネージドコンソールからアタッチします(CLIからでもOK)
アタッチ後に再度OS上から、aws configure listコマンドを実行してみると、Typeがiam-roleと表示されたaccess_keyとsecret_keyが追加表示されていますね。
PS C:\Users\Administrator> aws configure list
Name Value Type Location
---- ----- ---- --------
profile <not set> None None
access_key ****************CDKU iam-role
secret_key ****************/aFL iam-role
region ap-northeast-1 imds
PS C:\Users\Administrator>
この状態で再度S3バケットにアクセスを試みると、今回は認証エラーにならずにアクセスできました!
PS C:\Users\Administrator> aws s3 ls s3://a10e-com-s3/
PRE input/
PRE output/
PS C:\Users\Administrator>
アクセスキーを取得して保管する必要がなく、アタッチするだけなので簡単ですね。
AssumeRoleを使用してEC2に権限を付与する
お次の構成はこんな感じです。
先ほどと違って、EC2インスタンスにアタッチするロール自体にS3バケットへのアクセス権限を持たせるのではなく、権限を持たせた別のロールにスイッチする(切り替える)ことで、EC2インスタンスに権限を付与します。
こちらのパターンだと何が良いかというと、柔軟に権限の管理ができる点です。
先ほどのパターンだと、EC2インスタンスにアタッチするロールに、操作を行うための権限が全て付与されている必要があります。
但しこの場合だと、使用するOSユーザーに限らず過剰な権限が与えられることや、ロールの設定が複雑になる傾向にあります。(今後の運用で想定される権限が全て洗い出せて追加も無く、且つ、使用者が管理者やオペレーターといった違うレイヤーの役割が混ざっていなければ良いですが)
特に使うシチュエーションとして、別アカウント上のリソースにアクセスするために、別アカウント上のロールにスイッチする場合なんかがありますかね。
あとは、必要以上にIAMロールが増えてしまって管理が煩雑になる可能性を考えると、作るIAMロールは最小限にして、他のインスタンスやユーザーでも共通で使用できるようになっていることが望ましいかとは思いますね。
検証開始
ということで検証してみます。
EC2インスタンスにアタッチするのはAsumeRoleのみ許可するポリシー (SwitchOnlyPolicy) を用意します。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "*"
}
]
}
ロール (SwitchOnlyRole) の信頼されたエンティティの記述内容。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
スイッチ先ロール (S3ReadOnlyRole) の信頼されたエンティティの記述内容。
今回は、SwitchOnlyRoleがアタッチされたインスタンスのみスイッチロールを許可するよう、Principalを設定しました。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Statement1",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:sts::XXXXXXXXX:assumed-role/SwitchOnlyRole/i-XXXXXXXXXXX"
},
"Action": "sts:AssumeRole"
}
]
}
先ほどと同じように、マネジメントコンソールかCLIからインスタンスにロールをアタッチしておきます。
その後OSにログインし、~/.aws/config に以下のように記述します。
[default]
role_arn = arn:aws:iam::XXXXXXXXX:role/S3AdminRole
credential_source=Ec2InstanceMetadata
role_arn:
スイッチ先のロールのARNを記述します。
credential_source:
認証情報の参照元を指定します。ここで"Ec2InstanceMetadata"を指定することで、インスタンスメタデータにアクセスし、アタッチされたロールから生成された認証情報を取得します。
(参考URL) インスタンスメタデータからのセキュリティ認証情報の取得https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/instance-metadata-security-credentials.html
ロールをアタッチし、AWS CLIの~/.aws/configに記述した状態でaws configure listコマンドを実行すると、最初とは違ってTypeがassume-roleと表示されたaccess_keyとsecret_keyが追加表示されていますね。
PS C:\Users\Administrator> aws configure list
Name Value Type Location
---- ----- ---- --------
profile <not set> None None
access_key ****************5XOB assume-role
secret_key ****************CzlP assume-role
region ap-northeast-1 imds
PS C:\Users\Administrator>
PS C:\Users\Administrator>
PS C:\Users\Administrator> aws s3 ls s3://a10e-com-s3/
PRE input/
PRE output/
PS C:\Users\Administrator>
ちゃんとS3バケットに対してアクセスできていますね。
こんな感じで、AWS CLIでもスイッチロールすることができます!
終わりに
今回AWS CLIで使用するアクセスキーとシークレットアクセスキーの平文を記述を避ける方法として、IAMロールを使用した認証方法を2つご紹介しました。
大して設定も難しくないですが、ちょっとしたことでセキュリティを向上できるため、可能な限り実装しておきたいもんですね・・・!