IAM Roles AnywhereをAWS Private CAと連携させ、AWS外から一時クレデンシャルを取得してみた

2023.02.01

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

AWS IAM Roles AnywhereはAWS外のワークロードに対して一時的なAWSクレデンシャルを払い出すサービスです。 公開鍵基盤(PKI)の上に成り立っており、AWS IAM Roles Anywhereのトラストアンカーに登録した認証局(CA)が発行したX.509 証明書を元に、IAMロールを引き受ける一時的なクレデンシャルが払い出されます。

認証局がプラガブルなため、弊社ブログでも過去に様々なパターンが試されています。

一番シームレスに連携できるAWS Private Certificate Authority(以下AWS Private CA)との連携パターンが書かれておらず、インターネット上でもウォークスルー形式の具体的な手順が見当たらなかったので、共有します。

「AWSのことはAWSでせよ」学派の参考になれば幸いです。

ポイント

  • AWS IAM Roles Anywhereはリージョナル・サービス
  • AWS Private CAは有効期限が長い証明書や失効に対応して高価なモードと証明書の有効期限が短くて安価なモードの2モードがある
  • ヘルパーツール経由で一時クレデンシャルを取得。AWS CLI以外から使う場合、一工夫必要
  • 証明書の管理が肝

ウォークスルーの流れ

AWS上にPrivate CA(SHORT_LIVED_CERTIFICATEモード)をCAとして構築して、証明書を発行し、AWS外のクライアントからS3にアクセスします。

1. AWS リージョンを選択する

AWS IAM Roles Anywhereはリージョナル・サービスです。

同じリージョンに

  • AWS Private CA
  • AWS IAM Roles Anywhere

を構築してください。

AWS IAMのようなグローバル・リソースではないため、注意が必要です。

2. AWS Private CAの設定

AWS Private CAのコンソールからプライベートCAを作成します。

AWS Private CAには、有効期限が長期の証明書を発行可能な高価($400/月)な汎用(GENERAL_PURPOSE)モード、有効期限が7日までの証明書しか発行できない安価($50/月)な短期間の証明書(SHORT_LIVED_CERTIFICATE)モードの2モードがあります。

デフォルトの汎用モードは少しお高く感じるかもしれませんが、利用費はオンデマンドベースであり、無料枠も存在します。利用費の詳細は料金ページをご確認ください。

今回はSHORT_LIVED_CERTIFICATEモードで作成しました。

短期間の証明書モードのリリース文にあるように、AWSへ一時的にアクセスさせるIAM Roles Anywhere用途の場合、セキュリティ観点からは、早々に失効する短期間の証明書モードは十分に検討の余地があります。

If you use certificates to convey privileged access, such as with IAM Roles Anywhere, short-lived certificates may offer better security because they expire quickly rather than relying on the need to revoke certificates with a longer validity period.

参考

Private CAを作成が完了したら、ルート証明書をインストールしましょう。

このステップを踏まないと、ステータスは Pending certificate から ACTIVE に遷移しません。

3. クライアントが引き受けるIAM Role の作成

クライアントが引き受けるIAM Roleを作成します。

Permission

用途に合わせたパーミッションを設定してください。

trust relationship

IAM Roles Anywhereがこのロールを引き受けられるよう設定します。

Trusted entities

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": [
                    "rolesanywhere.amazonaws.com"
                ]
            },
            "Action": [
              "sts:AssumeRole",
              "sts:TagSession",
              "sts:SetSourceIdentity"
            ]
        }
    ]
}

トラストアンカーを作成してARNが確定したら、このIAMロールを特定のトラストアンカーだけがassumeできるよう、Condition 条件を追加してください。

Trusted entities

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": [
                    "rolesanywhere.amazonaws.com"
                ]
            },
            "Action": [
              "sts:AssumeRole",
              "sts:TagSession",
              "sts:SetSourceIdentity"
            ],
            "Condition": {
              "ArnEquals": {
                "aws:SourceArn": [
                  "arn:aws:rolesanywhere:region:account:trust-anchor/TA_ID"
                ]
              }
            }
        }
    ]
}

4. AWS IAM Roles Anywhereの設定

トラストアンカーの設定

AWS IAM Roles Anywhereのコンソールに移動し、トラストアンカー(どのCAが発行した証明書を認証するのか?)を設定します。

"Certificate authority (CA) source" には"AWS Certificate Manager Private CA"を選択し、"AWS Certificate Manager Private CA"一覧から、作成したPrivate CAを選択します。

プロファイルの設定

