Auto-인증이란 무엇인가?

Auto-인증이란 무엇인가? (What is Auto-authentication?)

Auto-인증(auto-authentication)은 다양한 환경에서 클라이언트 인증을 단순화합니다. 다음 Vault 도구에는 auto-인증이 내장되어 있습니다.

  • Vault Agent
  • Vault Proxy

출처: 문서

본문

방법(Method)과 싱크(Sink)

Auto-auth는 두 부분으로 구성됩니다.

  • 방법(method) — 현재 환경에 맞는 원하는 인증 방법입니다.
  • 싱크(sink) — 토큰 값이 바뀔 때 도구가 토큰을 저장하는 위치입니다.

지원되는 도구가 auto-auth를 활성화한 채 시작되면, 도구는 구성된 방법을 사용해 Vault 토큰을 요청합니다. 요청이 실패하면 도구는 지수 백오프(exponential back off)로 요청을 재시도합니다.

요청이 성공하면 auto-auth는 Vault가 갱신을 거부할 때까지 래핑되지 않은 인증 토큰을 자동으로 갱신합니다. 인증 방법이 토큰을 래핑하면 auto-인증은 토큰을 자동으로 갱신할 수 없습니다.

Vault는 일반적으로 토큰이 다음과 같으면 갱신을 거부합니다.

  • 토큰이 폐기된 경우.
  • 토큰이 최대 사용 횟수를 초과한 경우.
  • 토큰이 그 외에 유효하지 않은 경우.

인증이 성공할 때마다 auto-auth는 적절히 구성된 모든 싱크에 토큰을 기록합니다.

고급 기능 (Advanced functionality)

싱크는 몇 가지 고급 기능을 지원합니다. 여기에는 기록된 값이 암호화되거나 response-wrapped가 되는 기능이 포함됩니다.

두 메커니즘을 동시에 사용할 수 있습니다. 이 경우 값은 먼저 response-wrapped된 다음 암호화됩니다.

Response-Wrapping 토큰

토큰을 response-wrap하는 방법은 두 가지입니다.

  1. 인증 방법에 의한 래핑 — 이를 통해 최종 클라이언트가 토큰의 creation_path를 검사할 수 있어 중간자(MITM) 공격을 막는 데 도움이 됩니다. 다만 auto-auth는 creation_path를 바꾸지 않고 토큰을 unwrap·rewrap할 수 없으므로 토큰을 갱신할 수 없습니다. 토큰을 갱신하는 것은 최종 클라이언트의 몫입니다. 일부 인증 방법이 특정 이벤트에서 재인증을 허용하므로 Agent와 Proxy는 이 모드에서 계속 데몬화되어 있습니다.
  2. 토큰 싱크에 의한 래핑 — 싱크를 두 개 이상 구성할 수 있으므로, 토큰은 Vault가 반환할 때 래핑하는 대신 가져온 후에 래핑해야 합니다. 결과적으로 creation_path는 항상 sys/wrapping/wrap이 되며, 이 필드의 검증을 MITM 공격에 대한 보호로 사용할 수 없습니다. 다만 이 모드는 auto-auth가 최종 클라이언트를 위해 토큰을 계속 갱신하고, 만료되면 자동으로 재인증하게 해 줍니다.

토큰 암호화

참고

암호화된 토큰 지원은 실험적입니다. 입출력 형식이 바뀌면 하위 호환성을 제공하기 위해 최선을 다할 것입니다.

토큰은 Diffie-Hellman 교환을 사용해 임시(ephemeral) 키를 생성해 암호화할 수 있습니다. 이 메커니즘에서 토큰을 받는 클라이언트는 생성된 공개 키를 파일에 씁니다. 그 클라이언트에 토큰을 쓰는 책임이 있는 싱크는 이 공개 키를 찾아 이로 공유 시크릿 키를 계산하고, 이를 AES-GCM으로 토큰을 암호화하는 데 사용합니다. 그런 다음 nonce, 암호화된 페이로드, 싱크의 공개 키가 출력 파일에 기록되며, 클라이언트는 공유 시크릿을 계산해 토큰 값을 복호화할 수 있습니다.

참고

토큰 암호화는 MITM 공격에 대한 보호가 아닙니다! 이 기능의 목적은 순방향 비밀성(forward-secrecy)과 토큰 원본 값이 영속되는 것을 방지하는 것입니다. 싱크의 출력 또는 클라이언트 공개 키 입력 파일에 쓸 수 있는 MITM은 이 교환을 공격할 수 있습니다. 토큰 전송을 보호하려면 TLS를 사용하는 것이 매우 권장됩니다.

