ポリシーの検証

このトピックでは、Identity and Access Management(IAM)許可ポリシーの検証(lint チェック)を行う方法について説明します。

始める前に

必要なロール

リソースの許可ポリシーで lint チェックを行うには、リソースを取得する権限と、リソースに対する許可ポリシーを取得して設定する権限が必要です。これらの権限の形式は次のとおりです。ここで SERVICE はリソースを所有するサービスの名前、RESOURCE_TYPE はアクセスを管理するリソースタイプの名前です。

  • SERVICE.RESOURCE_TYPE.get
  • SERVICE.RESOURCE_TYPE.getIamPolicy
  • SERVICE.RESOURCE_TYPE.setIamPolicy

たとえば、プロジェクトの許可ポリシーの lint チェックを行うには、次の権限が必要です。

  • resourcemanager.projects.get
  • resourcemanager.projects.getIamPolicy
  • resourcemanager.projects.setIamPolicy

必要な権限を取得するには、管理者に依頼して、それらの権限を含む事前定義ロールまたはカスタムロールを取得してください。たとえば、管理者からセキュリティ管理者ロール(roles/iam.securityAdmin)が付与された場合、そのロールにはほぼすべての Google Cloud リソースを取得して許可ポリシーを管理する権限が含まれています。

許可ポリシーの lint チェックについて

許可ポリシーのコンテキストでは、lint チェックは新規または既存の許可ポリシーを調べて特定の問題をチェックする方法です。これらの問題には、次のものが含まれている可能性があります。

  • 提案
  • 警告
  • 許可ポリシーのインテントの改善に役立つ情報(構文やセマンティクスの改善など)
  • setIamPolicy 操作の失敗を招く構文エラーまたはセマンティック エラー

許可ポリシーの更新でエラーが発生した場合、許可ポリシーの lint チェックを行うと、エラーの原因を特定できます。また、リンターを使用して、条件付きロール バインディングが意図したとおり機能しているかを確認することもできます。

条件の lint チェック

条件式は複雑になることがあります。特に、アクセスを適切に管理するために複数の句と論理演算子を必要とする場合は複雑になります。条件式に無効なロジックが含まれている場合や、構文が条件式の制限に違反している場合、許可ポリシーに条件を追加することはできません。

また、条件式で正しい構文を使用していても、セマンティック エラーが発生することがあります。この場合、許可ポリシーとロール バインディングが期待どおりに機能しません。一般的なセマンティック エラーには次のものがあります。

  • 推奨されない関数の使用
  • レガシー リソースタイプまたはレガシー サービス名の使用
  • 適用できない条件(無効な期間など)

条件の lint チェックを行うと、リンターによって条件式が検査され、構文エラーが報告されます。また、予期しない結果を引き起こす可能性のあるセマンティック エラーも報告されます。

新しい条件付きロール バインディングを設定する前に、最初に式を lint チェックすることをおすすめします。このセクションでは、Google Cloud コンソール、Google Cloud CLI、または REST API を使用して条件式を lint チェックする方法を説明します。

条件式を lint チェックするには:

コンソール

  1. Google Cloud コンソールの [IAM] ページに移動します。

    [IAM] に移動

  2. [プロジェクトを選択] をクリックし、プロジェクトを選択して [開く] をクリックします。

  3. プリンシパルのリストから、目的のプリンシパルを見つけて、[編集] ボタンをクリックします。

  4. [権限の編集] パネルで、lint チェックするロールを探します。次に、[IAM の条件(省略可)] で、条件の名前をクリックします。

  5. [条件エディタ] で、条件式を手動で追加または編集します。

  6. CEL 構文を検証するには、[リンターを実行] をクリックします。

    構文にエラーがある場合、誤った行の横に エラー アイコンが表示されます。エラーの詳細を表示するには、アイコンの上にポインタを置きます。

    条件に正しい構文を使用していても、潜在的な問題が見つかると、その問題の横に 警告アイコンが表示されます。警告の詳細を表示するには、アイコンの上にポインタを置きます。

  7. 条件式に必要な変更を加えます。[リンターを実行] をクリックすると、式の編集中にリンターがバックグラウンドで自動的に実行されます。

    条件式を保存する前にすべてのエラーを修正する必要があります。警告もすべて修正することを強くおすすめします。

  8. エラーや警告がない場合は、[保存] をクリックして条件を適用します。

  9. [条件の編集] パネルを閉じたら、[権限の編集] パネルでもう一度 [保存] をクリックし、許可ポリシーを更新します。