引き受け可能なIAM Role一覧を定義するために、プロファイルを作成します。

Roleには、一つ前のステップで作成したIAM Roleを指定します。

5. クライアント証明書の発行

IAM Roles Anywhereでは、クライアントは証明書ベースで一時的なクレデンシャルを取得できます。

クライアントはAWSへの直接のアクセス権限は不要ですが、クライアント証明書を手配する管理者は、AWSへのアクセス権限、特に、Private CAへの各種権限が必要です。

まず、openssl コマンドを利用し、証明書の署名リクエスト(Certificate Signing Request;CSR)ファイル(csr.pem)と秘密鍵(private-key.pem)を作成します。

$ openssl req -out csr.pem \
  -new -newkey rsa:2048 -nodes \
  -keyout private-key.pem
...

$ ls -1
csr.pem 
private-key.pem

AWS Private CAに対して

  • CAのARN
  • クライアントのCSRファイル

を指定して acm-pca::issue-certificate API でクライアント証明書を発行します。

$ aws acm-pca issue-certificate \
  --certificate-authority-arn arn:aws:acm-pca:ap-northeast-1:123456789012:certificate-authority/d560b578-b14b-4061-88dc-79a3d6a43cb3 \
  --csr fileb://csr.pem \
  --signing-algorithm SHA256WITHECDSA \
  --validity Value=7,Type=DAYS
{
    "CertificateArn": "arn:aws:acm-pca:ap-northeast-1:123456789012:certificate-authority/d560b578-b14b-4061-88dc-79a3d6a43cb3/certificate/2fe5a4c4aee7523abc5b3950660a5cd1"
}

署名アルゴリズム(--signing-algorithm)は以下から指定可能です。

  • SHA256WITHECDSA
  • SHA384WITHECDSA
  • SHA512WITHECDSA
  • SHA256WITHRSA
  • SHA384WITHRSA
  • SHA512WITHRSA

証明書の有効期限(--validity)は Private CAに依存します。

例えば SHORT_LIVED_CERTIFICATE モードのPrivate CA は証明書の有効期限が最大で7日のため、有効期限が10日の証明書を要求すると、以下のエラーが発生します。

An error occurred (ValidationException) when calling the IssueCertificate operation:

The requested certificate validity exceeds the maximum allowed by the usage mode. Reduce the requested validity period to be equal to or less than that supported by the usage mode for this CA or use a CA with a different usage mode.

証明書を発行後は、acm-pca::get-certificate APIで証明書を取得します。

# 証明書の確認
$ aws acm-pca get-certificate \
  --certificate-authority-arn  arn:aws:acm-pca:ap-northeast-1:123456789012:certificate-authority/d560b578-b14b-4061-88dc-79a3d6a43cb3 \
  --certificate-arn arn:aws:acm-pca:ap-northeast-1:123456789012:certificate-authority/d560b578-b14b-4061-88dc-79a3d6a43cb3/certificate/b892cc7ab89826bdde60e291b01f7121
{
    "Certificate": "-----BEGIN CERTIFICATE-----\nMIIDA...dF/1wDgA==\n-----END CERTIFICATE-----",
    "CertificateChain": "-----BEGIN CERTIFICATE-----\nMIICNzC...55zNUEFHdw==\n-----END CERTIFICATE-----"
}

# 証明書を cert.pem にリダイレクト
$ aws acm-pca get-certificate \
  --certificate-authority-arn arn:aws:acm-pca:ap-northeast-1:123456789012:certificate-authority/d560b578-b14b-4061-88dc-79a3d6a43cb3 \
  --certificate-arn  arn:aws:acm-pca:ap-northeast-1:123456789012:certificate-authority/d560b578-b14b-4061-88dc-79a3d6a43cb3/certificate/2fe5a4c4aee7523abc5b3950660a5cd1 | \
  jq -r  .'Certificate' > cert.pem

# cert.pem を確認
$ cat cert.pem
-----BEGIN CERTIFICATE-----
MIIDBDCCAqugAwIBAgIQL+WkxK7nUjq8WzlQZgpc0TAKBggqhkjOPQQDAjB7MQsw
...
LUk8HYm2sUs=
-----END CERTIFICATE-----

openssl コマンドで証明書を確認します。

Issuer フィールドなどから、作成した Private CA から発行されていることがわかります。

