Sentinel 정책 예시

Sentinel 정책 예시 (Examples)

Vault Enterprise에서 Sentinel 정책을 작성하는 데 익숙하지 않다면, 다음 예시가 개념을 소개하는 데 도움이 됩니다. 몇 가지 모범 사례를 이해하려면 처음부터 읽어보세요. 추가 예시는 여기에서 찾을 수 있습니다.

출처: 문서

본문

로그인 시 MFA 및 CIDR 검사

다음 Sentinel 정책은 들어오는 사용자가 LDAP으로 인증하기 전에 Okta MFA 푸시 요청으로 성공적으로 검증하도록 요구합니다. 또한 10.20.0.0/16 서브넷에 있는 사용자만 LDAP을 사용해 인증할 수 있도록 보장합니다.

import "sockaddr"
import "mfa"
import "strings"

# We expect logins to come only from our private IP range
cidrcheck = rule {
    sockaddr.is_contained("10.20.0.0/16", request.connection.remote_addr)
}

# Require ping MFA validation to succeed
ping_valid = rule {
    mfa.methods.ping.valid
}

main = rule when strings.has_prefix(request.path, "auth/ldap/login") {
    ping_valid and cidrcheck
}

main 규칙의 rule when 구문에 주목하세요. 이것은 정책을 주어진 조건으로 범위를 한정합니다.

Vault는 보안에 대해 기본 거부(default-deny) 접근 방식을 취합니다. 이러한 범위 한정이 없으면, 활성 Sentinel 정책이 모두 성공적으로 통과해야 하므로 사용자는 통과 상태로 시작한 다음 접근이 거부되는 조건을 정의해야 하며, 이는 기본 거부 개념을 깨뜨립니다.

대신 main 규칙(그리고 이 예시에서는 전체 정책)을 평가해야 하는 조건을 나타냄으로써, 정책은 일치하는 요청이 성공하는 조건을 설명하게 됩니다. 이는 Vault의 기본 거부 느낌을 유지합니다. 평가 조건이 충족되지 않으면 정책은 단순히 no-op입니다.

특정 ID 엔티티 또는 그룹만 허용

main = rule {
    identity.entity.name is "jeff" or
    identity.entity.id is "fe2a5bfd-c483-9263-b0d4-f9d345efdf9f" or
    "sysops" in identity.groups.names or
    "14c0940a-5c07-4b97-81ec-0d423accb8e0" in keys(identity.groups.by_id)
}

이 예시는 결정을 내리기 위해 Identity 속성에 접근하는 것을 보여주며, Identity 값에 대해 참조에 ID나 이름을 사용할 수 있음을 보여줍니다.

일반적으로 ID를 사용하는 것이 더 안전합니다. 편리하지만 엔티티 이름과 그룹 이름은 유일해야 한다는 제약만 있으므로 한 엔티티에서 다른 엔티티로 바뀔 수 있습니다. ID를 사용하면 특정 엔티티나 그룹만 충분하다는 것을 보장합니다. 그룹이나 엔티티가 삭제되고 같은 이름으로 다시 생성되면 일치가 실패합니다.

이전에 생성된 모든 토큰 즉시 거부

이전에 생성된 알 수 없는 수의 토큰이 손상되었다는 것이 발견된 브레이크 글라스(break-glass) 시나리오를 상상해보세요.

이러한 상황에서는 이전 모든 토큰을 폐기(revoke)하는 것이 가능하지만, 생성된 시크릿 폐기가 필요하거나 단순히 스토리지에서 많은 항목을 제거하는 데 필요한 지연 때문에 시간이 걸릴 수 있습니다. 또한 나중에 포렌식 분석에서 손상되지 않은 것으로 밝혀진 토큰과 생성된 시크릿까지 폐기하여, 대량 폐기의 영향을 불필요하게 넓힐 수 있습니다.

Vault의 ACL 시스템에서는 단순한 거부를 넣을 수 있지만, 이는 매우 거친 제어이며 그런 식으로 수정할 수 있는 정책이 모든 토큰에 연결되도록 보장하려면 사전 숙고가 필요합니다. 또한 로그인 경로나 다른 인증되지 않은 경로에 대한 접근을 방지하지 못합니다.

Sentinel은 훨씬 더 세밀한 제어를 제공합니다.

import "time"

main = rule when not request.unauthenticated {
    time.load(token.creation_time).unix >
      time.load("2017-09-17T13:25:29Z").unix
}

*에 EGP로 생성하면, Sentinel이 운영하는 모든 경로에 대해 주어진 시간 이전에 생성된 토큰으로 접근을 차단합니다. 이 시간 이후에 생성된 토큰은 손상의 일부가 아니었기 때문에 이 제한의 대상이 되지 않습니다.

경로 아래의 EGP 정책 관리 위임

다음 정책은 이 정책을 가진 토큰 보유자(자신의 토큰 또는 Identity 엔티티/그룹을 통해)에게 특정 접두사 아래의 Vault 경로에서만 효력을 발휘할 수 있는 EGP 정책을 작성하는 기능을 부여합니다. 이는 효과적으로 팀이 자신의 키-값 공간에 대한 정책 관리를 위임받는 것입니다.

import "strings"

data_match = func() {
    # Make sure there is request data
    if length(request.data else 0) is 0 {
        return false
    }

    # Make sure request data includes paths
    if length(request.data.paths else 0) is 0 {
        return false
    }

    # For each path, verify that it is in the allowed list
    for strings.split(request.data.paths, ",") as path {
        # Make it easier for users who might be used to starting paths with
        # slashes
        sanitizedPath = strings.trim_prefix(path, "/")
        if not strings.has_prefix(sanitizedPath, "dev-kv/teama/") and
           not strings.has_prefix(sanitizedPath, "prod-kv/teama/") {
            return false
        }
    }

    return true
}

# Only care about writing; reading can be allowed by normal ACLs
precond = rule {
    request.operation in ["create", "update"] and
    strings.has_prefix(request.path, "sys/policies/egp/")
}

main = rule when precond {
    strings.has_prefix(request.path, "sys/policies/egp/teama-") and data_match()
}

더 알아보기 (Learn more)