MITM 공격을 완화하는 데 도움이 되도록 AAD(추가 인증 데이터, Additional Authenticated Data)를 Agent와 Proxy에 제공할 수 있습니다. 이 데이터는 AES-GCM 태그의 일부로 기록되며 Agent·Proxy와 클라이언트 양쪽에서 일치해야 합니다. 이 AAD를 보호하는 것이 물론 중요해지지만, 공격자가 넘어야 하는 또 하나의 계층을 제공합니다. 예를 들어 공격자가 토큰이 기록되는 파일시스템에 접근할 수 있지만 구성 파일을 읽거나 환경 변수를 읽을 수는 없다면, 이 AAD를 Agent·Proxy와 클라이언트에 공격자가 찾기 어려운 방식으로 생성·전달할 수 있습니다.

AAD를 사용할 때는 가능한 한 신선하게 유지하는 것이 항상 좋습니다. 시작 시 값을 생성해 클라이언트와 Agent·Proxy에 전달하세요. 또한 Agent와 Proxy는 TOFU(Trust On First Use) 모델을 사용합니다. 생성된 공개 키를 찾은 후에는 새로 기록된 값을 찾는 대신 그 공개 키를 재사용합니다.

이 기능을 사용하는 클라이언트를 작성한다면 dhutil 라이브러리를 보는 것이 도움이 될 것입니다. 이 라이브러리는 공개 키 입력과 봉투(envelope) 출력의 예상 형식을 보여줍니다.

구성 (Configuration)

최상위 auto_auth 블록에는 두 개의 구성 항목이 있습니다.

  • method (object: required) — 방법에 대한 구성입니다.
  • sinks (array of objects: optional) — 싱크에 대한 구성입니다.
  • enable_reauth_on_new_credentials (bool: false) — 활성화하면 Auto-auth는 지원되는 인증 방법(AliCloud/AWS/Cert/JWT/LDAP/OCI)의 새 자격 증명 이벤트를 처리하고 새 자격 증명으로 재인증합니다.

구성 (방법, Method)

참고

Auto-auth는 사용 횟수가 제한된 토큰 사용을 지원하지 않습니다. Auto-auth는 남은 사용 횟수를 추적하지 않으며, 토큰을 갱신하기 전에 토큰이 만료되도록 내버려 둘 수 있습니다. 예를 들어 AppRole auto-auth를 사용한다면 token_num_uses 값으로 0(무제한 의미)을 사용해야 합니다.

다음은 method 블록 안에 있는 공통 구성 값입니다.

  • type (string: required) — 사용할 방법의 유형입니다. 예: aws, gcp, azure 등. 참고: HCL을 사용할 때는 이를 블록의 키로 사용할 수 있습니다(예: method "aws" {...}).
  • mount_path (string: optional) — 방법의 마운트 경로입니다. 지정하지 않으면 auth/<method type> 값으로 기본 설정됩니다.
  • namespace (string: optional) — 마운트가 있는 네임스페이스입니다. 우선 순위는 낮은 것부터: 이 설정, 그 다음 환경 변수 VAULT_NAMESPACE, 마지막으로 가장 높은 우선 순위의 커맨드라인 옵션 -namespace입니다. 이 중 아무것도 지정하지 않으면 루트 네임스페이스로 기본 설정됩니다. 싱크 response wrapping과 템플릿도 auto-auth가 만든 클라이언트를 기반으로 하므로 같은 네임스페이스를 사용합니다. Vault Agent 또는 Vault Proxy의 Vault 스탠자에 있는 namespace 옵션과 함께 지정하면, 그 구성이 auto-auth를 제외한 모든 것에 우선합니다.
  • wrap_ttl (string or integer: optional) — 지정하면 기록된 토큰이 auto-auth에 의해 response-wrapped됩니다. 이는 싱크로 래핑하는 것보다 안전하지만, auto-auth가 토큰을 계속 갱신하거나 만료 시 자동으로 재인증할 수 없게 합니다. 기록된 값은 단순한 문자열이 아니라 JSON 인코딩된 SecretWrapInfo 구조입니다. 기간 형식 문자열을 사용합니다.
  • min_backoff (string or integer: "1s") — 실패한 인증 시도 후 auto-auth가 재시도 전에 지연할 최소 백오프 시간입니다. 백오프는 구성된 값에서 시작해 연속 실패 후 (약간의 무작위성과 함께) 두 배가 되며, max_backoff에 의해 제한됩니다. Agent 템플릿을 사용 중이면 이 값은 템플릿 서버의 최소 백오프 시간으로도 사용됩니다. 기간 형식 문자열을 사용합니다.
  • max_backoff (string or integer: "5m") — 실패한 인증 시도 후 Agent가 재시도 전에 지연할 최대 시간입니다. 백오프는 min_backoff에서 시작해 연속 실패 후 (약간의 무작위성과 함께) 두 배가 되며, max_backoff에 의해 제한됩니다. Agent 템플릿을 사용 중이면 이 값은 템플릿 서버의 최대 백오프 시간으로도 사용됩니다. max_backoff는 재시도 사이의 간격이지, 포기하기 전에 재시도를 수행하는 기간이 아닙니다. 기간 형식 문자열을 사용합니다.
  • exit_on_err (bool: false) — true로 설정하면 Vault Agent와 Vault Proxy는 인증 중 오류가 발생하면 종료합니다. 이 구성은 새 토큰(초기 또는 만료된 토큰)에 대한 로그인 시도에만 영향을 주며, 유효한 토큰 갱신의 오류로는 종료하지 않습니다.
  • config (object: required) — 방법 자체의 구성입니다. 각 방법에 대한 정보는 사이드바를 참조하세요.

