술어 언어 (Predicate Language)
Teleport의 술어 언어(predicate language)는 동적 구성 리소스에서 필터링 조건을 정의하는 데 사용됩니다. 술어 언어는 다음 중 어디에서 사용되느냐에 따라 구문이 약간 다릅니다: Teleport의 역할 리소스의 일부 필드는 술어 언어를 사용하여 역할 권한의 범위를 정의합니다:
Teleport의 술어 언어(predicate language)는 동적 구성 리소스에서 필터링 조건을 정의하는 데 사용됩니다. 또한 선택된 리소스 목록을 필터링하고 검색하는 쿼리 언어로도 사용됩니다.
술어 언어는 다음 중 어디에서 사용되느냐에 따라 구문이 약간 다릅니다:
역할 리소스에서 허용/거부 규칙 범위 지정#
Teleport의 역할 리소스의 일부 필드는 술어 언어를 사용하여 역할 권한의 범위를 정의합니다:
역할 리소스에서 사용될 때, 술어 언어는 다음 연산자를 지원합니다:
| 연산자 | 의미 | 예시 |
|---|---|---|
| && | AND (모든 조건이 일치해야 함) | contains(field1, field2) && equals(field2, "val") |
| || | OR (하나의 조건이라도 일치해야 함) | contains(field1, field2) || contains(field1, "val2") |
| ! | NOT (함수와 함께 사용, 아래 자세한 내용) | !equals(field1, field2) |
언어는 다음 함수도 지원합니다:
| 함수 | 설명 |
|---|---|
contains(<field>, <field2>) |
<field2>의 값이 <field>의 문자열 목록에 포함되어 있는지 확인합니다 |
contains(<field>, "<value>") |
<value>가 <field>의 문자열 목록에 포함되어 있는지 확인합니다 |
equals(<field>, <field2>) |
<field2>의 값이 <field>의 값과 같은지 확인합니다 |
equals(<field>, "<value>") |
<value>가 <field>의 값과 같은지 확인합니다 |
리소스 필터링#
tsh와 tctl CLI 도구 모두 --query 플래그를 사용하여 노드, 애플리케이션, 데이터베이스 및 Kubernetes 리소스를 필터링할 수 있습니다. --query 플래그를 사용하면 술어 언어를 통해 더 정교한 검색을 수행할 수 있습니다.
일반적인 리소스 필드의 경우, 다음과 같이 쉽게 접근할 수 있는 단축 필드 이름을 정의했습니다:
| 단축 필드 | 실제 필드 동등값 | 예시 |
|---|---|---|
labels["<key>"] |
resource.metadata.labels + resource.spec.dynamic_labels |
labels["env"] == "staging" |
name |
resource.spec.hostname (서버 리소스에만 적용) 또는 resource.metadata.name |
name == "jenkins" |
언어는 다음 연산자를 지원합니다:
| 연산자 | 의미 | 예시 |
|---|---|---|
| == | 같음 | labels["env"] == "prod" 또는 labels[`env`] == "prod" |
| != | 같지 않음 | labels["env"] != "prod" |
| && | AND (모든 조건이 일치해야 함) | labels["env"] == "prod" && labels["os"] == "mac" |
| || | OR (하나의 조건이라도 일치해야 함) | labels["env"] == "dev" || labels["env"] == "qa" |
| ! | NOT (함수와 함께 사용) | !equals(labels["env"], "prod") |
언어는 다음 함수도 지원합니다:
| 함수 (예시 포함) | 설명 |
|---|---|
equals(labels["env"], "prod") |
레이블 키 env가 레이블 값 prod와 같은 리소스 |
exists(labels["env"]) |
레이블 키 env가 있는 리소스; 레이블 값은 확인하지 않음 |
!exists(labels["env"]) |
레이블 키 env가 없는 리소스; 레이블 값은 확인하지 않음 |
search("foo", "bar", "some phrase") |
일반적인 리소스 필드에 대한 퍼지 매치 |
hasPrefix(name, "foo") |
접두사 foo로 시작하는 이름을 가진 리소스 |
split(labels["foo"], ",") |
구분된 문자열을 목록으로 변환 |
contains(split(labels["foo"], ","), "bar") |
목록에 값이 존재하는지 확인 |
리소스를 필터링하는 다양한 방법의 예시를 참조하십시오.
레이블 표현식#
레이블 표현식은 Teleport 역할에서 사용자 정의 로직으로 리소스에 대한 접근을 정의하는 데 사용할 수 있습니다. 레이블 표현식의 개요와 사용 가능한 위치에 대한 접근 제어 참조 페이지를 참조하십시오.
레이블 표현식은 다음 필드가 사용 가능한 술어 언어를 지원합니다:
| 필드 | 유형 | 설명 |
|---|---|---|
labels |
map[string]string |
접근하는 리소스(서버, 애플리케이션 등)의 정적 및 동적 레이블 합산. |
user.spec.traits |
map[string][]string |
리소스에 접근하는 사용자의 모든 traits (역할 템플릿 표현식에서 external 또는 internal로 참조됨). |
user.metadata.name |
string |
사용자의 Teleport 사용자 이름. |
언어는 다음 연산자를 지원합니다:
| 연산자 | 의미 | 예시 |
|---|---|---|
| == | 같음 | labels["env"] == "staging" |
| != | 같지 않음 | labels["env"] != "production" |
| || | OR (하나의 조건이라도 일치해야 함) | labels["env"] == "staging" || labels["env"] == "test" |
| && | AND (모든 조건이 일치해야 함) | labels["env"] == "staging" && labels["team"] == "dev" |
| ! | NOT (논리적 부정) | !regexp.match(user.spec.traits["teams"], "contractor") |
언어는 다음 함수도 지원합니다:
| 구문 | 반환 유형 | 설명 | 예시 |
|---|---|---|---|
contains(list, item) |
Boolean | list가 item과 정확히 일치하는 항목을 포함하면 true 반환 |
contains(user.spec.traits[teams], labels["team"]) |
regexp.match(list, re) |
Boolean | list가 re와 일치하는 항목을 포함하면 true 반환 |
regexp.match(labels["team"], "dev-team-\d+$") |
regexp.replace(list, re, replacement) |
[]string |
list의 모든 항목에 대해 re의 모든 일치를 replacement로 교체 |
contains(regexp.replace(user.spec.traits["allowed-env"], "^env-(.*)$", "$1"), labels["env"]) |
email.local(list) |
[]string |
list의 각 이메일의 로컬 부분을 반환하거나, 이메일 파싱에 실패하면 오류 반환 |
contains(email.local(user.spec.traits["email"]), labels["owner"]) |
strings.upper(list) |
[]string |
목록의 모든 항목을 대문자로 변환 | contains(strings.upper(user.spec.traits["username"]), labels["owner"]) |
strings.lower(list) |
[]string |
목록의 모든 항목을 소문자로 변환 | contains(strings.lower(user.spec.traits["username"]), labels["owner"]) |
labels_matching(re) |
[]string |
re와 일치하는 키를 가진 모든 레이블 값의 집계를 반환 (글로브 또는 정규 표현식 가능) |
contains(labels_matching("^project-(team|label)$"), "security") |
contains_any(list, items) |
Boolean | list가 items의 임의 요소와 정확히 일치하는 항목을 포함하면 true 반환 |
contains_any(user.spec.traits["projects"], labels_matching("project-*")) |
contains_all(list, items) |
Boolean | list가 items의 모든 요소와 정확히 일치하는 항목을 포함하면 true 반환 |
contains_all(user.spec.traits["projects"], labels_matching("project-*")) |
위에서 list라는 인수는 값 목록(특정 사용자 trait의 값 목록 등)이나 단일 값(리소스 레이블의 값 또는 문자열 리터럴 등)을 받을 수 있습니다.
regexp 함수에서 사용하는 표현식은 글로빙(예: "env-*")을 지원하거나, ^와 $로 감싸서 표준 정규 표현식 구문(예: "^env-.*$")을 사용할 수 있습니다.
접근 모니터링 규칙#
접근 모니터링 규칙은 술어 언어를 사용하여 알림 라우팅 규칙 또는 자동 검토 규칙을 접근 요청에 적용하기 위한 조건을 정의합니다.
접근 모니터링 규칙은 다음 필드가 사용 가능한 술어 언어를 지원합니다:
| 필드 | 설명 |
|---|---|
| access_request.spec.roles | 요청된 역할 집합. |
| access_request.spec.suggested_reviewers | 요청에 지정된 검토자 집합. |
| access_request.spec.system_annotations | 요청의 시스템 주석 맵. |
| access_request.spec.user | 요청하는 사용자. |
| access_request.spec.request_reason | 요청 이유. |
| access_request.spec.creation_time | 요청의 생성 시간. |
| access_request.spec.expiry | 요청의 만료 시간. |
| access_request.spec.resource_labels_intersection | 모든 요청된 리소스 레이블의 교집합을 포함하는 맵. |
| access_request.spec.resource_labels_union | 모든 요청된 리소스 레이블의 합집합을 포함하는 맵. |
| user.traits | 요청하는 사용자의 traits 맵. |
언어는 다음 연산자를 지원합니다:
| 연산자 | 의미 | 예시 |
|---|---|---|
| == | 같음 | access_request.spec.user == "example_user" |
| != | 같지 않음 | access_request.spec.user != "example_user" |
| && | AND (모든 조건이 일치해야 함) | regexp.match(user.traits["level"], "^L1$") && regexp.match(user.traits["team"], "^Cloud$") |
| || | OR (하나의 조건이라도 일치해야 함) | regexp.match(user.traits["level"], "^L1$") || regexp.match(user.traits["team"], "^Cloud$") |
| ! | NOT (함수와 함께 사용) | !regexp.match(set(access_request.spec.request_reason), "*important*") |
언어는 다음 함수도 지원합니다:
| 함수 | 설명 | 예시 |
|---|---|---|
contains_any(set, items) |
set이 items의 임의 요소와 정확히 일치하는 항목을 포함하면 true 반환 |
contains_any(user.traits["team"], set("dev", "stage")) |
contains_all(set, items) |
set이 items의 모든 요소와 정확히 일치하는 항목을 포함하면 true 반환 |
contains_all(access_request.spec.roles, set("dev", "security", "cloud")) |
contains(set, item), set.contains(item) |
set이 item과 정확히 일치하는 항목을 포함하면 true 반환 |
contains(access_request.spec.roles, "dev") |
regexp.match(set, re) |
set이 re와 일치하는 항목을 포함하면 true 반환 |
regexp.match(set(access_request.spec.request_reason), "*on-call*") |
is_empty(set) |
set이 요소를 포함하지 않으면 true 반환 |
is_empty(access_request.spec.roles) |
regexp 함수에서 사용하는 표현식은 글로빙(예: "env-*")을 지원하거나, ^와 $로 감싸서 표준 정규 표현식 구문(예: "^env-.*$")을 사용할 수 있습니다.
