정책 린트

이 주제에서는 ID 및 액세스 관리(IAM) 정책을 린트(검사)하는 방법을 설명합니다.

시작하기 전에

IAM 정책의 린트 이해

IAM 정책의 맥락에서 린트는 새 정책이나 기존 정책을 검사하여 특정 문제를 확인하는 방법입니다. 이러한 문제에는 다음이 포함될 수 있습니다.

  • 제안
  • 경고
  • 정책의 의도를 개선할 수 있는 더 나은 구문 및 시맨틱스와 같은 정보
  • setIamPolicy 작업이 실패할 수 있는 구문 또는 시맨틱 오류

정책 린트를 디버깅 도구로 사용하여 실패한 setIamPolicy() 작업에 대한 자세한 설명을 제공할 수 있습니다. 의도한 결과를 얻을 수 있도록 IAM 정책을 쉽게 작성하기 위한 도우미 도구로 사용할 수도 있습니다.

조건 린트

조건 표현식은 특히 여러 절과 논리 연산자를 사용하여 액세스를 적절하게 제한해야 하는 상황에서 복잡해질 수 있습니다. 조건 표현식에 잘못된 논리가 포함되거나 구문이 조건 표현식의 제한을 위반하는 경우 setIamPolicy() 작업이 실패합니다. 또한 조건이 정책 업데이트를 위한 모든 엄격한 구문 및 시맨틱스 요구사항을 충족할 수 있지만 정책 시행 중에 예기치 않은 액세스 결과로 이어질 수 있는 구성을 포함할 수 있습니다. 이러한 사례의 몇 가지 예시는 다음과 같습니다.

  • 권장되지 않는 함수 사용
  • 기존 리소스 유형 또는 기존 서비스 이름 사용
  • 적용할 수 없는 날짜 또는 시간 범위와 같은 무효 조건

조건 린트는 철저한 검사를 수행하며 정책 업데이트에 발생할 수 있는 오류와 기타 의심스러운 구성을 모두 보고합니다.

새 조건부 역할 binding을 설정하기 전에 먼저 표현식을 린트하는 것이 좋습니다. 이 섹션에서는 Cloud Console, gcloud 명령줄 도구 또는 REST API를 사용하여 조건 표현식을 린트하는 방법을 보여줍니다.

조건 표현식을 린트하려면 다음을 수행합니다.

Console

  1. Cloud Console에서 IAM 페이지로 이동합니다.

    IAM 페이지로 이동

  2. 프로젝트 선택을 클릭하고 프로젝트를 선택한 후 열기를 클릭합니다.

  3. 구성원 목록에서 원하는 구성원을 찾아 버튼을 클릭합니다.

  4. 권한 수정 패널에서 원하는 역할을 찾습니다. 그런 다음 조건에서 조건의 이름을 클릭합니다.

  5. 조건 수정 패널에서 조건 편집기는 표현식을 린트하는 기능을 제공합니다. 조건 빌더에는 현재 제한된 린트 기능이 있습니다.

  6. 조건 편집기에서 조건 표현식을 직접 추가하거나 수정합니다.

  7. 오른쪽 상단 입력란 위에 있는 린터 실행을 클릭하여 CEL 구문의 유효성을 검사합니다. 구문에 오류가 있는 경우 아이콘이 표현식의 각 행 옆에 표시됩니다. 아이콘 위에 포인터를 놓으면 표현식의 해당 부분에 대한 오류 메시지가 표시되고 디버깅을 위해 조치할 수 있는 피드백이 제공됩니다.

    조건을 저장하기 전에 오류를 수정하는 것이 좋습니다. 조건이 구문상으로는 맞지만 린트 작업이 의심스러운 구문을 발견하는 경우 경고 아이콘()이 표시됩니다. 아이콘 위로 마우스를 가져가면 표현식의 해당 부분에 대한 경고 메시지가 표시되고 디버깅을 위한 조치를 취할 수 있습니다. 조건을 저장하기 전에 경고를 반드시 수정해야 하는 것은 아닙니다.

  8. 조건 표현식을 필요한 대로 변경합니다. 린터 실행이 실행된 후에는 표현식을 수정하기 쉽도록 백그라운드에서 계속해서 린트합니다.

  9. 표현식이 성공적으로 실행된 후에는 저장을 클릭하여 조건을 적용합니다.

  10. 조건 수정 패널이 닫히면 권한 수정 패널에서 저장을 다시 클릭하여 IAM 정책을 업데이트합니다.

gcloud 명령어

gcloud alpha iam policies lint-condition 명령어를 실행하여 지정된 조건 표현식을 린트합니다. 이 명령어를 실행하려면 조건이 포함된 텍스트 파일을 만들거나 조건의 제목, 설명, 표현식에 플래그를 지정합니다.

아래 예시에서는 다음 조건이 포함된 텍스트 파일을 사용합니다.

condition.json

