AWSでIAMユーザを使い捨てにする


はじめに

私が所属するaslead DevOpsチームでは、日々変化するユーザの開発サーバ構成に対して、セキュリティを保ちつつ開発業務の効率化・自動化ができないかを検討しています。

この記事では、AWSにログインして作業するIAMユーザの扱い方についてご紹介します。AWSの中でもセキュリティの基礎となる重要サービスであり、ユーザの棚卸しや権限の管理に時間を割かれているチームも多いのではないでしょうか。
そこで、Hashicorp社が提供しているVaultを利用し、作業のタイミングでIAMユーザを作成し、終わったら削除するアプローチを考えてみます。IAMユーザの作成自体はVaultの標準機能ですが、複数アカウントの権限制御ができるスイッチロールとの組み合わせを提案します。

Vaultとは


(画像は https://medium.com/hashicorp-engineering/vault-enterprise%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6-%EF%BC%91-e5579c2fb8d5 より引用)

公式サイトより、Vaultは主に以下のような機能を持っています。

  • Secret Management:様々な環境のパスワードのライフサイクルを管理する
  • Data Encryption:データの暗号化/複合化を行う(データ自体は保持せず、変換だけ)
  • Identity-based Access:同一人物の様々な環境上のアカウントを一つに取りまとめる

本記事ではSecret Managementに分類される機能を取り扱います。

想定するIAMユーザ運用

以下のようなAWSの不正利用のリスクがある運用ケースを想定し、解消を試みてみます。

  • チームから移動したメンバのIAMユーザは手動で削除している
  • 強い権限を持った、アクセスキーが固定の機械ユーザがいる
  • アクセスキーの発行操作に特に制限をかけていない

Vaultによる解決策

上記のリスクに対し、今回はAWS Secret EngineでIAMユーザを作成し、スイッチロールで作業するアプローチをとってみます。

これにより、以下のようなメリットがもたらされます。

  • Vault以外に固定のIAMユーザが不要になり、IAMユーザの管理が容易になる
  • 利用時のみ機械ユーザを作成することで、アクセスキーの流出リスクを低減できる
  • Vault側でLDAPなどと組み合わせれば、アクセスキー(IAMユーザ)の発行を制御できる

以下では具体的にVaultを構築し、発行したIAMユーザでスイッチロールする部分について実装していきます。なお、上記では作業対象のAWSアカウント上にVaultを構築していますが、異なるAWSアカウントに対してもIAMユーザの発行が可能です。

実装

実装する環境

今回は以下の環境で実装を行います。
AWS上でVaultを構築していますが、ローカルでも確認可能な内容になっています。

  • Vault:ver1.5.4
  • OS:Amazon Linux 2
  • IaaS:AWS EC2サービス

OS部分の構築

本記事の主な解説対象ではないため、割愛します。
Acrovision社の記事などが参考になるかと思います。

以降は、Vaultが稼働するOSをvaultというホスト名で作成した前提で進みます。

Vaultのインストール

2020/07/24より、Linuxレポジトリからの取得が可能になりましたので、こちらを利用してvaultに対してインストールしていきます。

$ sudo yum install -y yum-utils
Loaded plugins: extras_suggestions, langpacks, priorities, update-motd
amzn2-core                                                       | 3.7 kB  00:00:00
Package yum-utils-1.1.31-46.amzn2.0.1.noarch already installed and latest version
Nothing to do

$ sudo yum-config-manager --add-repo https://rpm.releases.hashicorp.com/AmazonLinux/hashicorp.repo
Loaded plugins: extras_suggestions, langpacks, priorities, update-motd
adding repo from: https://rpm.releases.hashicorp.com/AmazonLinux/hashicorp.repo
grabbing file https://rpm.releases.hashicorp.com/AmazonLinux/hashicorp.repo to /etc/yum.repos.d/hashicorp.repo
repo saved to /etc/yum.repos.d/hashicorp.repo

$ sudo yum install -y vault
~中略~
Complete!

説明の簡便のため、起動は開発者モードで行います。
-dev-listen-addressvaultのIPアドレスを含めて下さい。EC2の場合は下記のようにメタデータから取得することができます。

$ vault server -dev -dev-root-token-id="root" -dev-listen-address="$(curl -s http://169.254.169.254/latest/meta-data/local-ipv4):8200"
==> Vault server configuration:

             Api Address: http://172.31.39.141:8200
                     Cgo: disabled
         Cluster Address: https://172.31.39.141:8201
              Go Version: go1.14.7
              Listener 1: tcp (addr: "172.31.39.141:8200", cluster address: "172.31.39.141:8201", max_request_duration: "1m30s", max_request_size: "33554432", tls: "disabled")
               Log Level: info
                   Mlock: supported: true, enabled: false
           Recovery Mode: false
                 Storage: inmem
                 Version: Vault v1.5.4
             Version Sha: 1a730771ec70149293efe91e1d283b10d255c6d1
~中略~
==> Vault server started! Log data will stream in below:
~省略~

ブラウザからApi Addressに記載されたアドレス(上記ではhttp://172.31.39.141:8200)にアクセスし、下記のようにログイン画面が表示されればインストールと起動は完了です。

IAMユーザの発行

AWS管理コンソールの作業

Vaultが利用するIAMユーザを作成します。ここではvaultという名称にしています。

作成の際、以下のようにIAMの操作権限を付与してください。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "iam:*",
            "Resource": "*"
        }
    ]
}