gcloud

gcloud alpha iam policies lint-condition コマンドを実行して、指定された条件式を lint チェックします。このコマンドを実行するには、条件を含むテキスト ファイルを作成するか、条件のタイトル、説明、式にフラグを指定します。

以下の例では、次の条件を含むテキスト ファイルを使用します。

condition.json

{
  "title": "1_less_than_2",
  "description": "",
  "expression": "1 <"
}

次のコマンドを実行します。

gcloud alpha iam policies lint-condition --condition-from-file="condition.json"

コマンドの出力には次の内容が含まれます。

lintResults:
- debugMessage: |-
    ERROR: Parse expression:1:3: mismatched input '<EOF>' expecting {'[', '{', '(', '.', '-', '!', 'true', 'false', 'null', NUM_FLOAT, NUM_INT, NUM_UINT, STRING, BYTES, IDENTIFIER}
      | 1 >
      | ...^
  fieldName: condition.expression
  level: CONDITION
  locationOffset: 3
  severity: ERROR
  validationUnitName: LintValidationUnits/ConditionCompileCheck
...

それぞれの lint チェックの結果には、debugMessage が含まれ、これは、条件式の問題の特定に役立ちます。条件でコンパイルが失敗した場合は、次の debugMessage テキストでさまざまな validationUnitName の種類を確認できます。

The validation unit is skipped due to absence of a required object: CheckedExpr

式がコンパイルされるように変更を行い、もう一度条件を lint チェックを実行します。

REST

iamPolicies.lintPolicy メソッドは、許可ポリシーの条件式に lint チェックまたは検証を行います。

リクエストのデータを使用する前に、次のように置き換えます。

HTTP メソッドと URL:

POST https://iam.googleapis.com/v1/iamPolicies:lintPolicy

リクエストの本文(JSON):

{
  "condition": {
    condition
  }
}

リクエストを送信するには、次のいずれかのオプションを展開します。

レスポンスの本文には、次のように 1 つ以上の LintResult オブジェクトが含まれます。

{
  "lint_results": {
    "level": "CONDITION",
    "validation_unit_name": "LintValidationUnits/ConditionCompileCheck",
    "severity": "ERROR",
    "field_name": "condition.expression",
    "location_offset": "2",
    "debug_message": "ERROR: Parse expression:1:2: mismatched input \'<EOF>\' expecting {\'[\', \'{\', \'(\', \'.\', \'-\', \'!\', \'true\', \'false\', \'null\', NUM_FLOAT, NUM_INT, NUM_UINT, STRING, BYTES, IDENTIFIER}\n  | 1<\n  | ..^"
  },
  "lint_results": {
    "level": "CONDITION",
    "validation_unit_name": "LintValidationUnits/ConditionComplexityCheck",
    "severity": "NOTICE",
    "field_name": "condition.expression",
    "debug_message": "The validation unit is skipped due to absence of a required object: CheckedExpr"
  }
}

それぞれの lint チェックの結果には、debug_message が含まれ、これは、条件式の問題の特定に役立ちます。条件でコンパイルが失敗した場合は、次の debugMessage テキストでさまざまな validation_unit_name の種類を確認できます。

The validation unit is skipped due to absence of a required object: CheckedExpr

式がコンパイルされるように変更を行い、もう一度条件を lint チェックを実行します。

サポートされている検証単位

前述したとおり、検証単位とは、構文の問題についての式を評価する個別の lint タイプです。下記の表では、サポートしている検証単位をまとめています。それぞれの単位には、対象の lint チェックのレベル、lint チェックの結果の重要度、簡単な説明を記載してあります。

検証単位 lint チェックのレベル 重大度 説明
ConditionCompileCheck CONDITION ERROR 条件式に、無効な CEL 構文の結果としてコンパイル エラーが含まれています。
ConditionComplexityCheck CONDITION ERROR 条件式に、最大の 12 個を超える論理演算子が含まれています。
DateTimeCheck CONDITION WARNING

条件式には、次のいずれかの問題で常に true または false に評価されるタイムスタンプ比較を指定します。