구성 (싱크, Sinks)

다음 구성 값은 모든 싱크에 공통입니다.

  • type (string: required) — 사용할 방법의 유형입니다. 예: file. 참고: HCL을 사용할 때는 이를 블록의 키로 사용할 수 있습니다(예: sink "file" {...}).
  • wrap_ttl (string or integer: optional) — 지정하면 기록된 토큰이 싱크에 의해 response-wrapped됩니다. 이는 방법에 의한 래핑보다 안전하지 않지만, auto-auth가 토큰을 계속 갱신하고 만료 시 자동으로 재인증하게 해 줍니다. 기록된 값은 단순한 문자열이 아니라 JSON 인코딩된 SecretWrapInfo 구조입니다. 기간 형식 문자열을 사용합니다.
  • dh_type (string: optional) — 지정하면 수행할 Diffie-Hellman 교환 유형, 즉 사용할 암호·곡선을 의미합니다. 현재는 curve25519만 지원됩니다.
  • dh_path (string: dh_type 설정 시 required) — auto-auth가 클라이언트의 초기 파라미터(예: curve25519 공개 키)를 읽을 경로입니다.
  • derive_key (bool: false) — 지정하면 계산된 공유 시크릿과 두 공개 키에서 HKDF-SHA256으로 키를 파생해 최종 암호화 키를 계산해 보안을 강화합니다. 하위 호환성에 신경 쓰지 않는다면 권장됩니다.
  • aad (string: optional) — 지정하면 토큰의 AES-GCM 암호화와 함께 사용할 추가 인증 데이터입니다. 직렬화된 데이터를 포함해 어떤 문자열이든 될 수 있습니다.
  • aad_env_var (string: optional) — 지정하면 AAD가 구성 파일의 값이 아니라 주어진 환경 변수에서 읽힙니다.
  • config (object: required) — 싱크 자체의 구성입니다. 각 싱크에 대한 정보는 사이드바를 참조하세요.

Auto-auth 예시

Auto-auth 구성 객체는 HCL과 JSON으로 지정할 때 두 가지 별도의 형태를 가집니다. 다음 예시는 두 형식의 차이를 명확히 하기 위한 것입니다.

싱크 (HCL 형식)

HCL 형식은 선택적 wrapping sinks {...} 객체와 함께 임의 개수의 싱크 객체를 정의할 수 있습니다.

참고

대응하는 JSON 형식은 모든 sink JSON 객체를 묶기 위해 "sinks" : [...] 배열을 반드시 지정해야 합니다.

// Other Vault Agent or Vault Proxy configuration blocks
// ...

auto_auth {
  method {
    type = "approle"

    config = {
      role_id_file_path = "/etc/vault/roleid"
      secret_id_file_path = "/etc/vault/secretid"
    }
  }

  sinks {
    sink {
      type = "file"

      config = {
        path = "/tmp/file-foo"
      }
    }
  }
}

다음 유효한 HCL은 wrapping sinks 객체를 생략하면서 여러 싱크를 지정합니다.

// Other Vault Agent or Vault Proxy configuration blocks
// ...

auto_auth {
  method {
    type = "approle"

    config = {
      role_id_file_path = "/etc/vault/roleid"
      secret_id_file_path = "/etc/vault/secretid"
    }
  }

  sink {
    type = "file"

    config = {
      path = "/tmp/file-foo"
    }
  }

  sink {
    type = "file"

    config = {
      path = "/tmp/file-bar"
    }
  }
}
싱크 (JSON 형식)

다음 JSON 구성은 임의 개수의 sink 객체를 묶는 sinks: [...] 배열이 필요함을 보여줍니다.

{
  "auto_auth" : {
    "method" : [
      {
        type = "approle"

        config = {
          role_id_file_path = "/etc/vault/roleid"
          secret_id_file_path = "/etc/vault/secretid"
        }
      }
    ],
    "sinks" : [
      {
        "sink" : {
          type = "file"

          config = {
            path = "/tmp/file-foo"
          }
        }
      }
    ]
  }
}

sinks 배열 안에 더 많은 sink 객체를 추가해 여러 싱크를 정의합니다.

{
  "auto_auth" : {
    "method" : [
      {
        type = "approle"

        config = {
          role_id_file_path = "/etc/vault/roleid"
          secret_id_file_path = "/etc/vault/secretid"
        }
      }
    ],
    "sinks" : [
      {
        "sink" : {
          type = "file"

          config = {
            path = "/tmp/file-foo"
          }
        }
      },
      {
        "sink" : {
          type = "file"

          config = {
            path = "/tmp/file-bar"
          }
        }
      }
    ]
  }
}

더 알아보기 (Learn more)