CLIでAssumeRoleしてみる
Assume Roleについてなんとなく理解はしているつもりでしたが、 手元で動かしたことはなかったのでCLIでAssume Roleをしてみて理解を深めようと思います。
Assume Roleとは?
Returns a set of temporary security credentials that you can use to access AWS resources. These temporary credentials consist of an access key ID, a secret access key, and a security token. Typically, you use AssumeRole within your account or for cross-account access.
AWSのリソースにアクセスするための一時的なセキュリティ認証情報を返します。 これらの一時的な認証情報は「access key ID」「 secret access key」「security token」で構成されています。一般的にあなたのアカウントやクロスアカウントへのアクセスでAssumeRoleを使います。
つまりAssumeRoleとは、AWSのリソースにアクセスするための一時的なクレデンシャルを返す仕組みです。
動かしてみる
今回下記のような状況を想定してAssumeRoleしてみます。
- とあるIAMユーザ(以下IAMユーザAとします)は自身のAWSアカウント内で、Action
iam:ListPolicies
の実行が許可されていません。そのためaws iam list-policies
を実行しても失敗します。 - IAMユーザAが
iam:ListPolicies
の実行が許可されているIAMロールのAssumeRoleを実行し、一時的なクレデンシャルを受け取り、それを使用してaws iam list-policies
を実行します。
それでは必要なIAMポリシーやIAMロールをTerraformで作成していきます。
IAMポリシーとロールの作成
iam:ListPolicies
を許可するポリシーを作成します。
# iam:ListPoliciesを許可するポリシーのドキュメント data "aws_iam_policy_document" "iam-list-policies-policy-document" { statement { sid = "IamListPoliciesPolicyDocument" effect = "Allow" actions = [ "iam:ListPolicies" ] resources = ["*"] } } # iam:ListPoliciesを許可するポリシー resource "aws_iam_policy" "iam-list-policies-policy" { name = "iam-list-policies-policy" policy = data.aws_iam_policy_document.iam-list-policies-policy-document.json }
次にIAMロールの作成です。 次のポリシードキュメントは、作成するIAMロールを誰がAssumeRoleすることができるかを書いたものです。
# 誰にロールを引き渡すかを書いたポリシー data "aws_iam_policy_document" "iam-test-role-policy-document" { statement { sid = "IamTestRolePolicyDocument" effect = "Allow" actions = [ "sts:AssumeRole" ] principals { type = "AWS" identifiers = ["arn:aws:iam::000000000000:user/user_a"] } } }
上記ポリシーを持ったIAMロールを作成します。
# ロールの作成 resource "aws_iam_role" "iam-list-policies-role" { name = "iam-test-role" assume_role_policy = data.aws_iam_policy_document.iam-test-role-policy-document.json }
初めに作成したiam:ListPolicies
を許可するポリシーを上記IAMロールにアタッチします。
# ロールに`iam:ListPolicies`を許可するポリシーをアタッチ resource "aws_iam_role_policy_attachment" "iam-list-policies-role-iam-list-policies-policy-attachment" { role = aws_iam_role.iam-list-policies-role.name policy_arn = aws_iam_policy.iam-list-policies-policy.arn }
以上でIAMユーザAがiam:ListPolicies
の実行可能なIAMロールiam-test-role
をAssumeRoleすることが可能になりました。
AWS CLIからAssumeRoleしてみる
初めにIAMユーザAで下記コマンドを実行してみます。
aws iam list-policies --profile user_a
ユーザAはiam:ListPolicies
が許可されていないので失敗します。
An error occurred (AccessDenied) when calling the ListPolicies operation〜
それでは次にIAMユーザAでAssumeRoleしてみます。
--role-session-name
は任意の文字列です。
aws sts assume-role --role-arn arn:aws:iam::000000000000:role/iam-test-role --role-session-name hoge --profile user_a
すると下記のように一時的なクレデンシャルが返却されます。
{ "Credentials": { "AccessKeyId": "WWWWWWWWWW", "SecretAccessKey": "xxxxxxxxxx", "SessionToken": "yyyyyyyyyy", "Expiration": "2023-11-03T15:10:06+00:00" }, "AssumedRoleUser": { "AssumedRoleId": "ZZZZZZZZZZ:hoge", "Arn": "arn:aws:sts::000000000000:assumed-role/iam-test-role/hoge" } }
これを環境変数にセットして
export ACCESS_KEY_ID=WWWWWWWWWW export SECRET_ACCESS_KEY=xxxxxxxxxx export SESSION_TOKEN=yyyyyyyyyy
下記コマンドを実行すると、今回は成功しました!
aws iam list-policies
AssumeRoleしている状態を抜ける場合は、環境変数を破棄します。
unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN
AssumeRoleを用いて、許可されていないアクションを実行する流れを確認することができました。
LocalStackでAWS KMSを操作してみる
AWS KMS。 AWS認定ソリューションアーキテクトアソシエイトの勉強をしていた時や、仕事で読んだコードで度々見かけていましたが、 実際に自分で操作をしたことがなかったのでLocalStackでKMSを操作してみました。
AWS KMSってなに?
AWS Key Management Service (KMS) を利用すると、データ保護に使用される暗号化キーを一元管理できます。
つまり、データ保護に使用する暗号化キーをAWS側が管理してくれるので、我々が暗号化キーを管理する必要がありません。 IAM ユーザやIAM ロールに適切なポリシーを設定することで、暗号化キーを安全に管理することができます。
KMSをLocalStackで操作してみる
ローカルにpassword.txtというファイルを用意しました。 ファイルの中には平文で mypassword と記述してあります。
$ ls -la password.txt $ cat password.txt mypassword
KMSキーを作成する
平文のパスワードを暗号化したいです。 しかし、暗号化するためのキーは自分で管理したくありません。 暗号化されたパスワードと暗号化に使用したキーの両方を盗まれた場合にパスワードを複合されてしまうからです。 そこでKMSの出番です。KMSは暗号化に使用するキーであるKMSキーを管理してくれます。
$ awslocal kms create-key { "KeyMetadata": { "AWSAccountId": "000000000000", "KeyId": "e6a25557-e58a-4a47-929d-5404b4ac73e1", "Arn": "arn:aws:kms:ap-northeast-1:000000000000:key/e6a25557-e58a-4a47-929d-5404b4ac73e1", "CreationDate": "2023-09-13T10:15:00.026118+09:00", "Enabled": true, "Description": "", "KeyUsage": "ENCRYPT_DECRYPT", "KeyState": "Enabled", "Origin": "AWS_KMS", "KeyManager": "CUSTOMER", "CustomerMasterKeySpec": "SYMMETRIC_DEFAULT", "KeySpec": "SYMMETRIC_DEFAULT", "EncryptionAlgorithms": [ "SYMMETRIC_DEFAULT" ], "MultiRegion": false } }
KMSキーを作成するコマンドを実行するとKMSキーの情報が’返却されます。
暗号化をする際にKeyId
を使用します。
KMSキーを使用して平文のパスワードを暗号化する
下記のコマンドで平文のパスワードpassword.txt
を暗号化し、
encrypted_password.txtを作成します。
KMSキーを作成した際に取得したKeyId
を--key-id
に渡します。
$ awslocal kms encrypt \ --key-id e6a25557-e58a-4a47-929d-5404b4ac73e1 \ --plaintext fileb://password.txt \ --output text \ --query CiphertextBlob | base64 \ --decode > encrypted_password.txt
暗号化されたパスワードの書かれているencrypted_password.txt
を確認すると
平文のパスワードは暗号化されており、KeyId
が記述されています。
$ cat encrypted_password.txt e6a25557-e58a-4a47-929d-5404b4ac73e1?{o???'>pZ??l??A??1?????Ui?&??b??9??+?"??
このKeyId
が記述されていることにより、encrypted_password.txt
を複合化する際にKMSは
このKeyId
を持つKMSキーを使用します。
平文パスワードの削除
暗号化されたパスワード encrypted_password.txt
があり、
それを複合化するためのKMSキーがAWS KMSで管理されています。
平文のパスワードpassword.txtをローカルに置いておく必要はないので削除します。
$ rm password.txt $ ls -la encrypted_password.txt
暗号化されたパスワードの複合化
暗号化されたパスワードにKMSキーのKeyId
が記述されているので、
複合化する際はKMSにKeyId
を知らせる必要はありません。
$ awslocal kms decrypt \ --ciphertext-blob fileb://encrypted_password.txt \ | jq -r '.Plaintext' | base64 --decode > password.txt
$ ls -la encrypted_password.txt password.txt $ cat password.txt mypassword
暗号化されたパスワードを平文で取得できました!
AWS Glue crawlerとAthenaを使ってS3に置いてあるCSVファイルへSQLを実行する
AWS Athenaを使ってS3に置いてあるCSVファイルへSQLを実行する機会はあるのですが、自分で環境構築をしたことがありませんでした。 また、AWS Glueは様々な機能を持っていて、Athenaとどう関係があるのかを理解できていませんでした。 そこで、Athenaの環境構築をTerraformでやってみます。
最低限下記の3つを作成する必要があります。
テーブルについては手動で作成することもできますが、Glueクローラーを使ってCSVファイルから自動で作成することもできます。 今回はGlueクローラーを使います。
Glueクローラーの作成
Glueクローラーを作成するために下記を行います。
resource "aws_glue_catalog_database" "aws_glue_catalog_database_example" { name = "athena-example-database" } data "aws_s3_bucket" "hoge_test_athena_bucket" { bucket = "hoge-test-athena" } data "aws_iam_role" "glue_crawler_athena_example_role" { name = "glue_crawler_athena_example_role" } resource "aws_glue_crawler" "glue_crawler_athena_example" { database_name = aws_glue_catalog_database.aws_glue_catalog_database_example.name name = "athena-example-crawler" role = data.aws_iam_role.glue_crawler_athena_example_role.arn s3_target { path = "s3://${data.aws_s3_bucket.hoge_test_athena_bucket.bucket}" } }
Glueクローラーを実行してテーブルの作成
今回は下記の内容でCSVファイルを用意し、hoge-test-athena
bucketへ置きました。
name,amount,price,producer,country apple,10,1500,Michael,Japan
それでは先ほど作成したクローラの名前を指定して、クローラを実行します。
aws glue start-crawler --name athena-example-crawler
しばらくするとAWSコンソール > AWS Glue > Data Catalog > Databases > Tables
にhoge_test_athena
というテーブルが作成され、テーブルスキーマが生成されていることが確認できました。
SQLの実行
Athenaを使ってSQLを実行します。
実行するにはワークグループを指定する必要があります。
今回は下記のようにdeveloperという名前のワークグループを作成しました。
CloudWatchメトリクスは今回不要なのでfalseに、
また、result_configuration.output_location
でクエリの結果を保存するS3 bucketを指定しています。
data "aws_s3_bucket" "hoge_test_athena_result_bucket" { bucket = "hoge-test-athena-result" } resource "aws_athena_workgroup" "developer" { name = "developer" configuration { publish_cloudwatch_metrics_enabled = false result_configuration { output_location = "s3://${data.aws_s3_bucket.hoge_test_athena_result_bucket.bucket}" } } }
それではクローラによって作成されたテーブルに対してSELECT文を実行してみます。 ワークグループはdeveloperを指定します。
期待通りの結果が確認できました。