皆さま、こんにちは!y.takanashiです。
今年も1/4が過ぎ、毎年の時間の流れの速さを実感しています。
今回は以下の記事の続編として、OCI IAM ポリシーの詳細についてご紹介します。
基本編と同様に、本記事でもポリシーの仕組みを理解し、実践的な活用方法を学んでいきましょう。
目次
ポリシーの内部動作
最初にポリシーの内部動作についてご紹介します。
OCIの認証・認可の仕組み
OCI は他クラウドと同様に、 全ての操作が API のコールによって実行されるアーキテクチャになっています。
そのため各リクエストが送信される際に、認証(Authentication)と認可(Authorization) が行われ、適切な権限があるかどうかが検証されます。
OCI の IAM は、この認証・認可のプロセスを制御する重要な要素であり、 適切なポリシー設定を行うことで、不要なアクセスを防ぎ、システムの安全性を確保 する役割を果たしています。
※ 補足でOCI の「監査(Audit)」というサービスがあり、API に関する操作ログが自動的に収集・保存されます。
本記事では監査サービスの詳細な説明は割愛しますが、必要に応じて確認・活用することで、より強固なセキュリティ管理が可能となります。
詳しくは以下の公式ドキュメントをご参照ください。
動詞とパーミッションの関係
IAM ポリシーの動詞(Verb)は、 内部的には事前定義されたパーミッション※(Permission)の集合体 として定義されます。
動詞のレベルが上がるにつれて、利用可能なパーミッションが増加します。
※「パーミッション」はOCI固有の用語であり、ここではLinuxにおけるパーミッションとは異なる概念として扱ってください。
Inspect < Read < Use < Manage
リソースの リスト取得 | リソースの メタデータ取得 | リソースの操作 (作成・更新・削除は 除く) | リソースの操作 (作成・更新・削除も 含む) | 想定ユーザー | |
---|---|---|---|---|---|
Inspect | ◯ | × | × | × | 外部監査者 |
Read | ◯ | ◯ | × | × | 内部監査者 |
Use | ◯ | ◯ | ◯ | × | 日常のユーザー |
Manage | ◯ | ◯ | ◯ | ◯ | 管理者 |
各動詞には、対応する オペレーション(API 操作) に必要なパーミッションが割り当てられています。
例えば、以下の例では ListVolumes を実行するためにはVOLUME_INSPECT のパーミッションが必要になります。
IAM ポリシーでは、動詞(Verb)の代わりに パーミッションを直接指定 することも可能です。
例えば、以下のポリシーではA-Admins に属するユーザーに対し、Project-A 内のブロック・ボリュームに対する閲覧(Inspect)と更新(Update)権限を付与しています。
Allow 'A-Domain'/'A-Admins' to {VOLUME_INSPECT, VOLUME_UPDATE} in compartment Project-A
動詞とパーミッション、オペレーションの組み合わせの一覧については、以下のドキュメントをご確認ください。
条件(where)
ここでは条件句(where)句について説明します。
IAM ポリシーでは、より詳細なアクセス制御を行うため、ステートメントの後に条件(where)句をオプションとして定義できます。
条件句は1つ以上の事前定義済みの変数で構成され、リソースへのアクセスリクエスト時に条件が満たされている場合は "true" と評価され、リクエストが許可されます。
一方、条件が満たされない場合は "false" と評価され、アクセスが拒否されます。
変数
条件句を使用する場合、request ~ もしくは target ~ で指定して変数を指定することができます。
一般的な変数一覧は以下となっております。
名前 | タイプ | 説明 |
---|---|---|
request.user.id | エンティティ型(OCID) | リクエスト・ユーザーのOCID。 |
request.user.name | 文字列型 | リクエスト・ユーザーの名前。 |
request.groups.id | エンティティ型(OCID) | リクエストしているユーザーが属するグループのOCID。 |
request.permission | 文字列型 | リクエストされている基礎となる権限。 |
request.operation | 文字列型 | リクエストされているAPI操作名(ListUsersど)。 |
request.region | 文字列型 | リクエストが発行されるリージョンの3文字のキー(東京リージョンの場合は`NRT`、大阪リージョンの場合は`KIX`)。 |
request.utc-timestamp | 文字列型 | リクエストが送信されるUTC時間。 |
request.networkSource.name | 文字列型 | リクエストの発行を許可されるIPアドレスを指定するネットワーク・ソース・グループの名前。 |
target.compartment.id | エンティティ型(OCID) | プライマリ・リソースを含むコンパートメントのOCID。 |
target.compartment.name | 文字列型 | コンパートメントの名前 |
単一条件
単一の条件を指定する場合、 =(Equal)もしくは !=(Not Equal)の比較演算子を使用します。
パーミッションを使用して単一条件を使用してIAM ポリシーを定義する場合、内容は以下となります。
Allow 'A-Domain'/'A-Admins' to manage volume-family in compartment Project-A where request permission != 'VOLUME_DELETE'
(A--Admins グループに Project-A コンパートメント内のストレージを管理する権限(manage)を与えるが、「ストレージの削除(VOLUME_DELETE)」は禁止。)
上記の例から、特定の操作を禁止する場合は、!= を使用して定義することでポリシー・ステートメントの数を減らすことができ、結果的に管理の工数を削減できます。
複数条件
複数の変数を指定する場合、all もしくは any を使用します。
all の場合、AND 条件が適用されて全ての変数に一致した場合、リクエストは許可されます。
Allow group 'A-Domain'/'A-Admins' to manage instance-family in compartment Project-A
where all { request.networkSource.name = 'Prod', request permission != 'INSTANCE_DELETE' }
(A-Admins グループに Project-A コンパートメント内のインスタンスを管理する権限(manage)を与えるが、「コンピュート・インスタンスの削除(INSTANCE_DELETE)」は禁止。
Prod のネットワーク・ソース※内のCIDR からのアクセスのみ許可)
※ネットワーク・ソースは「3.3 特定のIPアドレスから許可/拒否する場合」で解説します。
any の場合、OR 条件が適用されていずれかの変数に一致した場合、リクエストは許可されます。
Allow group 'A-Domain'/'A-Admins' to use instance-family in compartment Project-A
where any { request.region = 'NRT', request.region = 'KIX' }
(A-Admins グループに Project-A コンパートメント内にあるのインスタンスを管理する権限(manage)を与えるが、東京リージョンもしくは大阪リージョンのみに適用)
部分一致の条件を定義する場合、ワイルドカード(「*」)を使用できます。
この場合、文字列の前後にスラッシュ(/)を記述します。
- /HR*/(「HR」で始まる文字列と一致します)
- /*HR/(「HR」で終わる文字列と一致します)
- /*HR*/(「HR」を含む文字列と一致します)
部分一致のポリシー例は以下となります。
Allow group GroupAdmins to manage groups in tenancy where all {target.group.name=/A-*/,target.group.name!='A-Admins'}
Allow group GroupAdmins to inspect groups in tenancy
(次のポリシーにより、GroupAdminsは、A-Adminsグループ自体を除く、名前が「A-」で始まるグループを作成、更新または削除可能)
注意点
最後に、変数を定義する際の注意点として、リソース名は小文字大文字が区別されない点(Ignore Case)に注意が必要です。
例えば、オブジェクト・ストレージで「BucketA」と「bucketA」という名前のバケットを同じコンパートメントに作成した場合、「BucketA」を指定した条件を定義しても、小文字・大文字が区別されないため、「bucketA」にも条件が適用されてしまいます。
そのため、リソース名はテナンシ内で一意となるように設定することが推奨されます。
ポリシー別ユースケース
ここでは以下のケースが発生した場合のポリシー別ユースケースについてご紹介します。
- 特定のIPアドレスから許可/拒否する場合
- タグに基づいて許可/拒否する場合
- 時間枠に応じて許可/拒否する場合
特定のIPアドレスから許可/拒否する場合
特定のIPアドレスから許可/拒否する場合、ネットワーク・ソースを使用して制御することが可能です。
ネットワーク・ソースは定義されたIP アドレスのセットのことで、パブリックIP アドレスまたはテナンシ内のVCN のCIDR のいずれかを指定可能です。
ここではOCI コンソール画面からネットワーク・ソースを作成する手順についてご紹介します。
左上のナビゲーション・メニューから「アイデンティティとセキュリティ」→アイデンティティ内の「ネットワーク・ソース」をそれぞれ選択します。
ネットワーク・ソースはテナンシレベルで動作するサービスで、基本的にどこのコンパートメントで作成してもテナンシ内で一意となります。
「ネットワーク・ソースの作成」を選択して、作成を行います。
以下内容をそれぞれ入力、「作成」を選択します。
- 名前:任意(ここでは「TestNS」)
※ 使用可能な文字は、文字と数字(例: a-z、A-Z、0-9)、アンダースコア(_)、ピリオド(.)およびハイフン(-)です。 - 説明:任意(ここでは「テスト用ネットワーク・ソース」)
※ 日本語可です。 - ネットワーク:(ここではVCN CIDRを指定)
- ※ 仮想クラウド・ネットワーク(VCN)もしくはパブリック・ネットワーク(パブリックIP アドレス)を指定可能です。
仮想クラウド・ネットワークでCIDRを0.0.0.0/0に指定した場合、VCN内の全てのIP アドレスの許可を行います。
ネットワーク・ソースが作成されます。
ネットワーク・ソースを使用してアクセス制御を実施する場合、条件句で以下のように "request.networksource.name" でソース名を指定します。
Allow group 'A-Domain'/'A-Admins' to manage all-resources in compartment Project-A
where request.networkSource.name = 'TestNS'
タグに基づいて許可/拒否する場合
条件およびタグ変数を使用して、リソースに適用されたタグに基づくアクセス制御を定義できます。
ポリシーは、以下の要素に存在するタグを基準にアクセスを制御できます。
- リクエスト元: ポリシー内のグループまたは動的グループ
- リクエストの対象: リソースまたはコンパートメント
例えば、プロジェクトごとにグループを作成し、すべてのグループに EmployeeGroup.Role='Admin'
のタグを付与しているとします。
この状態で、3つのプロジェクトのメンバーが共有する テスト・コンパートメント を設定し、すべての管理グループに管理アクセス権を付与する場合、以下のようなポリシーを記述できます。
allow any-user to manage all-resources in compartment Test where request.principal.group.tag.EmployeeGroup.Role='Admin'
このポリシーにより、タグ EmployeeGroup.Role='Admin'
が付与されたすべての管理グループが、テスト・コンパートメントへのアクセス権を持つようになります。
また、将来新たに EmployeeGroup.Role='Admin'
のタグを付与されたグループも、ポリシーを更新することなく自動的にアクセスが許可されます。
このようにタグを活用することで、コンパートメントやグループを超えた柔軟なアクセス管理が可能になります。
詳細は以下ドキュメントをご覧ください。
OCI 公式ドキュメント - 「タグを使用したアクセスの管理」
時間枠に応じて許可/拒否する場合
ポリシーで時間ベースの変数を使用すると、アクセス権を特定の時間枠に制限できます。
この機能により、リソースに対するアクションを特定の時間帯や期間に限定可能です。
活用例
指定した日付までアクセスを許可するポリシーを作成
→例:契約社員の契約終了後にアクセスを自動で無効化
営業時間内(例:月~金 9:00~17:00)のみアクセスを許可
→例:業務時間外の不正な変更リスクを軽減
時間ベースの変数一覧
変数 | サポートされる演算子 | 説明 | ユースケース |
---|---|---|---|
request.utc-timestamp | before, after | 指定日時の前後でアクセスを制限 | 2025年3月31日までのアクセスを許可 |
request.utc-timestamp.month-of-year | =, !=, in | 特定の月にアクセスを制限 | 6月~8月のみアクセス可能 |
request.utc-timestamp.day-of-month | =, !=, in | 特定の日にアクセスを制限 | 毎月1日のみアクセス許可 |
request.utc-timestamp.day-of-week | =, !=, in | 特定の曜日にアクセスを制限 | 土日はアクセス不可 |
request.utc-timestamp.time-of-day | between | 指定した時間帯のみアクセスを許可 | 9:00~17:00のみアクセス可 |
例として、グループContractors が2025年3月31日までインスタンス・ファミリーにアクセスできるようにするポリシーは以下のように定義できます。
Allow group Contractors to manage instance-family in tenancy where request.utc-timestamp before '2025-03-31T00:00Z'
注意点として、指定する時間は協定世界時(UTC)によって評価されるため、ローカル時間との差を考慮して設定してください。
詳細は以下ドキュメントをご覧ください。
OCI 公式ドキュメント - 「時間枠に基づいたリソースへのアクセスの制限」
最後に
本記事では、IAM ポリシーの内部的な仕組みや、動詞やパーミッションの関係、条件句の活用方法、そしてユースケースごとの実装例まで幅広くご紹介しました。
IAM ポリシーは単なるアクセス制御の手段ではなく、「いつ・どこから・誰が・何に対して・どのような操作をできるのか」をきめ細かく定義する強力なセキュリティ・サービスです。
組織の規模が大きくなるほど、IAM ポリシーの設計は複雑になりがちですが、ポリシーの可読性とメンテナンス性を意識した設計を心がけることで、長期的な運用負荷の軽減につながります。
OCIをより安全かつ効率的に活用するためにも、本記事で紹介した知見をぜひポリシー設計・運用の参考にしていただければ幸いです。
以上となります。
この記事を通じて読者の皆様の問題解決の一助となれば幸いです。
最後まで読んで頂き、ありがとうございましたm( )m