Keyboard shortcuts

Press ← or → to navigate between chapters

Press ? to show this help

Press Esc to hide this help

CEL 승인 정책 예시

정책은 각 변경에 대해 함께 평가됩니다. 아래에서 approve()를 반환하는 분기는 해당 정책의 검토 요건을 면제하며, 다른 정책의 요건을 없애지는 않습니다. no_op()로 넘긴 유형을 처리하는 정책도 있어야 합니다.

팀 이름, 모듈 이름과 서비스 계정은 가상의 예시입니다. 실제 리소스와 조직의 승인 범위에 맞추어 지정합니다.

작성자의 팀으로 자동 승인 대상 선택

approvedTeam을 STRING 변수로 정의하고 허용할 팀 이름을 값으로 지정합니다.

type == "UPDATE_ENTITY" && {{ policyVariable.approvedTeam }} in author.teams
  ? approve("허용된 팀의 구성원이 작성한 변경입니다.")
  : no_op()

팀 이름은 정책 변수에서 바꿀 수 있습니다. 이 조건은 요청을 연 author의 팀을 검사합니다. 서비스 계정이 사용자를 대신하여 연 요청에서는 실제 요청자가 onBehalfOf에 있으므로, 누구의 권한으로 자동 승인을 허용할지 구분해야 합니다.

작성자가 가진 리소스 역할로 선택

해당 설치본의 운영자 역할을 가진 작성자를 선택할 수도 있습니다.

type == "UPDATE_ENTITY" &&
  "entity:operator" in referencedResources.installation.authorRoles
  ? approve("이 설치본의 개체 운영자가 작성한 변경입니다.")
  : no_op()

팀 소속은 author.teams, 대상 리소스에서 가진 역할은 해당 참조의 authorRoles에서 검사합니다.

특정 개체 유형에 보안 팀 검토 요구

다음 정책은 네트워크 보안 개체의 구성 변경만 처리합니다.

type == "UPDATE_ENTITY" && request.apolloEntityType == "network-security"
  ? require_team(
      "platform-security",
      "네트워크 보안 구성에는 보안 팀의 승인이 필요합니다."
    )
  : no_op()

먼저 변경 유형을 확인하고 그 유형에서 제공하는 request.apolloEntityType을 검사합니다. 다른 변경이나 개체 유형에서는 결과를 내지 않습니다.

기존 승인 요건에 보안 검토 추가

기존 정책이 개체 운영자의 승인을 요구하는 상태에서 다음 정책을 활성화하면, 모든 개체 구성 변경에 보안 팀 승인도 필요해집니다.

type == "UPDATE_ENTITY"
  ? require_team("platform-security", "모든 개체 구성 변경을 보안 팀이 검토해야 합니다.")
  : no_op()

운영자 승인과 보안 팀 승인을 모두 충족해야 합니다. 두 역할을 가진 사용자의 승인 하나가 두 요건에 해당할 수 있습니다. 각 정책은 다른 정책의 내용을 직접 읽을 필요 없이 자신의 요건을 반환합니다.

특정 모듈의 요청 허용

모듈 설치에서 발생한 개별 개체 변경에는 기존 개체 정책들도 적용됩니다. 특정 모듈 요청을 자동 승인하려면 승인자를 요구하는 해당 정책 안에 허용 분기를 넣어야 합니다.

다음은 서비스 개체의 구성 변경을 처리하는 정책에 가상의 my-trusted-module을 추가한 예시입니다. 기존 Apollo 서비스 계정의 자동 승인 분기도 유지합니다.

type == "UPDATE_ENTITY" && request.apolloEntityType == "service" ? (
  should_auto_approve_service_user(type, author, onBehalfOf, editors)
    ? approve("신뢰하는 Apollo 서비스 계정의 변경입니다.")
    : (
        is_trusted_module_request(author, metadata, editors) &&
        "module" in referencedResources &&
        referencedResources.module.name == "my-trusted-module"
          ? approve("허용된 모듈의 설치 요청입니다.")
          : require_operation(
              referencedResources.installation.rid,
              "entity:approve-config-update",
              "개체 구성 변경 승인 권한이 필요합니다."
            )
      )
) : no_op()

