Linting policies

Alpha

This feature is subject to the "Pre-GA Offerings Terms" in the General Service Terms section of theService Specific Terms. Pre-GA features are available "as is" and might have limited support. For more information, see thelaunch stage descriptions.

This topic describes how tolint, or validate, your Identity and Access Management (IAM)allow policies.

Before you begin

  • Enable the IAM API.

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains theserviceusage.services.enable permission.Learn how to grant roles.

    Enable the API

  • Read theIAM Conditions overview tounderstand the basics of IAM Conditions.

Note: This alpha release oflintPolicy only supportslinting operations on thegoogle.iam.v1.Binding.condition field.

Required roles

To lint a resource's allow policy, you need permissions to get the resource, andto get and set the allow policy for the resource. These permissions have thefollowing form, whereSERVICE is the name of the servicethat owns the resource andRESOURCE_TYPE is the name ofthe resource type that you want to manage access to:

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

For example, to lint a project's allow policy, you need the followingpermissions:

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

To gain the required permissions, ask your administrator to grant you apredefined or custom role that includes the permissions. For example, youradministrator could grant you the Security Admin role(roles/iam.securityAdmin), which includes permissions to get almost allGoogle Cloud resources and manage their allow policies.

Understanding linting for allow policies

In the context of allow policies, linting is a method of examining a new orexisting allow policy and checking it for specific issues. These issues includethe following range of possibilities:

  • Suggestions
  • Warnings
  • Information that can help improve the intent of the allow policy, such asbetter syntax and semantics
  • Syntax or semantic errors that causesetIamPolicy operations to fail

If you try to update an allow policy, and you get an error, linting the allowpolicy can help you find the cause of the error. You can also use the linter tohelp ensure that a conditional role binding has the intended effect.

Linting a condition

Condition expressions can be complex, especially in scenarios that requiremultiple clauses and logic operators to appropriately manage access. If acondition expression contains invalid logic, or if the syntax violates therestrictions of a condition expression, you cannot add the condition to an allowpolicy.

Also, even if a condition expression uses the correct syntax, it might containsemantic errors, which can prevent your allow policies and role bindings fromworking as expected. Common semantic errors include the following:

  • Use of unrecommended functions
  • Use of legacy resource types or legacy service names
  • Ineffective conditions, such as an inapplicable date or time range

When you lint a condition, the linter inspects the condition expression andreports any syntax errors. It also reports possible semantic errors that couldcause unexpected results.

Before attempting to set a new conditional role binding, you are encouraged tolint the expression first. This section shows you how to lint a conditionexpression using the Google Cloud console, Google Cloud CLI, or theREST API.

To lint a condition expression:

Console

  1. In the Google Cloud console, go to theIAM page.

    Go to IAM

  2. ClickSelect a project, choose a project, and clickOpen.

  3. From the list of principals, locate the desired principal and click theEdit button.

  4. From theEdit permissions panel, locate the desired role that you wantto lint. Then underIAM condition (optional), click the name of thecondition.

  5. In theCondition editor, manually add or edit a condition expression.

  6. To validate the CEL syntax, clickRun Linter.

    If the syntax contains errors, anError icon appears next to theincorrect line. To see details about each error, hold the pointer over theicon.

    If the condition uses the correct syntax, but the linter finds a possibleissue, aWarning iconappears next to the line with the issue. To see details about each warning,hold the pointer over the icon.

  7. Make any necessary changes to the condition expression. After you clickRunLinter, the linter runs automatically in the background while you edit theexpression.

    You must correct all errors before you save the condition expression. Westrongly encourage you to fix all warnings as well.

  8. When there are no errors or warnings, clickSave to apply the condition.

  9. Once theEdit condition panel is closed, clickSave again fromtheEdit permissions panel to update your allow policy.

gcloud

Execute thegcloud alpha iam policies lint-conditioncommand to lint a given condition expression. To execute this command, youcan either create a text file that contains the condition, or specifyflags for the condition's title, description, and expression.

The following example uses a text file that contains the following condition:

condition.json

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

Run command:

gcloudalphaiampolicieslint-condition--condition-from-file="condition.json"

The output from the command contains the following:

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.expressionlevel:CONDITIONlocationOffset:3severity:ERRORvalidationUnitName:LintValidationUnits/ConditionCompileCheck...

Each of the lint results contain adebugMessage that can be used to helplocate the problem with the condition expression. If the condition failed tocompile, you may see many differentvalidationUnitName types with thefollowingdebugMessage text:

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

Make changes so that the expression compiles, then lint the condition again.

REST

TheiamPolicies.lintPolicy method lints, or validates, a condition expression in an allow policy.

Before using any of the request data, make the following replacements:

  • condition: AnExpr object representing the condition to lint. For example:

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

    To learn about the format of anExpr object, see theExpr schema reference.

HTTP method and URL:

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