IAMユーザが作成されたら、アクセスキーIDとシークレットアクセスキーを控えておきます。

Vaultの作業

IAMユーザの発行にはAWS Secret Engineという機能を利用します。
新規でvaultのターミナルを開き、AWS Secret Engineを有効化します。
access_keysecret_keyには先ほどIAMユーザを作成したときに控えておいた値を入れます。

$ export VAULT_ADDR="http://$(curl -s http://169.254.169.254/latest/meta-data/local-ipv4):8200"

$ vault secrets enable -path=aws aws
Success! Enabled the aws secrets engine at: aws/

$ vault write aws/config/root \
    access_key=XXXXXXXXXXXXXXX \
    secret_key=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX \
    region=ap-northeast-1

作成するIAMユーザにはロールという単位で権限を付与します。このロールも作成していきます。
今回はスイッチロールを利用するため、以下のようなonly-switchというロールを作成します。

$ vault write aws/roles/only-switch \
         credential_type=iam_user \
         policy_document=-<<EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "sts:AssumeRole"
            ],
            "Resource": "*"
        }
    ]
}
EOF
Success! Data written to: aws/roles/only-switch

ブラウザからvaultサーバに8200ポートでアクセスし、Tokenにrootを入力してログインします。ログイン後、Secrets>awsにアクセスすると、only-switchのロールが表示されているはずです。右の三点リーダからGenerate credentialsを選択します。

Credential typeIAM Userを選択したまま、Generateをクリックします。

IAMユーザが作成されました。アクセスキーIDとシークレットアクセスキーは画面遷移すると参照できなくなってしまうため控えておきます。
Lease durationで表示されているのがこのIAMユーザの有効期間です。本記事では割愛しますが、デフォルトの2,764,800秒(32日間)から60秒まで短くすることができます。

AWS管理コンソールでも確認すると、only-switchというポリシーが直接アタッチされたIAMユーザが作成されていることが確認できます。

スイッチロールでの作業

ここまでの手順で作成したIAMユーザに様々な権限をロールとして付与していくことでAWSの不正利用のリスクは低減できるのですが、既に複数のAWSアカウントでIAMロールを用意して運用されているケースが多いかと思います。

Vaultで作成したIAMユーザでスイッチロールを可能にするすることで、複数アカウントの権限制御に対処します。
AWSの公式ドキュメントをもとに実装していきます。

AWS管理コンソールの作業

例えばIAMの操作を行うロールを作成することを想定し、IAM-Adminという名前で以下のようなポリシーを作成します。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "iam:*"
            ],
            "Resource": "*"
        }
    ]
}

IAM-Adminという名前でロールを作成します。信頼されたエンティティは別のAWSアカウントを指定し、アカウントIDにはVaultがIAMユーザを作成するAWSアカウントのIDを入力してください。
ポリシーは先ほど作成しIAM-Adminポリシーをアタッチします。

IAMロールが作成されたら、ロールARNを控えておきます。

AWS CLIの作業

AWS CLIをインストールしていない方は公式ドキュメントをもとにインストールして下さい。
aws configureで作成したIAMユーザのアクセスキーIDとシークレットアクセスキーを設定します。

$aws configure
AWS Access Key ID []: XXXXXXXXXXXXXXXXXXXXXX
AWS Secret Access Key []: YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY
Default region name []:ap-northeast-1
Default output format []:json

.aws/configファイルにiamadminというプロファイルを追記し、IAM-AdminロールのARNを設定します。

[profile iamidmin]
    role_arn = arn:aws:iam::XXXXXXXXXXXX:role/IAM-Admin
    source_profile = default

動作検証として、以下のようにIAM-Adminの情報が取得できればスイッチロールは成功です。

$aws iam get-role --role-name IAM-Admin --profile iamadmin
{
    "Role": {
        "Path": "/",
        "RoleName": "IAM-Admin",
~~中略~~        
    }
}

--profile iamadmin無しで実行するとエラーとなり、作成されたIAMユーザの認証情報だけでは権限がないことが確認できます。

$aws iam get-role --role-name IAM-Admin
An error occurred (AccessDenied) when calling the GetRole operation: 
User: arn:aws:iam::XXXXXXXXXXXXX:user/vault-token-only-switch-XXXXXXXXXXXXXXX
is not authorized to perform: iam:GetRole on resource: role IAM-Admin

まとめ

本記事で伝えたかったことは以下の2点です。

  • Hashicorp VaultでIAMユーザを使い捨てにすることでアクセスキーの流出リスクを低減できる
  • スイッチロールと組み合わせることで既存のIAMロール運用から少ない修正で適用することができる