module 키는 하나의 모듈 설치와 관련된 변경에서 제공되므로 존재 여부를 먼저 확인합니다. 모듈에 포함된 개체 유형을 처리하는 다른 정책에도 필요한 분기를 추가합니다. 특히 구성 변경, 운영 설정 변경과 삭제 정책을 확인해야 하며, 신규 개체 생성이 포함되면 생성 정책도 확인합니다.

is_trusted_module_request는 요청의 생성 주체와 편집 여부를 검사합니다. 모듈 소유자가 선택한 승인 모드나 사용자 작성 구성의 덮어쓰기 여부는 검사하지 않습니다. 자동 업데이트 자격을 따르려면 다음 조건을 사용합니다.

type == "UPDATE_ENTITY" ? (
  should_auto_approve_service_user(type, author, onBehalfOf, editors)
    ? approve("신뢰하는 Apollo 서비스 계정의 변경입니다.")
    : (
        is_trusted_module_update_eligible_for_auto_approval(
          author, metadata, editors, request
        )
          ? approve("자동 승인 자격을 충족한 모듈 업데이트입니다.")
          : require_operation(
              referencedResources.installation.rid,
              "entity:approve-config-update",
              "개체 구성 변경 승인 권한이 필요합니다."
            )
      )
) : no_op()

이 표현식을 기존 정책에 통합할 때도 해당 정책의 Apollo 서비스 계정 처리와 다른 변경 유형의 분기는 유지해야 합니다.

모듈 버전까지 제한

모듈 관련 변경에서는 module.name으로 모듈의 제품 ID를, moduleRelease.name으로 릴리스 버전을 확인합니다. 다음은 가상의 모듈 my-module의 1.0.0 버전에 해당하는 구성 변경을 선택합니다.

type == "UPDATE_ENTITY" &&
  "module" in referencedResources &&
  "moduleRelease" in referencedResources &&
  referencedResources.module.name == "my-module" &&
  referencedResources.moduleRelease.name == "1.0.0"
    ? approve("허용한 모듈과 버전의 변경입니다.")
    : no_op()

이 조건은 모듈과 버전만 검사합니다. 요청이 다른 사용자에게 편집되지 않았는지까지 요구하려면 모듈 신뢰 판정도 함께 사용합니다. 기존 정책의 검토 요건을 면제하려는 경우에는 그 정책의 승인 분기에 조건을 통합해야 합니다.

외부 통신의 목적지와 포트 제한

CREATE_EGRESS_POLICIES의 request.data는 생성할 정책 목록입니다. all 매크로로 모든 항목의 목적지와 포트를 검사할 수 있습니다.

다음은 가상의 신뢰할 목적지가 example.com의 443번 포트일 때의 조건입니다.

type == "CREATE_EGRESS_POLICIES" && request.data.all(policy,
  policy.address.type == "dns" &&
  policy.address.dns == "example.com" &&
  policy.port.port == 443 &&
  (!has(policy.port.portRangeEnd) || policy.port.portRangeEnd == 443)
)
  ? approve("모든 항목의 목적지가 example.com의 443번 포트입니다.")
  : no_op()

다른 호스트나 포트가 하나라도 있으면 no_op()로 넘어갑니다. 끝 포트가 없는 단일 포트와 시작 및 끝이 모두 443인 범위만 조건을 통과합니다. 시작 포트만 443이고 끝 포트가 더 큰 범위는 통과하지 않습니다.

목록이 비어 있으면 all은 참을 반환합니다. 이 조건에는 최소 항목 수 검사가 포함되지 않습니다.

이 조건은 목적지와 포트만 제한합니다. 전송 프로토콜이나 네트워크 경로에도 제한이 필요하면 transportProtocol과 network의 조건을 별도로 정해야 합니다.