maybe daily dev notes

私の開発日誌

Amazon OpenSearch Serviceのfine-grained access control機能をCDKで管理する

Amazon OpenSearch Serviceでは、ドメインに対するアクセス制御の手段の一つとして、Fine-grained access control (きめ細かいアクセス制御、以下FGAC) が利用できます。 この記事では、FGACの設定をAWS CDKから管理する方法を紹介します。

なぜFGACを使うか

はじめに、FGACを知らない方・使っていない方のために、モチベーションを整理します。すでにご存知の方は読み飛ばしてください。

FGACを使わない場合、OpenSearch Serviceでは以下の方法でアクセス制御することができます。

  • リソースベースのポリシー (ドメインアクセスポリシーとも)
    • ドメインに対して1つだけ付与できるポリシーです
  • アイデンティティベースのポリシ
    • 利用側のIAMロール/ユーザーに付与するポリシーです

用意されているIAMのアクションは下表の通りであり、この程度の粒度で権限を設定できます。IAMポリシーのリソースや条件で対象のインデックスや接続元IPアドレスを絞り込むことも可能です。

FGACを利用しない場合の権限管理の粒度 doc

この方法に加えて、FGACでは次の機能が実現できます (公式ドキュメントの受け売りです):

IAMポリシーによる制御よりも柔軟なため、FGACを使いたいユースケースも少なくないのではないでしょうか。OpenSearch Serviceの運用ベストプラクティスにおいても、FGACはドメインをセキュアにする手段として明示的に推奨されています。

FGACを設定する際の課題

しかしながら、FGACを設定する上で課題があります。それはFGACの設定はCloudFormation(CFn)やCDKで公式にサポートされていないことです。このため、従来は次のような方法で設定していたかと思います:

  1. OpenSearchダッシュボードからGUIで設定する
  2. OpenSearchREST APIで設定する

1は自動化が困難なことや手順書の管理作業が生じることが難点です。2は自動化できる点で悪くないですが、VPC内にドメインがある場合はアクセスのため考えることが増えたり、またCDKで自動命名されたIAM Role名を引き回したりといった手間も考えられます。

これらの課題を解消するために、現在は次の方法でCDKからFGACを管理可能です。

CDKから管理する方法

opensearch-rest-resourcesというライブラリを使えば、CDKからFGACの設定を管理することができるようになります。

例えば、あるIAMロールに権限を与えたい場合は、下記のコードで実現可能です:

import { IVpc } from 'aws-cdk-lib/aws-ec2';
import { IRole } from 'aws-cdk-lib/aws-iam';
import { Domain } from 'aws-cdk-lib/aws-opensearchservice';
import { OpenSearchRole, OpenSearchRoleMapping } from 'opensearch-rest-resources';

declare const vpc: IVpc; // OpenSearch Domainが属するVPC (Domainがnon-VPCな場合は省略可)
declare const backendRole: IRole; // 権限を与えたいIAMロール
declare const domain: Domain; // 対象のOpenSearch Domain

// OpenSearch FGACのロールを作成
const role = new OpenSearchRole(this, 'Role', {
    vpc,
    domain,
    roleName: 'Role1',
    payload: {
        // Roleの設定: 以下の仕様に従う
        // https://opensearch.org/docs/latest/security/access-control/api/#create-role
        clusterPermissions: ['indices:data/write/bulk'],
        indexPermissions: [
            {
                indexPatterns: ['*'],
                allowedActions: ['read', 'write', 'index', 'create_index'],
            },
        ],
    }
});

// RoleMappingで上記のロールとIAMロールを紐づける
const roleMapping = new OpenSearchRoleMapping(this, 'RoleMapping', {
    vpc,
    domain,
    roleName: role.roleName,
    payload: {
        backendRoles: [backendRole.roleArn],
    },
    // RemovalPolicyも通常のCFnリソースと同様に利用できる
    removalPolicy: RemovalPolicy.RETAIN_ON_UPDATE_OR_DELETE,
});

他のCFnリソースと同様、設定を書き換えてデプロイすれば反映されますし、削除すればRemovalPolicyに沿って処理されます。またpayload プロパティには型がついているので、安全に設定できます。結構便利ではないでしょうか?

これまで構築が面倒なのでFGACを敬遠していたという方、ぜひお試しください。

現状の制約・注意事項

本コンストラクトライブラリを使う上での現時点での注意点をまとめます。大抵のユースケースにおいては問題にならないはずです。

OpenSearch Domain L2コンストラクトの利用が必要

APIを単純化するために、対象のドメインL2コンストラクトの利用を必須としています。新規にドメインを構築する方は皆大抵L2を使うだろうと思い、このようにしていますが、問題がある場合はぜひ教えて下さい。

Masterユーザーの認証方法

MasterユーザーはBasic認証 (not IAM)で、ユーザー名とパスワードがSecrets Managerに保存されている必要があります。Domain L2コンストラクトでは、以下のように設定すれば良いです。

const domain = new Domain(this, 'Domain', {
  // 他のプロパティは省略
  fineGrainedAccessControl: {
    masterUserName: 'master-user',  // これでOK
  },
});

これも巷のよくあるユースケースがどんな感じか不明なので、単純化のため一旦こうしています。例えばAuroraだと似た方法 (固定のユーザー名・パスワードの利用) は一般的だと思いますが、OpenSearchだとどうなのか、IAM認証もほしい方はIssueをください。

ドメイン側の設定は利用側の責任

FGACを使うためにはいくつかドメイン側に設定の必要があります。こちらのドキュメントが詳しいです。例えば下記が挙げられます:

  • トラフィックについてHTTPSを利用
  • Encryption of data at restの有効化
  • node-to-node encryptionの有効化
  • Domain access policyの設定

これらの設定は利用側の責任としています。このコンストラクト側では今のところバリデーションなどもしていません (これもどれくらい必要な機能なのか判断つかなかったため。)

ドメインのCDK実装例は、exampleをご覧ください。

対応リソース

本ライブラリでは、FGACに必要なリソースであるRole / RoleMapping / Userをすべて管理することができます。

将来的には、ライブラリ名が示すように、OpenSearchのそれ以外のRESTリソース (インデックスやML Connectorなど) も管理できるようにすることを目指しています。作成/更新(PUT)・削除(DELETE)のRESTエンドポイントが利用可能なリソースであれば、追加の対応は容易なはずです。もし何か必要なリソースがあれば、GitHub Issueにリクエストをください。

あるいは、基盤となる OpenSearchCustomResourceクラス も公開しているので、自分でコンストラクトを作ることもできます。その場合の実装は、他のクラスの実装を参考にしてください (基本的にはエンドポイントを指定して、リクエストのbodyをつくるだけです)。

まとめ

FGACの設定をCDKから管理する方法を紹介しました。ベストプラクティスに沿ったOpenSearch運用を実現するため、ぜひ使ってみてください。

今月のもなちゃん

上半期の換羽と抱卵が終わり、羽が艷やかになりました。