$ openssl x509 -in cert.pem -text
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            2f:e5:a4:c4:ae:e7:52:3a:bc:5b:39:50:66:0a:5c:d1
        Signature Algorithm: ecdsa-with-SHA256
        Issuer: C = JP, O = Example LLC, OU = Engineering, ST = Tokyo, CN = Classmethod Root CA 1, L = Chiyoda
        Validity
            Not Before: Jan 31 08:11:20 2023 GMT
            Not After : Feb  7 09:11:19 2023 GMT
        Subject: C = AU, ST = Some-State, O = Internet Widgits Pty Ltd
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:d8:02:49:5e:dd:0b:e6:d3:72:95:45:e5:1c:4d:
                    ...
                    24:87
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Basic Constraints:
                CA:FALSE
            X509v3 Authority Key Identifier:
                D5:A3:0A:5A:47:D3:B2:5F:86:F5:7B:BA:CD:C6:82:84:DC:80:F1:6D
            X509v3 Subject Key Identifier:
                65:C5:3A:E0:6D:F7:D4:F3:A2:22:4A:04:62:92:59:20:AD:04:F5:65
            X509v3 Key Usage: critical
                Digital Signature, Key Encipherment
            X509v3 Extended Key Usage:
                TLS Web Server Authentication, TLS Web Client Authentication
    Signature Algorithm: ecdsa-with-SHA256
    Signature Value:
        ..
-----BEGIN CERTIFICATE-----
MIIDBDCCAqugAwIBAgIQL+WkxK7nUjq8WzlQZgpc0TAKBggqhkjOPQQDAjB7MQsw
...
LUk8HYm2sUs=
-----END CERTIFICATE-----

現段階で、カレントディレクトリには、以下の3ファイルがあります。

$ ls -1
cert.pem          # クライアント証明書
csr.pem           # CSRファイル
private-key.pem   # 秘密鍵

本ステップの手順の詳細は次のドキュメントを参照して下さい。

なお、操作対象はAWS Private CAであり、AWS Certificate Manager (ACM)の操作は一切発生しません。

6. クライアントからのAWS操作

最後のステップです。

IAM Roles Anywhere経由で一時的なAWSクレデンシャルを取得し、AWSリソースを操作します。

管理者はAWSを操作するクライアントに対して以下の情報/ファイルを共有します。

AWSリソース情報

  • トラストアンカーのARN
  • プロファイルARN
  • 引き受けるIAM RoleのARN

ファイル

  • クライアント証明書(cert.pem)
  • 秘密鍵(private-key.pem)

次に、一時クレデンシャルを要求するヘルパーツールをドキュメントにあるリンクから取得します。

今回検証した x86_64 Linux の場合、現時点では以下の通りです。

$ wget https://rolesanywhere.amazonaws.com/releases/1.0.4/X86_64/Linux/aws_signing_helper
$ chmod +x aws_signing_helper
$ sudo mv aws_signing_helper /usr/local/bin
$ aws_signing_helper version
1.0.4

最後に、ヘルパーツールに以下の情報を渡し、IAM Roleを引き受けるための一時クレデンシャルを取得します。

  • クライアント証明書(cert.pem)
  • 秘密鍵(private-key.pem)
  • トラストアンカーのARN
  • プロファイルARN
  • 引き受けるIAM RoleのARN
$ aws_signing_helper credential-process \
  --certificate ./cert.pem \
  --private-key ./private-key.pem \
  --trust-anchor-arn arn:aws:rolesanywhere:ap-northeast-1:123456789012:trust-anchor/cf3d6148-d0d5-4ccc-aee7-0a82ecef1558 \
  --profile-arn arn:aws:rolesanywhere:ap-northeast-1:123456789012:profile/b662d044-9cdc-4bc6-8452-f844f904fe7e \
  --role-arn arn:aws:iam::123456789012:role/roles-anywhere-s3-test | jq .
{
  "Version": 1,
  "AccessKeyId": "ASIAIOSFODNN7EXAMPLE",
  "SecretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
  "SessionToken": "AQoDYXdzEJr...",
  "Expiration": "2023-01-31T10:18:02Z"
}

このレスポンスは、STSで一時クレデンシャルを取得する場合と同等です。

環境変数にクレデンシャルを設定し、AWSリソースを操作してみましょう。

# 環境変数のクレデンシャルを設定
$ export AWS_ACCESS_KEY_ID=ASIAIOSFODNN7EXAMPLE
$ export AWS_SECRET_ACCESS_KEY="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
$ export AWS_SESSION_TOKEN=AQoDYXdzEJr...