DateTimeRangeCheck CONDITION WARNING 対象の高度なタイムスタンプ関数と比較式の値が範囲外です。高度なタイムスタンプ関数については、有効な値をご覧ください。
DrgGetAttributeDefaultValueCheck CONDITION ERROR 条件式は api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', V) を呼び出します。ここで、V は空のリスト([])以外のあらゆる値です。この API 属性の場合、V は常に空のリストである必要があります。
EffectiveTimeRangeCheck CONDITION WARNING タイムスタンプ関数と比較を使用する場合、式の結果は空の有効期間となり、実質的に false になります。また、時間範囲は全範囲を対象としているため、実質的に true です。
HasOnlyListConstCheck CONDITION ERROR 条件式は hasOnly(List<T>) を呼び出します。ここで、型 T は文字列や整数などの定数型ではありません。hasOnly() 関数で指定できるのは定数のリストのみです。
HasOnlyListLengthCheck CONDITION ERROR 条件式は hasOnly(List<T>) を呼び出し、List<T> には最大 10 個を超える要素が含まれます。
ResourceServiceLiteralCheck CONDITION WARNING 指定された resource.service 値はサポートされていません。このような文字列リテラルを等価比較に使用した式は実質的には false です。サポートされている値を使用してください。
ResourceTypeLiteralCheck CONDITION WARNING 指定された resource.type 値はサポートされていません。このような文字列リテラルを等価比較に使用した式は実質的には false です。サポートされている値を使用してください。
RestrictedAttributesCheck CONDITION WARNING 式で、制限されている属性やサポートされていない属性が使用されています。条件式を設定できないことがあります。属性の一覧をご覧ください。

lint チェックの例

このセクションでは、各検証ユニットで問題が報告される条件の例を示します。それぞれの例で、Google Cloud CLI を使用した lint チェックを示します。

検証エラーがない場合

条件の例:

{
  "title": "1_less_than_2",
  "description": "",
  "expression": "1 < 2"
}

次のコマンドを実行します。

gcloud alpha iam policies lint-condition --condition-from-file="condition.json"

lint チェックの結果:

{}

ConditionCompileCheck

条件の例:

{
  "title": "Condition not compiling",
  "description": "",
  "expression": "true=false"
}

次のコマンドを実行します。

gcloud alpha iam policies lint-condition --condition-from-file="condition.json"

lint チェックの結果:

lintResults:
- debugMessage: |-
    ERROR: Parse expression:1:4: token recognition error at: '=f'
      | true=false
      | ....^
  fieldName: condition.expression
  level: CONDITION
  locationOffset: 4
  severity: ERROR
  validationUnitName: LintValidationUnits/ConditionCompileCheck

ConditionComplexityCheck

条件の例:

{
  "title": "Condition not compiling",
  "description": "",
  "expression":
    "1<2 || 2<3 || 3<4 || 4<5 || 5<6 || 6<7 || 7<8 || 8<9 || 9<10 || 10<11 || 11<12 || 12<13 || 13<14 || 14<15"
}

次のコマンドを実行します。

gcloud alpha iam policies lint-condition --condition-from-file="condition.json"

lint チェックの結果:

lintResults:
- debugMessage: Logical operators count must not be more than 12
  fieldName: condition.expression
  level: CONDITION
  severity: ERROR
  validationUnitName: LintValidationUnits/ConditionComplexityCheck

DateTimeCheck

条件の例:

{
  "title": "Condition not compiling",
  "description": "",
  "expression": "request.time < timestamp('2000-01-01T00:00:00Z')"
}

次のコマンドを実行します。

gcloud alpha iam policies lint-condition --condition-from-file="condition.json"

lint チェックの結果:

lintResults:
- debugMessage: Ineffective date time value 2000-01-01T00:00:00+00:00 parsed
    from "2000-01-01T00:00:00Z"; condition is effectively False. Time expired
    already.
  fieldName: condition.expression
  level: CONDITION
  locationOffset: 25
  severity: WARNING
  validationUnitName: LintValidationUnits/DateTimeCheck

DateTimeRangeCheck

条件の例:

{
  "title": "Time function out of range",
  "description": "",
  "expression": "request.time.getMonth() > 13"
}

次のコマンドを実行します。

gcloud alpha iam policies lint-condition --condition-from-file="condition.json"

lint チェックの結果:

lintResults:
- debugMessage: The value being compared to the specified timestamp function
    (getMonth) must be in range [0, 11].
  fieldName: condition.expression
  level: CONDITION
  locationOffset: 26
  severity: WARNING
  validationUnitName: LintValidationUnits/DateTimeRangeCheck

DrgGetAttributeDefaultValueCheck

条件の例:

{
  "title": "DRG condition takes non empty list as default value",
  "description": "",
  "expression":
    "api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', ['roles/viewer']).hasOnly(['roles/editor'])"
}

次のコマンドを実行します。

gcloud alpha iam policies lint-condition --condition-from-file="condition.json"

