【新機能】Auth0でAWSリソースをABAC!AWS Session TagとAuth0を組み合わせてみた #reinvent #Auth0JP

AWS Session Tagとは?

AWS Session Tagはre:Invent 2019期間中に新しく発表されたIdentity Federationのための新機能です。概要は臼田の記事を参考にしてください。

[UPDATE]フェデレーションでタグを渡せるSTSの新機能Session Tagがリリースされました #reinvent

AWS公式ブログでも紹介されている通り、SAMLやOIDC (OpenID Connect)といった標準的なプロトコルに準拠しているIDプロバイダであればIAMのABACが実現できます。

Auth0ももちろん対応!そしてAuth0の公式ドキュメントもすでに用意されていました。

ということでやってみましょう!

Tagの追加

まずはABACを行う先として、適当なEC2インスタンスにTagを設定します。

Exampleとしては次のような感じです。

インスタンス番号 Tags
1 Key: CostCenter, Value: marketing
Key: Project, Value: website
2 Key: CostCenter, Value: engineering
Key: Project, Value: management_dashboard
3 Key: CostCenter, Value: marketing
Key: Project, Value: community_site

これらのTagが付いたインスタンスの操作権限を、Auth0経由で実施するというわけです。

IAM Roleの作成

次にAuth0をSAMLプロバイダとしたIAM Roleを作ります。

まずはじめにサービスプロバイダの作成が必要です。本記事では割愛しますが、以下で詳細に解説されていますのでご覧ください。今回はAuth0をSAML IdPとして利用します。

Auth0第一歩 ~複数のAWSアカウントにSAML認証でシングルサインオン~

サービスプロバイダを作成後、IAM Roleを作ります。ウィザードで表示されるタイプは一番右側の「SAML 2.0」を選択します。

Policyは以下のようにします。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ec2:DescribeInstances"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "ec2:StartInstances",
                "ec2:StopInstances"
            ],
            "Resource": "*",
            "Condition": {
                "StringEquals": {
                    "ec2:ResourceTag/CostCenter": "${aws:PrincipalTag/CostCenter}"
                }
            }
        }
    ]
}

${aws:PrincipalTag/CostCenter} がミソです。

Role nameはドキュメント通り AccessByCostCenter としました。

作成後、Trust relationshipsを以下のように編集します。ConditionStringLikeに、Session Tagで使う予定のタグを列挙します。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowSamlIdentityAssumeRole",
            "Effect": "Allow",
            "Action": [
                "sts:AssumeRoleWithSAML",
                "sts:TagSession"
            ],
            "Principal": {"Federated":"arn:aws:iam::123456789012:saml-provider/ExampleCorpProvider"},
            "Condition": {
                "StringLike": {
                    "aws:RequestTag/CostCenter": "*",
                    "aws:RequestTag/Project": "*"
                },
                "StringEquals": {"SAML:aud": "https://signin.aws.amazon.com/saml"}
            }
        }
    ]
}

Auth0 Ruleの作成

次にAuth0の設定です。Ruleを新規に作成します。

Auth0を知らない方向けに解説をすると、RuleはAuth0でかなり特徴的な機能です。Ruleを使うことで、サインインが行われる、またはセッションがリフレッシュされるタイミングで独自の関数を呼び出すことができます。今回の場合はSAMLのAttributeに情報を付与するために使っています。

メニューから「Rule」を選び、「CREATE RULE」をクリックします。

「Empty rule」を選択します。

エディタに以下のコードを貼り付けます。

function(user, context, callback) {
  var awsAccount = '【AWSアカウントIDを指定する】';
  var rolePrefix = `arn:aws:iam::` + awsAccount; 
  var samlIdP = rolePrefix + `:saml-provider/auth0SamlProvider`;

  user.awsRole = rolePrefix + `:role/AccessByCostCenter,` + samlIdP;
  user.awsRoleSession = user.email;
  user.awsTagKeys = ['CostCenter', 'Project'];
  user.CostCenter = 'marketing';
  user.Project = 'website';

  context.samlConfiguration.mappings = {
    'https://aws.amazon.com/SAML/Attributes/Role': 'awsRole',
    'https://aws.amazon.com/SAML/Attributes/RoleSessionName': 'awsRoleSession',
    'https://aws.amazon.com/SAML/Attributes/PrincipalTag:CostCenter': 'CostCenter',
    'https://aws.amazon.com/SAML/Attributes/PrincipalTag:Project': 'Project'
  };

  callback(null, user, context);
}

ここでは user.CostCenter = 'marketing' などといったようにハードコーディングしていますが、例えばAuth0のRole機能と組み合わせて指定したり、メールアドレスのドメインで切り分けたりするなどもできますね。

試してみる

それでは試してみましょう!まずはSAMLログインページよりログインします。

AWS Management Consoleにログインできました。はじめに紹介した表を改めて提示します。

インスタンス番号 Tags
1 Key: CostCenter, Value: marketing
Key: Project, Value: website
2 Key: CostCenter, Value: engineering
Key: Project, Value: management_dashboard
3 Key: CostCenter, Value: marketing
Key: Project, Value: community_site

今回は user.CostCenter = 'marketing' というユーザーになっていますので、「1」のインスタンスの操作権限だけ持っています。当然インスタンスの操作が行えます。

「2」のインスタンスを操作しようとすると、操作が実行できないエラーが発生します。

まとめ

Auth0はSAML IdPにもOIDC Providerにもなれるので、Session Tagへの対応は非常に簡単です。またAuth0の最大の特徴である 接続先の柔軟性 の本領発揮ができる場面でもあります。どのような認証サーバーであっても、Auth0がSAML IdP/OIDC Providerに変換することで、今回の機能を使えるようにできるという訳です。

参考記事