"condition": {
    "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
...

각 린트 결과에는 debugMessage가 포함되어 조건 표현식의 문제점을 찾는 데 도움이 됩니다. 조건에서 컴파일할 수 없을 때 다음 debugMessage 텍스트가 포함된 여러 validationUnitName 유형을 볼 수 있습니다.

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

표현식이 성공적으로 컴파일되도록 필요한 변경 작업을 수행한 후 다시 조건 린트를 시도합니다.

REST API

lintPolicy()를 호출하여 조건 표현식을 린트합니다.

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

요청 본문에는 조건 표현식이 포함되어 있습니다.

{
    "condition": {
      "title": "1_less_than_2",
      "description": "",
      "expression": "1 &lt;"
    }
}

응답 본문에는 다음과 같은 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 \'&lt;EOF&gt;\' expecting {\'[\', \'{\', \'(\', \'.\', \'-\', \'!\', \'true\', \'false\', \'null\', NUM_FLOAT, NUM_INT, NUM_UINT, STRING, BYTES, IDENTIFIER}\n  | 1&lt;\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"
  }
}

각 린트 결과에는 debug_message가 포함되어 조건 표현식의 문제점을 찾는 데 도움이 됩니다. 조건에서 컴파일할 수 없을 때 다음 debugMessage 텍스트가 포함된 여러 validation_unit_name 유형을 볼 수 있습니다.

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

조건 표현식이 성공적으로 컴파일되도록 필요한 변경 작업을 수행한 후 다시 조건 린트를 시도합니다.

지원되는 검증 단위

위 섹션에서 설명한 것처럼 검증 단위는 구문 문제에 대한 표현식을 평가하는 개별 린트 유형입니다. 아래의 표는 각각의 린트 수준, 린트 결과 심각도, 간단한 설명이 포함된 지원 검증 단위를 요약한 것입니다.

검증 단위 린트 수준 심각도 설명
ConditionCompileCheck CONDITION ERROR 조건 표현식에 잘못된 CEL 구문으로 인한 컴파일 오류가 있습니다.
ConditionComplexityCheck CONDITION ERROR 조건 표현식에 포함된 논리 연산자 수가 최댓값인 12개를 초과합니다.
DateTimeCheck CONDITION WARNING 조건 표현식은 타임스탬프 비교가 사실상 참인지 거짓인지 지정합니다. 잘못된 타임스탬프 형식(ISO 8601 제외)이거나 만료 타임스탬프가 과거이거나 시작 타임스탬프가 과거입니다.
DateTimeRangeCheck CONDITION WARNING 의도한 고급 타임스탬프 함수 및 비교 표현식에 대한 범위를 벗어난 값입니다. 고급 타임스탬프 함수의 유효한 값 범위는 여기를 참조하세요.
EffectiveTimeRangeCheck CONDITION WARNING 타임스탬프 함수와 비교를 더 복잡하게 사용하면 표현식의 유효 시간 범위가 비어 사실상 거짓입니다. 또는 시간 범위가 전체 범위를 포함하므로 사실상 참입니다.
ResourceServiceLiteralCheck CONDITION WARNING 지정된 resource.service 값은 지원되지 않습니다. 균등 비교에 이러한 문자열 리터럴을 사용하는 표현식은 사실상 거짓입니다. 지원되는 값은 여기를 참조하세요.
ResourceTypeLiteralCheck CONDITION WARNING 지정된 resource.type 값은 지원되지 않습니다. 균등 비교에 이러한 문자열 리터럴을 사용하는 표현식은 사실상 거짓입니다. 지원되는 값은 여기를 참조하세요.
RestrictedAttributesCheck CONDITION WARNING 표현식에 현재 제한되거나 지원되지 않는 속성이 사용됩니다. 조건 표현식 설정이 성공하지 못할 수 있습니다. 속성 목록과 출시 단계는 여기를 참조하세요.

린트 예시

이 섹션에서는 각 검증 단위에 대한 린트 정책의 사용 예시를 제공합니다. 각 검증 단위에 대해 문제가 있는 입력 예시가 제공됩니다. 각 예시는 gcloud 명령줄 도구를 사용하여 린트를 보여줍니다.

ConditionCompileCheck

조건 표현식 예시:

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

명령어 실행:

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

린트 결과:

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

조건 표현식 예시:

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

명령어 실행:

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

린트 결과:

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

DateTimeCheck

조건 표현식 예시:

{
    "condition": {
      "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`

린트 결과:

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

조건 표현식 예시:

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

명령어 실행:

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

린트 결과:

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

EffectiveTimeRangeCheck

조건 표현식 예시:

{
    "condition": {
      "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`

린트 결과:

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

ResourceServiceLiteralCheck

조건 표현식 예시:

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

명령어 실행:

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

린트 결과:

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

조건 표현식 예시:

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

명령어 실행:

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

린트 결과:

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

조건 표현식 예시:

{
    "condition": {
      "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`

린트 결과:

lintResults:
- debugMessage: Condition attribute `request.auth.access_levels` is in private beta
    release and may be subject to whitelist control. Please check https://cloud.google.com/iam/docs/conditions-overview
    for the full list of restricted attributes
  fieldName: condition.expression
  level: CONDITION
  locationOffset: 57
  severity: WARNING
  validationUnitName: LintValidationUnits/RestrictedAttributesCheck