lint チェックの結果:

lintResults:
- debugMessage: api.getAttribute call on
    'iam.googleapis.com/modifiedGrantsByRole' can only
    accept empty list ('[]') as default value.
  fieldName: condition.expression
  level: CONDITION
  locationOffset: 60
  severity: ERROR
  validationUnitName: LintValidationUnits/DrgGetAttributeDefaultValueCheck

EffectiveTimeRangeCheck

条件の例:

{
  "title": "Empty time range",
  "description": "",
  "expression": "request.time.getMonth() > 5 && request.time.getMonth() < 4"
}

次のコマンドを実行します。

gcloud alpha iam policies lint-condition --condition-from-file="condition.json"

lint チェックの結果:

lintResults:
- debugMessage: The aggregate of time functions [getMonth] results in empty ranges.
  fieldName: condition.expression
  level: CONDITION
  severity: WARNING
  validationUnitName: LintValidationUnits/EffectiveTimeRangeCheck

HasOnlyListConstCheck

条件の例:

{
  "title": "hasOnly contains more than constant value",
  "description": "",
  "expression":
    "api.getAttribute('somekey', []).hasOnly(['somevalue', resource.name])"
}

次のコマンドを実行します。

gcloud alpha iam policies lint-condition --condition-from-file="condition.json"

lint チェックの結果:

lintResults:
- debugMessage: hasOnly() expects an argument of type list containing only const
      values, but a non-const expression was found in the list.
  fieldName: condition.expression
  level: CONDITION
  locationOffset: 59
  severity: ERROR
  validationUnitName: LintValidationUnits/HasOnlyListConstCheck

HasOnlyListLengthCheck

条件の例:

{
  "title": "hasOnly contains more than 10 elements",
  "description": "",
  "expression":
    "api.getAttribute('somekey', []).hasOnly([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])"
}

次のコマンドを実行します。

gcloud alpha iam policies lint-condition --condition-from-file="condition.json"

lint チェックの結果:

lintResults:
- debugMessage: The list argument to hasOnly() cannot have more than 10 elements
  fieldName: condition.expression
  level: CONDITION
  locationOffset: 39
  severity: ERROR
  validationUnitName: LintValidationUnits/HasOnlyListLengthCheck

ResourceServiceLiteralCheck

条件の例:

{
  "title": "Condition with unsupported resource service string",
  "description": "",
  "expression": "resource.service == 'resourcemanager'"
}

次のコマンドを実行します。

gcloud alpha iam policies lint-condition --condition-from-file="condition.json"

lint チェックの結果:

lintResults:
- debugMessage: 'resource.service : resourcemanager is not supported. Using this
    value in condition may lead to unintended consequences. Check user guide at
    https://cloud.google.com/iam/docs/conditions-resource-attributes#resource_service_values
    for supported values for resource.service.'
  fieldName: condition.expression
  level: CONDITION
  locationOffset: 20
  severity: WARNING
  validationUnitName: LintValidationUnits/ResourceServiceLiteralCheck

ResourceTypeLiteralCheck

条件の例:

{
  "title": "Condition with legacy resource type",
  "description": "",
  "expression": "resource.type == 'resourcemanager.projects'"
}

次のコマンドを実行します。

gcloud alpha iam policies lint-condition --condition-from-file="condition.json"

lint チェックの結果:

lintResults:
- debugMessage: 'resource.type : resourcemanager.projects is not supported.
    Using this value in condition may lead to unintended consequences. Check
    user guide at https://cloud.google.com/iam/docs/conditions-resource-attributes#resource_type_values
    for supported values for resource.type.'
  fieldName: condition.expression
  level: CONDITION
  locationOffset: 17
  severity: WARNING
  validationUnitName: LintValidationUnits/ResourceTypeLiteralCheck

RestrictedAttributesCheck

条件の例:

{
  "title": "Condition with restricted attribute",
  "description": "",
  "expression": "'accessPolicies/123/accesslevels/TRUSTED' in request.auth.access_levels"
}

次のコマンドを実行します。

gcloud alpha iam policies lint-condition --condition-from-file="condition.json"

lint チェックの結果:

lintResults:
- debugMessage: Condition attribute `request.auth.access_levels` is restricted
    or unsupported. Please check https://cloud.google.com/iam/docs/conditions-overview
    for the full list of supported attributes
  fieldName: condition.expression
  level: CONDITION
  locationOffset: 57
  severity: WARNING
  validationUnitName: LintValidationUnits/RestrictedAttributesCheck