Request JSON body:

{  "condition": {condition  }}

To send your request, expand one of these options:

curl (Linux, macOS, or Cloud Shell)

Note: The following command assumes that you have logged in to thegcloud CLI with your user account by runninggcloud init orgcloud auth login , or by usingCloud Shell, which automatically logs you into thegcloud CLI . You can check the currently active account by runninggcloud auth list.

Save the request body in a file namedrequest.json, and execute the following command:

curl -X POST \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json; charset=utf-8" \
-d @request.json \
"https://iam.googleapis.com/v1/iamPolicies:lintPolicy"

PowerShell (Windows)

Note: The following command assumes that you have logged in to thegcloud CLI with your user account by runninggcloud init orgcloud auth login . You can check the currently active account by runninggcloud auth list.

Save the request body in a file namedrequest.json, and execute the following command:

$cred = gcloud auth print-access-token
$headers = @{ "Authorization" = "Bearer $cred" }

Invoke-WebRequest `
-Method POST `
-Headers $headers `
-ContentType: "application/json; charset=utf-8" `
-InFile request.json `
-Uri "https://iam.googleapis.com/v1/iamPolicies:lintPolicy" | Select-Object -Expand Content

APIs Explorer (browser)

Copy the request body and open themethod reference page. The APIs Explorer panel opens on the right side of the page. You can interact with this tool to send requests. Paste the request body in this tool, complete any other required fields, and clickExecute.

The response body contains one or moreLintResult objects, such as the following:

{  "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"  }}

Each of the lint results contain adebug_message that can be used to helplocate the problem with the condition expression. If the condition failed tocompile, you may see many differentvalidation_unit_name types withthe followingdebugMessage text:

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

Make changes so that the expression compiles, then lint the condition again.

Supported validation units

As described previously, a validation unit is an individual lint type thatevaluates the expression for syntactic issues. The table below summarizessupported validation units, each with intended linting level, linting resultseverity, and a brief description.

Validation unitLint levelSeverityDescription
ConditionCompileCheckCONDITIONERROR The condition expression contains a compilation error as a result of invalid CEL syntax.
ConditionComplexityCheckCONDITIONERROR The condition expression contains more than the maximum of 12 logic operators.
DateTimeCheckCONDITIONWARNING

The condition expression specifies a timestamp comparison that always evaluates to either true or false, due to one of these issues:

DateTimeRangeCheckCONDITIONWARNING Value out of range for the intended advanced timestamp function and the comparison expression. See thevalid values for advanced timestamp functions.
DrgGetAttributeDefaultValueCheckCONDITIONERROR The condition expression callsapi.getAttribute('iam.googleapis.com/modifiedGrantsByRole',V), whereV is any value other than an empty list,[]. For this API attribute,V must always be an empty list.
EffectiveTimeRangeCheckCONDITIONWARNING In a more complex usage of timestamp functions and comparison, the expression results in an empty effective time range, and is therefore effectively false. Alternatively, the time range covers a full range, and is therefore effectively true.
HasOnlyListConstCheckCONDITIONERROR The condition expression callshasOnly(List<T>), where the typeT is not a constant type, such as a string or integer. ThehasOnly() function accepts only a list of constants.
HasOnlyListLengthCheckCONDITIONERROR The condition expression callshasOnly(List<T>), andList<T> contains more than the maximum of 10 elements.
ResourceServiceLiteralCheckCONDITIONWARNING The specifiedresource.service value is not supported. The expression using such string literal for equality comparison is effectively false. Use asupported value.
ResourceTypeLiteralCheckCONDITIONWARNING The specifiedresource.type value is not supported. The expression using such string literal for equality comparison is effectively false. Use asupported value.
RestrictedAttributesCheckCONDITIONWARNING The expression uses an attribute that is restricted or not supported. Setting the condition expression might not succeed. See thelist of attributes.

Linting examples

This section shows examples of conditions that cause each validation unit toreport issues. Each example demonstrates linting by using the Google Cloud CLI.

No validation issues

Example condition:

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

Run command:

gcloudalphaiampolicieslint-condition--condition-from-file="condition.json"

Lint result:

{}

ConditionCompileCheck

Example condition:

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

Run command:

gcloudalphaiampolicieslint-condition--condition-from-file="condition.json"

Lint result:

lintResults:-debugMessage:|-ERROR: Parse expression:1:4: token recognition error at: '=f'| true=false| ....^fieldName:condition.expressionlevel:CONDITIONlocationOffset:4severity:ERRORvalidationUnitName:LintValidationUnits/ConditionCompileCheck

ConditionComplexityCheck

Example condition:

{"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"}

Run command:

gcloudalphaiampolicieslint-condition--condition-from-file="condition.json"

Lint result:

lintResults:-debugMessage:Logical operators count must not be more than 12fieldName:condition.expressionlevel:CONDITIONseverity:ERRORvalidationUnitName:LintValidationUnits/ConditionComplexityCheck

DateTimeCheck

Example condition:

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

Run command:

gcloudalphaiampolicieslint-condition--condition-from-file="condition.json"

Lint result:

lintResults:-debugMessage:Ineffective date time value 2000-01-01T00:00:00+00:00 parsedfrom "2000-01-01T00:00:00Z"; condition is effectively False. Time expiredalready.fieldName:condition.expressionlevel:CONDITIONlocationOffset:25severity:WARNINGvalidationUnitName:LintValidationUnits/DateTimeCheck

DateTimeRangeCheck

Example condition:

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

Run command:

gcloudalphaiampolicieslint-condition--condition-from-file="condition.json"

Lint result:

lintResults:-debugMessage:The value being compared to the specified timestamp function(getMonth) must be in range [0, 11].fieldName:condition.expressionlevel:CONDITIONlocationOffset:26severity:WARNINGvalidationUnitName:LintValidationUnits/DateTimeRangeCheck

DrgGetAttributeDefaultValueCheck

Example condition:

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

Run command:

gcloudalphaiampolicieslint-condition--condition-from-file="condition.json"

Lint result:

lintResults:-debugMessage:api.getAttribute call on'iam.googleapis.com/modifiedGrantsByRole' can onlyaccept empty list ('[]') as default value.fieldName:condition.expressionlevel:CONDITIONlocationOffset:60severity:ERRORvalidationUnitName:LintValidationUnits/DrgGetAttributeDefaultValueCheck

EffectiveTimeRangeCheck

Example condition:

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

Run command:

gcloudalphaiampolicieslint-condition--condition-from-file="condition.json"

Lint result:

lintResults:-debugMessage:The aggregate of time functions [getMonth] results in empty ranges.fieldName:condition.expressionlevel:CONDITIONseverity:WARNINGvalidationUnitName:LintValidationUnits/EffectiveTimeRangeCheck

HasOnlyListConstCheck

Example condition:

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

Run command:

gcloudalphaiampolicieslint-condition--condition-from-file="condition.json"

Lint result:

lintResults:-debugMessage:hasOnly() expects an argument of type list containing only constvalues, but a non-const expression was found in the list.fieldName:condition.expressionlevel:CONDITIONlocationOffset:59severity:ERRORvalidationUnitName:LintValidationUnits/HasOnlyListConstCheck

HasOnlyListLengthCheck

Example condition:

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

Run command:

gcloudalphaiampolicieslint-condition--condition-from-file="condition.json"

Lint result:

lintResults:-debugMessage:The list argument to hasOnly() cannot have more than 10 elementsfieldName:condition.expressionlevel:CONDITIONlocationOffset:39severity:ERRORvalidationUnitName:LintValidationUnits/HasOnlyListLengthCheck

ResourceServiceLiteralCheck

Example condition:

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

Run command:

gcloudalphaiampolicieslint-condition--condition-from-file="condition.json"

Lint result:

lintResults:-debugMessage:'resource.service:resourcemanagerisnotsupported.Usingthisvalueinconditionmayleadtounintendedconsequences.Checkuserguideathttps://cloud.google.com/iam/docs/conditions-resource-attributes#resource_service_valuesforsupportedvaluesforresource.service.'fieldName:condition.expressionlevel:CONDITIONlocationOffset:20severity:WARNINGvalidationUnitName:LintValidationUnits/ResourceServiceLiteralCheck

ResourceTypeLiteralCheck

Example condition:

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

Run command:

gcloudalphaiampolicieslint-condition--condition-from-file="condition.json"

Lint result:

lintResults:-debugMessage:'resource.type:resourcemanager.projectsisnotsupported.Usingthisvalueinconditionmayleadtounintendedconsequences.Checkuserguideathttps://cloud.google.com/iam/docs/conditions-resource-attributes#resource_type_valuesforsupportedvaluesforresource.type.'fieldName:condition.expressionlevel:CONDITIONlocationOffset:17severity:WARNINGvalidationUnitName:LintValidationUnits/ResourceTypeLiteralCheck

RestrictedAttributesCheck

Example condition:

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

Run command:

gcloudalphaiampolicieslint-condition--condition-from-file="condition.json"

Lint result:

lintResults:-debugMessage:Condition attribute `request.auth.access_levels` is restrictedor unsupported. Please check https://cloud.google.com/iam/docs/conditions-overviewfor the full list of supported attributesfieldName:condition.expressionlevel:CONDITIONlocationOffset:57severity:WARNINGvalidationUnitName:LintValidationUnits/RestrictedAttributesCheck

Except as otherwise noted, the content of this page is licensed under theCreative Commons Attribution 4.0 License, and code samples are licensed under theApache 2.0 License. For details, see theGoogle Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.

Last updated 2025-12-15 UTC.