Keyboard shortcuts

Press ← or → to navigate between chapters

Press ? to show this help

Press Esc to hide this help

CEL 승인 정책의 평가 방식

Apollo는 CEL(Common Expression Language) 표현식으로 변경 요청에 필요한 승인자를 정합니다. CEL은 애플리케이션에 정책을 넣어 평가하기 위한 오픈 소스 표현식 언어입니다. C, Java, JavaScript와 Go의 조건식에 익숙하다면 비교 연산, 논리 연산과 조건에 따른 분기를 비슷한 형태로 작성할 수 있습니다.

정책은 공간(Space)별로 관리합니다. 공간 관리자는 Space Settings에서 정책을 조회하고 수정할 수 있습니다. 변경 요청이 열리면 해당 공간에서 활성화된 정책들을 평가합니다.

개별 변경을 평가하는 단위

정책은 변경 요청 안의 개별 배포 개체 변경을 평가합니다. 하나의 요청에서 두 개체를 변경하면 두 입력을 따로 평가하며, 각 개체에 필요한 검토자가 달라질 수 있습니다.

각 입력에는 모든 활성 정책을 적용합니다. 여러 정책이 반환한 승인 요건은 AND 관계로 결합하므로 모든 요건을 충족해야 변경을 승인할 수 있습니다.

가상의 요청에서 다음 두 정책이 함께 적용된다고 가정하겠습니다.

정책반환한 요건
개체 구성 정책해당 설치본의 운영자가 승인
보안 검토 정책보안 팀이 승인

두 요건을 모두 충족해야 합니다. 한 사용자가 해당 설치본의 운영자이면서 보안 팀의 구성원이면 한 번의 승인이 두 요건을 충족할 수 있습니다.

어떤 정책이 자동 승인 결과를 반환해도 다른 정책의 요건은 남습니다. 자동 승인을 허용하려면 해당 변경에 승인자를 요구하는 기존 정책들의 분기를 함께 검토해야 합니다.

정책이 반환하는 결과

결과해당 정책의 동작
approve(reason)이 정책에서는 검토자를 요구하지 않음
reject(reason)변경을 즉시 거절
require_role, require_operation, require_team역할, 작업 권한 또는 팀을 기준으로 승인 요건 생성
require_any여러 승인 요건 가운데 하나를 충족하도록 요구
no_op()해당 변경에 관여하지 않으며 결과를 결합에서 제외

모든 활성 정책이 같은 입력에 no_op()를 반환하면 Apollo는 오류를 반환합니다. 특정 유형만 처리하는 정책은 다른 유형에 no_op()를 반환할 수 있지만, 그 유형을 실제로 처리하는 정책도 있어야 합니다.

정책의 모든 실행 경로는 결과 함수를 반환해야 합니다. 참이나 거짓을 반환하는 조건만으로 정책을 끝낼 수는 없습니다. 함수의 매개변수와 승인 요건의 결합은 정책 함수에서 설명합니다.

표현식과 이름 있는 변수

정책은 결과를 계산하는 표현식 문자열과 선택적인 이름 있는 변수로 구성됩니다. 변수마다 이름, 타입과 값을 지정합니다. 표현식의 {{ policyVariable.variableName }}는 평가 전에 설정된 값으로 치환됩니다.

가상의 trustedAuthors 변수를 STRING_LIST 타입으로 정의하고 신뢰할 작성자의 사용자 이름 목록을 저장하면 다음 정책에서 사용할 수 있습니다.

type == "UPDATE_ENTITY" ? (
  author.username in {{ policyVariable.trustedAuthors }}
    ? approve("신뢰할 작성자의 개체 구성 변경입니다.")
    : require_role(
        referencedResources.installation.rid,
        "entity:operator",
        "개체 운영자의 승인이 필요합니다."
      )
) : no_op()

이 정책은 개체의 애플리케이션 구성을 바꾸는 UPDATE_ENTITY만 처리합니다. 목록에 있는 작성자는 이 정책의 검토 요건을 면제받고, 다른 작성자는 해당 설치본의 운영자 승인을 받아야 합니다. 다른 변경 유형은 별도의 정책에서 처리합니다.

문법의미
a == b두 값 비교
a && b두 조건을 모두 충족
a || b조건 중 하나 이상 충족
value in collection목록, 집합 또는 맵의 키에 값이 포함되는지 확인
condition ? resultA : resultB조건이 참이면 첫 결과, 거짓이면 두 번째 결과 선택
has(object.field)해당 필드의 존재 여부 확인

이름 있는 변수는 사용자 목록처럼 운영 중 자주 바꾸는 값을 표현식과 분리할 때 유용합니다. 팀 이름 하나에는 STRING, 여러 사용자 이름에는 STRING_LIST를 사용할 수 있습니다.

모든 평가에서 사용하는 입력

필드타입의미와 사용 조건
type문자열CREATE_ENTITY, UPDATE_ENTITY 같은 변경 유형
author객체요청을 연 사용자. username은 문자열, teams는 팀 이름 문자열의 집합
onBehalfOf객체서비스 계정이 다른 사용자를 대신하여 요청한 경우 실제 요청자. 구조는 author와 같으며, 대신 요청한 경우가 아니면 없음
editors집합요청을 연 뒤 내용을 편집한 사용자 이름 문자열
metadata맵내부 변경 요청 메타데이터. 신뢰 판정 함수에 그대로 전달
request객체변경 유형별 요청 데이터
diff맵변경된 필드만 있는 차이 정보. 제거된 필드의 값은 "<<unset>>"
referencedResources맵변경과 관련된 리소스. 사용할 수 있는 키는 변경 유형에 따라 다름
createdAt타임스탬프요청을 연 시각
now타임스탬프현재 정책을 평가하는 시각

서비스 계정이 사용자를 대신하여 요청했다면 author에는 서비스 계정이, onBehalfOf에는 실제 요청자가 들어갑니다. 작성자의 팀을 검사하는 조건과 실제 요청자의 신원을 검사하는 조건은 이 구분에 맞추어 작성합니다.

diff는 전체 구성의 복사본이 아닙니다. 변경되지 않은 키는 없으며, 키가 없다는 사실과 제거 표시가 있는 상태를 구분해야 합니다. 이 차이 정보의 "<<unset>>"과 모듈 설정에서 키를 제거하는 {{ unset }}은 서로 다른 형식입니다.

유형을 먼저 확인하기

request와 referencedResources의 필드는 변경 유형에 따라 달라집니다. 개체 구성 정책에서는 먼저 type을 확인한 뒤 설치본이나 개체 유형 필드에 접근합니다. 모듈과 관련된 변경인지 확인하려면 해당 참조 키가 있는지도 검사해야 합니다.

필드별 조건은 변경 유형별 입력, 팀과 모듈 및 외부 통신을 기준으로 분기하는 정책은 정책 예시에서 확인할 수 있습니다. 개발 환경의 자동 승인은 환경별 승인 범위 설정에서 다룹니다.