はじめに
みなさんはOpenShift上のコンテナからAWSを操作する時、どのような形で権限を付与していますか?よくあるパターンとしてIAMユーザーのアクセスキーとシークレットキーをSecretで環境変数としてアタッチすることが多いかと思います。
しかしAWSでのベストプラクティスでは、システム上での認証はIAMユーザーでなくIAMロールやAWS STS(Security Token Service)による一時的な形での付与を推奨されています。また企業のセキュリティ規約上、システムリソースにIAMユーザーを使うことを明示的にNGにしていることもあるかと思います。
そこで、OpenShift上のコンテナに対して、IAMユーザーの認証情報ではなく、STSを使った一時的な認証情報を渡す方法についてご紹介します。
ここでは、Red Hat OpenShift Service on AWS(ROSA)環境にてSTSによる認証を付与されたPodからAWSリソースにアクセスできるまでの手順をまとめます。
前提条件としてすでにSTSを使ったROSA環境をデプロイできていることを想定しているため、もしこれからSTSを使ったROSAのインストールを実施する場合は以下の赤帽エンジニアブログを参照ください。
また、AWS IPIインストール時の手順は、OpenShiftの構築手順と含めて以下の赤帽エンジニアブログに上げています。
AWS STSを使って一時的な認証情報を扱うOpenShift on AWS環境を構築する
それでは、まずはキーコンポーネントとなるCloud Credential Operatorの説明から。
Cloud Credential Operator(CCO)
Cloud Credential Operator(CCO)はOpenShiftの管理Operatorで、デフォルトでクラスターにインストールされています。 CCOはクラウドの認証情報をCredentialsRequestというカスタムリソースで管理しており、このリソース内に記述したIAMポリシー情報や利用先のNamespace情報を元に、自動的に該当のIAMユーザーの作成とSecretの作成を実施してくれる便利なツールです。 IAMユーザーの利用で問題なければ、上記を活用して簡単にAWSアクセス用のリソースが準備できるのでぜひご利用してみてください。
今回はSTSを使うということなのでOpenShift上のこちらの機能は活用できませんが、CCOはccoctlというバイナリツールを提供しており、それを使うことでCredentialsRequestからSTSを使う場合のSecret yamlファイルを作成することができます。 ちなみにOpenShiftのSTSによるインストールはバージョン4.8からGAになりました。
以下はCCOのgithubにある、STSを使った一時的なCredential付与の概要です。
OpenShiftは、AWS Security Token Service(STS)で様々なコンポーネントの一時的なクレデンシャルを使用するように設定できます。これにより、認証フローが有効になり、コンポーネントがIAMロールを引き受けることができるため、資格情報が短命になります。また、AWS IAM OpenID Connect(OIDC)IDプロバイダーを使用して、Credentialsのリクエストと更新を自動化します。OpenShiftは、AWS IAMによって信頼されているServiceAccountトークンに署名できます。このトークンは、Podにプロジェクションして認証に使用できます。以下は、それがどのように機能するかを示す図です。
https://github.com/openshift/cloud-credential-operator/blob/master/docs/sts.md
ROSA環境におけるSTS利用手順
前提条件
- Linux環境
- ROSAをAWS STSを使った方法でインストール済
- ocコマンド
- AdministratorAccessのIAMユーザー
pull-secretのダウンロード
まずはこちらからpull-secretをダウンロードして実行フォルダに格納してください。
ccoctlバイナリのダウンロード
まずccoctlコマンド実行のための準備を行います。
ROSA環境にcluster-adminでログインしている状態で以下のコマンドを実行します。
今のROSA環境にインストールされているCCOのイメージを取得し、バイナリとしてダウンロードします。
$ CCO_IMAGE=$(oc adm release info --image-for='cloud-credential-operator')
$ oc image extract $CCO_IMAGE --file="/usr/bin/ccoctl" -a ./pull-secret.txt
$ chmod 775 ccoctl
以下コマンドを実行すると正常にダウンロードできているか確認できます。
$ ccoctl aws --help
Creating/updating/deleting cloud credentials objects for AWS cloud
Usage:
ccoctl aws [command]
Available Commands:
create-all Create all the required credentials objects
create-iam-roles Create IAM roles
create-identity-provider Create IAM identity provider
create-key-pair Create a key pair
delete Delete credentials objects
Flags:
-h, --help help for aws
Use "ccoctl aws [command] --help" for more information about a command.
IDプロバイダーのARNを確認
AWSコンソールにログインして、IAM
→IDプロバイダ
からROSA構築時に作成されたIDプロバイダを選択し、表示されたARNをメモしておきます。
CredentialsRequestリソースのyamlファイルを作成
次に、デプロイしたいIAMロールの権限情報を記載したCredentialsRequestリソースのyamlファイルを作成します。
今回はPodからS3バケットの一覧を取得するコマンドを実施したいので、その操作に必要な権限を定義します。
以下は、Secretのデプロイ先Projectを「sts-test」に、またPodに付与するService Accountを「default」にすることを前提として記述しています。
$ mkdir -p sts-test-resource/cred-reqs
$ cd sts-test-resource
$ vi cred-reqs/s3-access-secret.yaml
apiVersion: cloudcredential.openshift.io/v1
kind: CredentialsRequest
metadata:
name: sts-test-cr
namespace: openshift-cloud-credential-operator
spec:
secretRef:
name: s3-access-secret
namespace: sts-test
providerSpec:
apiVersion: cloudcredential.openshift.io/v1
kind: AWSProviderSpec
statementEntries:
- effect: Allow
action:
- s3:ListAllMyBuckets
resource: "*"
serviceAccountNames:
- default
ccoctlコマンドの実行
取得・作成した内容をもとに、ccoctlコマンドを実行してIAMロールの作成とsecretマニフェストの作成を行います。
--identity-provider-arn
には先述の手順で取得したIDプロバイダーのARNを入力します。
$ ccoctl aws create-iam-roles \
--identity-provider-arn arn:aws:iam::XXXXXXXXXXXX:oidc-provider/rh-oidc.s3.us-east-1.amazonaws.com/1ql0oja8ndd2h0s03c9lhmdrtfqev56q \
--output-dir ./outputs \
--name sts-test-rosa \
--region ap-northeast-1 \
--credentials-requests-dir ./cred-reqs/
ポリシーを確認するとCredentialsRequestで指定したポリシーがアタッチされています。
信頼関係を見てみると、ROSAインストール前に構築したIDプロバイダーをプリンシパルとして、sts-test
Namespaceのdefault
サービスアカウントに権限を付与することが読み取れます。
またoutputsディレクトリに、デプロイするためのマニフェストが出力されています。
$ cat outputs/manifests/sts-test-s3-access-secret-credentials.yaml
apiVersion: v1
stringData:
credentials: |-
[default]
role_arn = arn:aws:iam::XXXXXXXXXXXX:role/sts-test-rosa-sts-test-s3-access-secret
web_identity_token_file = /var/run/secrets/openshift/serviceaccount/token
kind: Secret
metadata:
name: s3-access-secret
namespace: sts-test
Secretのデプロイ
outputsディレクトリに出力されたyamlをデプロイします。
$ oc new-project sts-test
$ oc create -f outputs/manifests/sts-test-s3-access-secret-credentials.yaml
これでPodからSTSの認証情報を取得する準備が整いました。
Podのデプロイ
最後にデプロイするPodのyamlファイルを作成していきます。
- デプロイしたSecretを/var/run/secrets/awsにVolumeMount
- awscli実行時の認証ファイルに/var/run/secrets/aws/credentialsを使うようAWS_CONFIG_FILE環境変数を設定
- サービスアカウントのトークンを/var/run/secrets/openshift/serviceaccountに格納するようbound-sa-tokenvolumesを設定(詳細はこちらを参照)
$ vi pod.yaml
apiVersion: v1
kind: Pod
metadata:
annotations:
labels:
run: running-aws
name: running-aws
spec:
containers:
- command:
- tail
- -f
- /dev/null
image: amazon/aws-cli
name: running-aws
resources: {}
env:
- name: AWS_CONFIG_FILE
value: /var/run/secrets/aws/credentials
volumeMounts:
- name: aws-credentials
mountPath: /var/run/secrets/aws
readOnly: true
- name: bound-sa-token
mountPath: /var/run/secrets/openshift/serviceaccount
readOnly: true
volumes:
- name: aws-credentials
secret:
defaultMode: 420
secretName: s3-access-secret
- name: bound-sa-token
projected:
defaultMode: 420
sources:
- serviceAccountToken:
audience: openshift
expirationSeconds: 3600
path: token
上記のPodをデプロイします。
$ oc create -f pod.yaml
実際にPodにログインしてawsコマンドを叩いてみます。
$ oc rsh running-aws
sh-4.2# aws s3 ls
2022-02-28 05:46:27 sts-test-rosa-vlwl8-image-registry-ap-northeast-1-tcfkpstrpeww
無事にS3バケットの情報が取得できました。
最後に
ということで、ROSA環境におけるSTSでの一時的な認証付与を行なったPodの作成方法についてご紹介しました。
CCOの機能を最大限活用するにはIAMユーザーでの運用が望ましいですが、セキュリティ的な側面からIAMユーザー認証が使えない際は、この手法を検討してみてはいかがでしょうか?