PKIベースでAWSのIAMロールを使える IAM Role Anywhereが発表されました。早速使えるようだったのでOpenSSLでCA構築して使ってみた手順を残しておきます。
環境汚さないためにDocker使っています。
AWS Identity and Access Management introduces IAM Roles Anywhere for workloads outside of AWS
What is AWS Identity and Access Management Roles Anywhere? - IAM Roles Anywhere
Extend AWS IAM roles to workloads outside of AWS with IAM Roles Anywhere | AWS Security Blog
- [HostOS] RootCA用のDockerコンテナを起動
- [Docker] OSパッケージインストール
- [Docker] OpenSSLでRootCAを構築
- [AWS] IAM Role Anyware用のIAM Roleを作成
- [AWS] IAM Role Anywareの信頼アンカー設定
- [AWS] IAM Role Anywareのプロファイル設定
- [Docker] クライアント証明書を作成
- [Docker] helperツールを使って証明書からIAM一時アクセス情報を取得
- [Docker] AWS CLIから利用
- [AWS] Pythonから利用
- [ホストOS] RootCA用のDockerを停止
[HostOS] RootCA用のDockerコンテナを起動
RootCAはコンテナ上で構築したいので、まずはDebianのコンテナを rootca
という名前で立ち上げます。
# コンテナ100分間起動します docker run --name rootca -d --rm debian:bullseye-slim sleep 60000 # 起動したコンテナでbashを起動 docker exec -it rootca /bin/bash
以下の作業はこのコンテナ内で実施します。
[Docker] OSパッケージインストール
CA作成とawscliのインストールで必要なパッケージをインストールします。
apt update && apt install -y openssl curl unzip less
[Docker] OpenSSLでRootCAを構築
以下の記事を参考にOpenSSLでRootCAを構築します。
以下のコマンドをコピペで構築されます。
mkdir -p /opt/pki/RootCA mkdir /opt/pki/configs cd /opt/pki/RootCA mkdir newcerts echo "01" > serial echo "00" > crlnumber touch index.txt cat <<'EOF' > /opt/pki/configs/openssl_sign.cnf [ ca ] default_ca = CA_default [ CA_default ] dir = ./ certs = $dir/certs crl_dir = $dir/crl database = $dir/index.txt new_certs_dir = $dir/newcerts serial = $dir/serial crlnumber = $dir/crlnumber crl = $dir/crl.pem RANDFILE = $dir/.rand name_opt = ca_default cert_opt = ca_default default_days = 365 default_crl_days= 30 default_bits = 2048 default_md = sha256 preserve = no policy = policy_match [ policy_match ] countryName = match stateOrProvinceName = match organizationName = match organizationalUnitName = optional commonName = supplied emailAddress = optional [ v3_ca ] subjectKeyIdentifier=hash authorityKeyIdentifier=keyid:always,issuer basicConstraints=CA:true keyUsage = cRLSign,keyCertSign [ v3_client ] subjectKeyIdentifier=hash authorityKeyIdentifier=keyid,issuer basicConstraints = CA:FALSE keyUsage = nonRepudiation, digitalSignature, keyEncipherment extendedKeyUsage = clientAuth crlDistributionPoints = URI:http://127.0.0.1:8200/v1/pki/crl EOF openssl genrsa -out RootCA_key.pem -aes256 -passout pass:rootcaprivkeypass 2048 openssl req -new \ -subj "/C=JP/ST=Tokyo/O=EXAMPLE/CN=EXAMPLE Root CA" \ -out RootCA_csr.pem \ -key RootCA_key.pem \ -passin pass:rootcaprivkeypass openssl ca -config ../configs/openssl_sign.cnf -batch -extensions v3_ca \ -out RootCA_crt.pem \ -in RootCA_csr.pem \ -selfsign \ -keyfile RootCA_key.pem \ -passin pass:rootcaprivkeypass openssl x509 -in RootCA_crt.pem -out RootCA_crt.pem
コマンド完了時は以下のようになります。
次の手順のため証明書のPEMファイルの中身をコピーしておきます。
cat RootCA_crt.pem -----BEGIN CERTIFICATE----- xxx xxx xxx -----END CERTIFICATE-----
[AWS] IAM Role Anyware用のIAM Roleを作成
クライアントからAssumeするIAMロールとして、以下のように Test-IAM-Anyware
(名前は任意)というロールを作成しました。ポリシーにはテスト用に AmazonS3ReadOnlyAccess
を付けてみます。
信頼関係は以下のように設定します。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "rolesanywhere.amazonaws.com" }, "Action": [ "sts:AssumeRole", "sts:SetSourceIdentity", "sts:TagSession" ] } ] }
こちらに記載ありますように、この時点で Condition
入れることで信頼する証明書のフィルタリングも可能です。
"Condition": { "StringEquals": { "aws:PrincipalTag/x509Subject/CN": "Alice" } }
[AWS] IAM Role Anywareの信頼アンカー設定
IAM Role Anywareの管理画面を開きます。ちなみに、IAM Role Anywhereはリージョン毎の設定になります。
https://ap-northeast-1.console.aws.amazon.com/rolesanywhere
信頼アンカーを作成するを選択して、外部証明書のバンドルとして先ほどのPEMファイルを貼り付け、信頼アンカーを作成します。
]
[AWS] IAM Role Anywareのプロファイル設定
プロファイルを作成するを選択して、先ほど作った Test-IAM-Anyware
のロールを指定します。後はそのままで作成します。
ちなみにこちらのブログの例では、ここでIPアドレス制限をかけているので参考になります。
"Condition": { "IpAddress": { "aws:SourceIp": "xxx.xxx.xxx.xxx/xx" } }
これでAWS側の設定は完了です。
[Docker] クライアント証明書を作成
今回は /opt/pki/RootCA
でそのまま作業してしまいます。
以下の手順でクライアント証明書を発行します。
pwd # -> 作業ディレクトリ確認 /opt/pki/RootCA # 鍵を生成 openssl genrsa -out my-key.pem 2048 # CSRを作成 openssl req -new \ -subj "/C=JP/ST=Tokyo/O=EXAMPLE/CN=EXAMPLE Client" \ -out my-csr.pem \ -key my-key.pem # クライアント証明書を発行 openssl ca -config ../configs/openssl_sign.cnf \ -batch -extensions v3_client \ -out my-crt.pem \ -in my-csr.pem \ -cert RootCA_crt.pem \ -keyfile RootCA_key.pem \ -passin pass:rootcaprivkeypass # PEMだけに変換 openssl x509 -in my-crt.pem -out my-crt.pem
# この時点で以下の3ファイルが出力されています ls my-* # -> my-crt.pem my-csr.pem my-key.pem # CAの証明書で発行したクライアント証明書をVerifyしてみて確認します openssl verify -CAfile RootCA_crt.pem my-crt.pem # -> my-cert.pem: OK
この証明書を使ってAWSにアクセスしていきます。
[Docker] helperツールを使って証明書からIAM一時アクセス情報を取得
証明書を使ってIAMロールの認証情報を取得するには以下のhelperツールを利用します。
helperツールをインストールします。
mkdir -p /opt/aws/ curl --output /opt/aws/aws_signing_helper https://s3.amazonaws.com/roles-anywhere-credential-helper/CredentialHelper/latest/linux_amd64/aws_signing_helper chmod +x /opt/aws/aws_signing_helper
AWSの画面から信頼アンカーのARN(trust-anchor-arn)とプロファイルのARN(profile-arn)、 Test-IAM-Anyware
のIAMロールのARNを取得しておき、ツールにパラメータを渡して実行してみます。
※変数に入れている値はダミー値です
ANCHOR_ARN=arn:aws:rolesanywhere:us-west-1:123456789012:trust-anchor/xxxxxx PROFILE_ARN=arn:aws:rolesanywhere:us-west-1:123456789012:profile/xxxxx ROLE_ARN=arn:aws:iam::123456789012:role/Test-IAM-Anyware /opt/aws/aws_signing_helper credential-process \ -certificate my-crt.pem \ -private-key my-key.pem \ -trust-anchor-arn ${ANCHOR_ARN} \ -profile-arn ${PROFILE_ARN} \ -role-arn ${ROLE_ARN}
以下のようにIAMアクセスに必要なトークン情報などが取れます。
{ "Version": 1, "AccessKeyId": "xxxxx", "SecretAccessKey": "xxxxx", "SessionToken": "xxxx", "Expiration": "2022-07-08T01:20:52Z" }
次はこの情報をawscliから利用してみます。
[Docker] AWS CLIから利用
何も入っていないOSなのでawscliのインストールから。
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" unzip awscliv2.zip ./aws/install
以下のバージョンがインストールできました。
aws --version # -> aws-cli/2.7.13 Python/3.9.11 Linux/5.13.0-52-generic exe/x86_64.debian.11 prompt/off
以下のように先ほどのhelperツールのコマンドをawcliのconfigに設定することで、awscliから認証情報が利用できるので、以下の用に設定してみます。
mkdir ~/.aws cat <<EOF > ~/.aws/config [profile anywhere] credential_process = /opt/aws/aws_signing_helper credential-process -certificate /opt/pki/RootCA/my-crt.pem -private-key /opt/pki/RootCA/my-key.pem -trust-anchor-arn ${ANCHOR_ARN} -profile-arn ${PROFILE_ARN} -role-arn ${ROLE_ARN} EOF
これでawscliからも使えるはずです。
まずは、以下のコマンドを実行してみて、Test-IAM-Anyware
にAssumeできていることを確認できました。
aws sts get-caller-identity --profile anywhere { "UserId": "Axxxxxxxxx:xx", "Account": "123456789012", "Arn": "arn:aws:sts::123456789012:assumed-role/Test-IAM-Anyware/xx" }
IAMロールがAssumeできているので、IAMロールの権限に沿ってS3の読み込みも可能になっています。
aws s3 ls --profile anywhere
[AWS] Pythonから利用
以下のようにPython+boto3からも利用可能です。
# Python3インストール apt install -y python3 python3-pip # boto3インストール pip3 install boto3 # PythonワンライナーでS3バケット一覧取得 python3 -c 'import boto3;import pprint;s=boto3.Session(profile_name="anywhere");c=s.client("s3");pprint.pprint(c.list_buckets())'
[ホストOS] RootCA用のDockerを停止
置いておいても100分で停止しますが念のため、コンテナ片付けます。
docker rm -f rootca