LoginSignup
18
0

More than 3 years have passed since last update.

KeycloakのToken Exchangeを活用した一時的なAWSアクセスキーの発行

Last updated at Posted at 2020-12-02

NRI OpenStandia Advent Calendar 2020の3日目は、2日目の続きとしてKeycloakのToken Exchangeを活用した話を紹介します。具体的には、AWSのCLIツールなどの利用で必要なAWSアクセスキーの発行をToken Exchange経由で行うというものです。

やりたいこと

皆さんAWSアクセスキーの管理はどのようにされているでしょうか?誤ってGitリポジトリにコミットしちゃって漏洩し、たくさんEC2インスタンスを起動されて高額請求されちゃう、なんていう事故をたまに聞きますよね。ベストプラクティスとしてそもそも発行しない (EC2インスタンスロールなど、IAMロールで制御する)という考え方がありますが、ローカルPCなどから作業したい場合はどうしても発行が必要になります。そのような場合は、有効期限付きの一時的なAWSアクセスキーを使うと漏洩したときのリスクを減らすことができます。

一時的なAWSアクセスキーの発行

いくつかやり方があります。

AWS SSOを使う

AWS SSOを使って認証を一元化しているのであれば、AWS SSOの画面から一時的なAWSアクセスキーを発行して取得することができます。詳しくは、https://dev.classmethod.jp/articles/aws-sso-temporary-credential/ などで紹介されています。
また、AWS CLI バージョン2からはCLIからもAWS SSOを利用して発行することができます
(AWS SSOを使っている人には本記事はまったく役に立ちません... :angel_tone1:)

サードパーティ製ツールを使う

企業によっては諸事情によりAWS SSOを使わず、AWS管理コンソールへのログインを、KeycloakやADFS、Azure AD、Oktaなどの外部IdPと直接SAMLで連携させている場合があります。この場合は、例えば https://github.com/Versent/saml2aws のようなツールを使うとコマンドラインで一時的なAWSアクセスキーを取得可能になります。ただし saml2aws の実装はスクレイピング方式であり、各IdPのログイン画面に対してログイン処理をエミュレートする形になっています。https://github.com/Versent/saml2aws/blob/3968f0fa20fb71b2e78e1364bce68acc3f4b201a/pkg/provider/keycloak/keycloak.go#L76 あたりを見ると、Keycloakのログイン画面をパースしてログインしていることがわかります。

この方式ですと、ログイン画面のHTMLや認証シーケンスに強く依存しますので、バージョンアップで動かなくなったり、認証フローをカスタマイズしていると対応できなかったりします。また、パスワードをサードパーティ製ツールに渡すというところで懸念があります。理想的にはOpenID Connectなどのフェデレーションを利用して、スクレイピングなしで安全に行いたいところです。

というわけで作ってみた

(随分前ですが) https://github.com/openstandia/aws-cli-oidc というツールを勉強も兼ねて作ってみました。クライアントPCで動作するCLIのネイティブアプリケーションですので、RFC8252 OAuth 2.0 for Native Appsを参考にしつつ実装しています。CLIツールを起動するとブラウザが起動し、OpenID Provider(今回だとKeycloak)で認証が行われます。 ブラウザを使ってKeycloakに認証しているので、パスワードなどのクレデンシャルがCLIツールに流れることありません。 認証後、CLIツールは認可コードフローを経てIDトークンを受け取ります。このIDトークンをAWS STSに渡すことで一時的なアクセスキーを発行することができます(事前に、KeycloakとAWSアカウントとの間でOpenID Connectによるフェデレーション設定が必要です)。

なお、お気づきかもしれませんが、この方式だとToken Exchangeは出てきません(AWS STSがAWS側の独自実装のToken Exchangeではありますが)。

この方式を利用するにはAWS STSがIDトークンの検証を行うために、Keycloakに対して公開鍵を取得するためにHTTPSアクセスが必要になります(図中の番号9の箇所)。よって、Keycloakを社内に立てている場合はネットワーク制約のため実現は難しいでしょう。インターネット上にあるOpenID Provider(Googleやその他IDaaS、パブリッククラウド上にKeycloakを立てているなど)であればこの方式を使うことができますが、社内ネットワーク内にある場合は残念ながら使えません。

そこでSAML2とToken Exchangeを使う

そこで https://github.com/openstandia/aws-cli-oidc では、SAML2とToken Exchangeを使った方式も実装しています。事前に、社内にあるKeycloakとAWSをSAML2でフェデレーション設定をしておきます。SAML2の場合は、フェデレーション設定時にKeycloakの公開鍵を設定する方式になっているため、AWS STSからKeycloakに対して通信が行われることはありません。よって社内ネットワークに配置しても使うことができます。

問題は、CLIツールからKeycloakで認証した後にどうやってAWS STSに渡すSAMLResponseを取得するかです。CLIツールとKeycloakの間はOpenID Connectでフェデレーションしているだけであり、通常だと取得可能なトークンはCLIツール向けに発行されたIDトークンとアクセストークンのみです。ここからどうやってAWS向けのSAMLResponseを生成すればよいかが課題となります。

ここでようやくToken Exchangeが出てきます。つまり、 CLIツール向けに発行されたIDトークンまたはアクセストークンを、AWS向けのSAML2トークンに交換ができればいい わけです。下図でいうと、番号8の箇所ですね。ここでアクセストークンをKeycloakのToken Exchangeを使ってAWS STS用のSAML2アサーションに交換しています。Keycloakバージョン10まではSAML2トークンへの交換に対応していませんでしたが、2日目の記事で紹介したとおり、プルリクエストを送りバージョン11以降は対応しています。

SAML2アサーションに交換できたらそれをSAMLResponseとして少々ラップしてあげて(アサーションのみではAWS STS側が受け付けないため)、番号10のところでAWS STS APIを呼び出してあげれば無事に一時的なAWSアクセスキーを受け取ることができます。

終わりに

というわけで、本記事では2日目に書きました「KeycloakのToken ExchangeのSAML2対応」をどのように活用しているかを紹介しました。意外とSAML2トークンに交換するユースケースが他にあるかもしれません。是非皆さんも探してみてください。

18
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
0