# assumeするIAMロールを確認
$ aws sts get-caller-identity
{
    "UserId": "ARXXXXXXXXXX:2fe5a4c4aee7523abc5b3950660a5cd1",
    "Account": "123456789012",
    "Arn": "arn:aws:sts::123456789012:assumed-role/roles-anywhere-s3-test/2fe5a4c4aee7523abc5b3950660a5cd1"
}

# S3を操作
$ aws s3 mb s3://YOUR-BUCKET-NAME
make_bucket: YOUR-BUCKET-NAME

対応するCloudTrailログの抜粋です

{
    "eventVersion": "1.08",
    "userIdentity": {
        "type": "AssumedRole",
        "principalId": "ARXXXXXXXXXX:2fe5a4c4aee7523abc5b3950660a5cd1",
        "arn": "arn:aws:sts::123456789012:assumed-role/roles-anywhere-s3-test/2fe5a4c4aee7523abc5b3950660a5cd1",
        "accountId": "123456789012",
        "accessKeyId": "ASIAIOSFODNN7EXAMPLE",
        "sessionContext": {
            "sessionIssuer": {
                "type": "Role",
                "principalId": "ARXXXXXXXXXX",
                "arn": "arn:aws:iam::123456789012:role/roles-anywhere-s3-test",
                "accountId": "123456789012",
                "userName": "roles-anywhere-s3-test"
            },
            ...
        },
        "invokedBy": "rolesanywhere.amazonaws.com"
    },
    "eventTime": "2023-01-31T09:21:07Z",
    "eventSource": "s3.amazonaws.com",
    "eventName": "CreateBucket",
    "awsRegion": "ap-northeast-1",
    "sourceIPAddress": "rolesanywhere.amazonaws.com",
    "userAgent": "rolesanywhere.amazonaws.com",
    ...
}

IAM Roles Anywhereの文字を散見できますね。

毎回ヘルパーツールを呼び出して、一時クレデンシャルを環境変数に設定するのは手間です。 ~/.aws/config に設定を追加しておくと、AWS CLI実行時に認証情報を暗黙的に一時クレデンシャルを取得・設定します。

~/.aws/config

[profile developer]
    credential_process = ./aws_signing_helper credential-process --certificate /path/to/certificate --private-key /path/to/private-key --trust-anchor-arn arn:aws:rolesanywhere:region:account:trust-anchor/TA_ID --profile-arn arn:aws:rolesanywhere:region:account:profile/PROFILE_ID --role-arn arn:aws:iam::account:role/role-name-with-path

7. 検証後は速やかにリソース削除

今回の構成では、AWSのうっかり高額請求第4位(俺調べ)のAWS Private CAを利用しています。 検証完了後は速やかにリソース削除しましょう。

利用費について

AWS Private CAで証明書を管理した場合の利用費の概算を求めます。

CAのモード Private CA 運用 証明書
GENERAL_PURPOSE $400/月 $0.75 〜 / 証明書
SHORT_LIVED_CERTIFICATE $50/月 $0.058 / 証明書

AWS Private CAの利用費は

  • CAの運用費(モードによる)
  • 証明書発行(GENERAL_PURPOSE はボリュームディスカウント有り)

の2本立てで、オプションとして OCSP を有効にした場合は、その費用も発生します。 また、レートは全リージョン共通です。

仮にプライベートCAを1台運用し、証明書を1000枚/月 発行した場合のそれぞれのモードでの利用費は次のテーブルの通りです。

CAのモード Private CA 利用 証明書 利用費/月
GENERAL_PURPOSE $400 $750 $1150
SHORT_LIVED_CERTIFICATE $50 $58 $108

利用費の詳細や利用費のシミュレーションは料金ページをご確認ください。

最後に

IAM Roles AnywhereのPKI基盤としてAWS Private CAを利用する方法を紹介しました。

多くの処理がAWSにオフロードされており、クライアント向け作業は

  • CSR・秘密鍵の作成
  • クライアント証明書の発行
  • 一時クレデンシャルの取得

だけのため、検証目的であればクライアント環境はAWS CloudShellで十分です。

今回PKIに利用したAWS Private CAは

  • 有効期間が長い証明書の発行や証明書の失効にも対応した高価な汎用(GENERAL_PURPOSE)モード($400/月)
  • 有効期間が最大7日で失効に対応しない安価な短期間の証明書(SHORT_LIVED_CERTIFICATE)モード($50/月)

の2モードがあり、モードによって証明書の運用方針が大きく異なります。

IAM Roles Anywhereでは証明書の運用が肝要です。

クライアントへの証明書の配布方法、認証局の選定など、証明書の運用全般については十分にご検討ください。

それでは。

参考