AWS 인증 방식
AWS 인증 방식
참고: 이 엔진은 TLS 또는 서명 검증의 일부로 외부 X.509 인증서를 사용할 수 있어요. SHA-1을 사용하는 X.509 인증서에 대한 서명 검증은 구식화(Deprecated)되었고 Vault 1.12부터 워크어라운드 없이는 더 이상 사용할 수 없어요. 자세한 내용은 구식화 공지를 참고하세요.
aws 인증 방식은 IAM 프린시펄과 AWS EC2 인스턴스에 대한 Vault 토큰을 검색하는 자동화된 메커니즘을 제공해요. 대부분의 Vault 인증 방식과 달리 이 방식은 많은 상황에서 운영자가 보안에 민감한 크레덴셜(토큰, 사용자 이름/비밀번호, 클라이언트 인증서 등)을 수동으로 최초 배포하거나 프로비저닝할 필요가 없어요.
출처: 문서
본문
인증 워크플로 (Authentication workflow)
aws 인증 방식에는 iam과 ec2 두 가지 인증 유형이 있어요.
iam 방식에서는 AWS IAM 크레덴셜로 서명된 특별한 AWS 요청이 인증에 사용돼요. IAM 크레덴셜은 IAM 인스턴스 프로파일, Lambda 함수 등에 있는 AWS 인스턴스에 자동으로 공급되며, Vault가 클라이언트를 인증하는 데 사용할 수 있는 것은 바로 AWS가 이미 제공한 이 정보예요.
ec2 방식에서는 AWS가 신뢰할 수 있는 제3자로 취급되고 각 EC2 인스턴스를 고유하게 나타내는 암호학적으로 서명된 동적 메타데이터 정보가 인증에 사용돼요. 이 메타데이터 정보는 AWS가 모든 EC2 인스턴스에 자동으로 공급해요.
인증하려는 방식에 따라 Vault는 iam 또는 ec2 유형을 사용하려 하는지 결정해요. 각 방식마다 다른 인증 워크플로가 있으며, 각각 다른 사용 사례를 해결할 수 있어요.
참고:
ec2방식은iam방식을 구현하는 프리미티브가 AWS에서 지원되기 전에 구현되었어요.iam방식은 더 유연하고 접근 제어와 인증을 수행하는 모범 사례와 일치하므로 권장되는 접근 방식이에요. 두 인증 방식을 비교하는 것은 아래 섹션을 참고하세요.
사용법: Vault CLI 및 API 사용 예시는 인증 섹션을 참고하세요. 코드 예시 섹션은 AWS 인증 방식을 사용한 Vault 인증을 보여주는 코드 스니펫을 제공해요.
IAM 인증 방식 (IAM auth method)
AWS STS API에는 클라이언트의 신원을 검증할 수 있는 sts:GetCallerIdentity라는 메서드가 있어요. 클라이언트는 AWS Signature v4 알고리즘을 사용해 GetCallerIdentity query에 서명하고 Vault 서버로 보내요. GetCallerIdentity 요청에 서명하는 데 사용되는 크레덴셜은 EC2 인스턴스의 인스턴스 메타데이터 서비스나 AWS Lambda 함수 실행의 AWS 환경 변수에서 올 수 있어요. 이는 운영자가 먼저 어떤 종류의 신원 자료를 수동으로 프로비저닝할 필요를 없애요. 그러나 크레덴셜은 원칙적으로 AWS가 제공한 위치뿐 아니라 어디서든 올 수 있어요.
GetCallerIdentity query는 네 가지 정보 조각으로 구성돼요: 요청 URL, 요청 본문, 요청 헤더, 요청 메서드 — AWS 서명이 해당 필드에 대해 계산되기 때문이에요. Vault 서버는 이 정보를 사용해 query를 재구성하고 AWS STS 서비스로 전달해요. STS 서비스의 응답에 따라 서버는 클라이언트를 인증해요.
주목할 점은 클라이언트가 AWS STS API 엔드포인트에 직접 대화하기 위해 네트워크 수준 접근을 가질 필요가 없다는 거예요. 요청에 서명할 크레덴셜에만 접근하면 되거든요. 그러나 그것은 Vault 서버가 STS 엔드포인트에 요청을 보내려면 네트워크 수준 접근이 필요함을 의미해요.
각 서명된 AWS 요청에는 재생 공격의 위험을 완화하기 위해 현재 타임스탬프가 포함돼요. 또한 Vault는 X-Vault-AWS-IAM-Server-ID라는 추가 헤더가 있도록 요구할 수 있어요. 이는 다른 유형의 재생 공격(예: dev Vault 인스턴스에서 도난되어 prod Vault 인스턴스에 인증하는 데 사용되는 서명된 GetCallerIdentity 요청)을 완화하기 위한 것이에요. Vault는 이 헤더가 AWS 서명에 포함된 헤더 중 하나가 되도록 추가로 요구하며 해당 서명을 인증하는 데 AWS에 의존해요.
AWS API 엔드포인트는 서명된 GET과 POST 요청을 모두 지원하지만, 단순함을 위해 aws 인증 방식은 POST 요청만 지원해요. 또한 인증 정보를 포함하는 X-Amz-Credential, X-Amz-Signature, X-Amz-SignedHeaders GET query 파라미터가 있는 presigned 요청도 지원하지 않아요.
Amazon이 GetCallerIdentity 호출 주변에 어떤 종류의 인가도 포함하지 않는 것으로 보인다는 점도 주목하는 것이 중요해요. 예를 들어 크레덴셜에 모든 접근이 MFA 인증을 요구하는 IAM 정책이 있어도, MFA 인증되지 않은 크레덴셜(즉, GetSessionToken을 호출하고 MFA 코드를 공급해 검색되지 않은 원시 크레덴셜)은 여전히 이 방법을 사용해 Vault에 인증할 수 있어요. Vault에 인증하는 동안 IAM 프린시펄이 MFA 인증되도록 시행하는 것은 가능하지 않은 것 같아요.
EC2 인증 방식 (EC2 auth method)
Amazon EC2 인스턴스는 인스턴스를 설명하는 메타데이터에 접근할 수 있어요. Vault EC2 인증 방식은 이 메타데이터의 구성 요소를 활용해 인증하고 초기 Vault 토큰을 EC2 인스턴스에 분배해요. 데이터 흐름은 다음과 같아요:
- AWS EC2 인스턴스가 EC2 메타데이터 서비스에서 AWS Instance Identity Document를 가져와요. 데이터 자체 외에도 AWS는 데이터의 PKCS#7 서명을 제공하고, 서명을 검증하는 데 사용할 수 있는 공개 키(지역별)를 공개해요.
- AWS EC2 인스턴스가 PKCS#7 서명으로 Vault에 요청을 만들어요. PKCS#7 서명에는 Instance Identity Document가 포함돼요.
- Vault는 PKCS#7 문서의 서명을 검증해 정보가 AWS에 의해 정확하게 인증되었음을 확인해요. 이 과정은 문서 데이터의 유효성과 무결성을 모두 검증해요. 추가 보안 조치로 Vault는 공용 EC2 API 엔드포인트를 사용해 인스턴스가 현재 실행 중인지도 검증해요.
- 모든 단계가 성공하면 Vault는 초기 Vault 토큰을 EC2 인스턴스에 반환해요. 이 토큰은 인스턴스 메타데이터를 기반으로 구성된 모든 정책에 매핑돼요.
이 워크플로에는 이 문서의 뒷부분에 자세히 설명된 보안을 많거나 적게 제공하는 다양한 수정 사항이 있어요.
인가 워크플로 (Authorization workflow)
기본 작동 메커니즘은 역할별로 이뤄져요. 역할은 방식에 등록되고 역할이 생성된 후 변경할 수 없는 특정 인증 유형과 연결돼요. 역할은 허용된 정책 집합과 생성된 토큰의 최대 TTL 같은 다양한 선택적 제한과도 연결될 수 있어요. 각 역할은 로그인 중 충족되어야 하는 제약 조건으로 지정될 수 있어요. 이러한 제약 중 다수는 요구 값 목록을 받아들여요. 값 목록을 받아들이는 제약의 경우 로그인 과정에서 값 중 하나라도 일치하면 제약이 충족된 것으로 간주돼요. 예를 들어 지원되는 제약 중 하나는 AMI ID 목록에 대한 바인딩이에요. 특정 AMI 목록에 바인딩된 역할은 역할이 바인딩된 AMI 중 하나에 배포된 EC2 인스턴스에 의해서만 로그인에 사용될 수 있어요.
iam 인증 방식은 바인딩된 IAM 프린시펄 ARN을 지정할 수 있게 해요. Vault에 인증하는 클라이언트는 로그인하려는 역할에 바인딩된 ARN 중 하나와 일치하는 ARN을 가져야 해요. 바인딩된 ARN은 바인딩된 ARN 끝에 와일드카드를 지정할 수 있어요. 예를 들어 바인딩된 ARN이 arn:aws:iam::123456789012:*라면 AWS 계정 123456789012의 모든 프린시펄이 로그인할 수 있어요. 마찬가지로 arn:aws:iam::123456789012:role/*이라면 AWS 계정의 모든 IAM 역할이 로그인할 수 있어요. 와일드카드를 지정하려면 Vault에 iam:GetUser와 iam:GetRole 권한을 줘 전체 사용자 경로를 올바르게 해결해야 해요.
일반적으로 EC2 인스턴스에 특정한 역할 바인딩은 ec2 인증 방식이 로그인에 사용될 때만 확인되고, IAM 프린시펄에 특정한 바인딩은 iam 인증 방식이 로그인에 사용될 때만 확인돼요. 그러나 iam 방식에는 인증된 클라이언트에서 EC2 인스턴스 ID를 "유추(infer)"하고 그렇지 않으면 EC2 인스턴스에만 특정적으로 적용될 많은 바인딩을 적용할 수 있는 기능이 있어요.
많은 경우 조직은 부팅 후 구성 관리나 유사한 프로세스로 특수화되는 "시드 AMI"를 사용해요. 이 때문에 ec2 인증 유형을 사용할 때 방식의 역할 항목이 "역할 태그(role tag)"와도 연결될 수 있어요. 이러한 태그는 방식에 의해 생성되고 주어진 키의 태그 값으로 EC2 인스턴스에 배치돼요. 역할 태그는 역할에 설정된 파라미터를 추가로 제한하는 데 사용될 수 있지만 추가 권한을 부여하는 데는 사용될 수 없어요. AMI 바인드 제약이 있는 역할에 "역할 태그"가 활성화되어 있고, 로그인을 수행하는 EC2 인스턴스에 예상 태그가 없거나 인스턴스의 태그가 어떤 이유로 삭제되면 인증이 실패해요.
역할 태그는 적절한 API 접근이 있는 운영자가 마음대로 생성할 수 있어요. 이들은 방식 내에 저장된 역할별 키로 HMAC 서명되어, 방식이 발견된 역할 태그의 진위를 검증하고 변조되지 않았음을 보장할 수 있어요. 역할 태그가 의도된 머신 집합 밖에 배포된 것이 발견되면 역할 태그를 거부 목록(deny list)에 넣는 메커니즘도 있어요.
IAM 인증 유추 (IAM authentication inferences)
iam 인증 방식에서 일반적으로 Vault는 인증한 IAM 프린시펄, 즉 IAM 사용자 또는 역할을 봐요. 그러나 IAM 인스턴스 프로파일에 EC2 인스턴스가 있으면 Vault는 실제로 인스턴스의 인스턴스 ID를 볼 수 있고 그것이 EC2 인스턴스임을 "유추"할 수 있어요. 그러나 Vault가 그 유추를 하도록 구성하기 전에 알아야 할 중요한 보안 주의 사항이 있어요.
각 AWS IAM 역할은 역할에서 sts:AssumeRole을 호출하고 그 역할로 인증하는 데 사용할 수 있는 크레덴셜을 검색하도록 신뢰된 엔티티를 지정하는 "신뢰 정책(trust policy)"을 가져요. AssumeRole이 호출되면 AssumeRole을 호출하는 엔티티가 임의로 선택하는 RoleSessionName이라는 파라미터가 전달돼요. ARN이 arn:aws:iam::123456789012:role/MyRole인 역할이 있다면, 그 역할에 AssumeRole을 호출해 반환된 크레덴셜은 arn:aws:sts::123456789012:assumed-role/MyRole/RoleSessionName이며 여기서 RoleSessionName은 AssumeRole API 호출의 세션 이름이에요. Vault가 실제로 보는 것은 이 후자 값이에요.
인스턴스 프로파일에 EC2 인스턴스가 있으면 해당 역할의 신뢰 정책은 "Service": "ec2.amazonaws.com" 프린시펄이 AssumeRole을 호출하도록 신뢰된다고 지정해요. 이렇게 구성되면 EC2는 인스턴스의 인스턴스 ID에 해당하는 RoleSessionName으로 인스턴스를 대신해 AssumeRole을 호출해요. 따라서 인스턴스 프로파일의 EC2 인스턴스가 iam 인증 방식으로 Vault에 인증할 때 Vault가 보는 값에서 인스턴스 ID를 추출하는 것이 가능해요. 이를 "유추(inferencing)"라고 해요. Vault는 역할별로 호출자가 EC2 인스턴스임을 유추하도록 구성될 수 있고, 그렇다면 EC2 인스턴스에 특정적으로 적용되는 추가 바인딩 — 대부분 ec2 인증 방식에서 사용할 수 있는 바인딩 — 을 적용할 수 있어요.
그러나 AWS 서비스 이외의 엔티티가 역할에서 AssumeRole을 호출하도록 허용되면 그 엔티티가 인스턴스의 인스턴스 ID를 전달해 Vault에 인스턴스를 스푸핑할 수 있다는 점을 주목하는 것이 매우 중요해요. 이는 또한 역할의 신뢰 정책을 수정할 수 있는 사람(iam:UpdateAssumeRolePolicy 등으로)은 인스턴스를 스푸핑할 수도 있음을 의미해요. 이것이 우려되지만 유추를 활용하고 싶다면 역할에서 AssumeRole을 호출할 수 있는 사람과 역할에서 UpdateAssumeRolePolicy를 호출할 수 있는 사람을 엄격히 제한하고, AssumeRole과 UpdateAssumeRolePolicy 호출에 대한 CloudTrail 로그를 모니터링해야 해요. 이러한 주의 사항은 모두 유추 없이 iam 인증 방식을 사용하는 경우에도 동일하게 적용돼요. 요점은 Vault가 유추에 대해 철저한 보장을 제공할 수 없고, 운영자가 자체 AWS 제어와 사용 사례에 따라 유추 구성을 하는 것이 적절한지 결정하는 것이라는 점이에요.
인증 유형 혼합 (Mixing authentication types)
Vault는 ec2 인증 방식이나 iam 인증 방식을 구성하도록 허용하지만 두 인증 방식을 모두 허용하지는 않아요. 또한 assumed roles는 지원되지 않으며 Vault는 역할의 선택된 인증 유형으로 시행할 수 없는 제한을 시행하는 것을 방지해요. 실제로 이것이 작동하는 몇 가지 예시:
- 바인딩된 AMI ID로 ec2 인증 유형의 역할을 구성해요. 클라이언트는 iam 인증 유형으로 로그인할 수 없어요.
- 바인딩된 IAM 프린시펄 ARN으로 iam 인증 유형의 역할을 구성해요. 클라이언트는 ec2 인증 방식으로 로그인할 수 없어요.
- iam 인증 유형의 역할을 구성하고 추가로 유추를 구성해요. 바인딩된 AMI ID와 바인딩된 IAM 프린시펄 ARN이 있어요. 클라이언트는 iam 방식으로 로그인해야 하며, RoleSessionName은 Vault가 볼 수 있는 유효한 인스턴스 ID여야 하고, 인스턴스는 바인딩된 AMI ID에서 와야 해요.
IAM과 EC2 방식의 비교 (Comparison of the IAM and EC2 methods)
iam과 ec2 인증 방식은 둘 다 일부 유형의 AWS 엔티티를 Vault에 인증한다는 점에서 유사하고 다소 겹치는 기능을 제공해요. 여기 iam 방식이 ec2보다 선호되는 이유를 보여주는 몇 가지 비교가 있어요.
- 인증되는 엔티티의 유형:
- ec2 인증 방식은 AWS EC2 인스턴스만 인증하며 특정 AMI의 EC2 인스턴스, 특정 인스턴스 프로파일의 EC2 인스턴스, 특수화된 태그 값이 있는 EC2 인스턴스(role_tag 기능을 통해)로 접근을 제한하는 등 EC2 인스턴스를 처리하도록 특화되어 있어요.
- iam 인증 방식은 AWS IAM 프린시펄을 인증해요. 여기에는 IAM 사용자, 다른 계정에서 가정한 IAM 역할, IAM 역할로 실행되는 AWS Lambdas, IAM 인스턴스 프로파일로 실행되는 EC2 인스턴스까지 포함될 수 있어요. 그러나 더 일반화된 IAM 프린시펄을 인증하므로 이 방식은 유추 없이 주어진 IAM 프린시펄에 바인딩하는 것 이상의 세밀한 제어를 제공하지 않아요.
- 엔티티가 인증되는 방법:
- ec2 인증 방식은 인스턴스에 대한 메타데이터를 포함하는 암호학적으로 서명된 문서인 EC2 인스턴스 아이덴티티 문서를 사용해 인스턴스를 인증해요. 이 문서는 비교적 드물게 변경되므로 Vault는 클라이언트 nonce, 역할 태그, 인스턴스 마이그레이션 등 재생 공격을 완화하는 많은 다른 구성을 추가해요. 인스턴스 아이덴티티 문서가 AWS에 의해 서명되므로 EC2 인스턴스에서 왔다는 강한 보장이 있어요.
- iam 인증 방식은 클라이언트가 특별히 서명된 AWS API 요청을 제공해 인증하며, 방식은 그 요청을 AWS에 전달해 서명을 검증하고 누가 만들었는지 Vault에 알려줘요. 실제 비밀(즉, AWS 시크릿 액세스 키)은 네트워크를 통해 전송되지 않고, AWS 서명 알고리즘은 요청을 15분 후 자동으로 만료시켜 재생 공격에 대한 단순하고 견고한 보호를 제공해요. 그러나 유추의 사용은 ec2 인증 메커니즘에 비해 크레덴셜이 IAM 인스턴스 프로파일의 EC2 인스턴스에서 왔다는 더 약한 보장을 제공해요.
- ec2 인증 방식에서 사용되는 인스턴스 아이덴티티 문서는 상대적으로 정적이어서 도난될 가능성이 더 높지만 스푸핑하기는 더 어려워요. 반면 IAM 인스턴스 프로파일의 EC2 인스턴스 크레덴셜은 동적이고 수명이 짧아 도난될 가능성이 낮지만 EC2 인스턴스에서 왔을 수 있는 크레덴셜을 스푸핑하기는 더 쉬워요.
- 특정 사용 사례:
- EC2 인스턴스가 아닌 엔티티가 있으면, 예: IAM 사용자, IAM 역할의 Lambdas, AdRoll의 Hologram을 사용하는 개발자 노트북 — iam 인증 방식을 사용해야 해요.
- EC2 인스턴스가 있으면 두 인증 방식 중 하나를 사용할 수 있어요. 주어진 EC2 인스턴스의 인스턴스 프로파일 이상의 더 세밀한 필터링이 필요하면(예: 인스턴스가 시작된 AMI 기반 필터링) ec2 인증 방식을 사용하거나, EC2 인스턴스와 연결된 인스턴스 프로파일을 변경해 인증하려는 각 Vault 역할마다 고유한 IAM 역할을 갖도록 하거나, 유추를 사용해야 해요. 역할 태그를 사용해야 한다면 ec2 인증 방식을 사용해야 해요.
권장 Vault IAM 정책 (Recommended Vault IAM policy)
이는 AWS 인증 방식에 필요한 권장 IAM 정책을 지정해요. AWS 인증과 시크릿 방식에 동일한 크레덴셜을 사용한다면, AWS 시크릿 방식이 요구하는 추가 권한을 추가해야 해요.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ec2:DescribeInstances",
"iam:GetInstanceProfile",
"iam:GetUser",
"iam:GetRole"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": ["sts:AssumeRole"],
"Resource": ["arn:aws:iam::<AccountId>:role/<VaultRole>"]
},
{
"Sid": "ManageOwnAccessKeys",
"Effect": "Allow",
"Action": [
"iam:CreateAccessKey",
"iam:DeleteAccessKey",
"iam:GetAccessKeyLastUsed",
"iam:GetUser",
"iam:ListAccessKeys",
"iam:UpdateAccessKey"
],
"Resource": "arn:aws:iam::*:user/${aws:username}"
}
]
}
Vault가 이러한 권한 각각을 사용해야 하는 시나리오는 다음과 같아요. Vault가 AWS API 호출을 할 수 있는 모든 시나리오의 철저한 목록이 아니라 왜 필요한지 설명하기 위한 것이에요.
ec2:DescribeInstances—ec2인증 방식을 사용하거나ec2_instance엔티티 유형을 유추할 때 EC2 인스턴스가 역할의 바인딩 요구 사항을 충족하는지 검증하는 데 필요해요.iam:GetInstanceProfile—ec2인증 방식에bound_iam_role_arn이 있을 때 사용돼요. Vault는 인스턴스 프로파일에 어떤 IAM 역할이 연결되어 있는지 결정해야 해요.iam:GetUser와iam:GetRole— iam 인증 방식을 사용하고 IAM 사용자 또는 역할 프린시펄에 바인딩할 때 AWS IAM 고유 식별자를 결정하거나 바인딩된 ARN에 와일드카드를 사용해 사용자 또는 역할의 전체 ARN을 해결할 때 사용돼요.sts:AssumeRole스탠자는 크로스 계정 접근을 사용할 때 필요해요. 지정된Resource는 크로스 계정 접근을 구성한 모든 역할의 목록이어야 하며, 각 역할에는 이 IAM 정책이 연결되어야 해요(sts:AssumeRole문 제외).ManageOwnAccessKeys스탠자는 Vault를 정적 크레덴셜로 구성하고 루트 크레덴셜 회전 API 호출로 이 크레덴셜을 회전하려 할 때 필요해요.
일정 기반 루트 크레덴셜 회전 (Schedule-based root credential rotation)
적절한 Vault Enterprise 라이선스가 필요해요.
rotation_schedule 필드를 사용해 AWS 인증 엔진의 루트 크레덴셜에 대한 일정 기반 자동 크레덴셜 회전을 구성해요. 예를 들어 다음 명령은 매주 토요일 자정(00:00)에 회전이 발생하도록 설정해요:
$ vault write auth/aws/config/client \
...
rotation_schedule="0 * * * SAT"
...
예정된 루트 크레덴셜 회전은 예정된 회전이 발생하도록 허용되는 rotation_window를 설정할 수도 있어요. Vault는 창이 만료되면 크레덴셜 회전 시도를 중지해요. 예를 들어 다음 명령은 Vault에게 토요일 자정에 크레덴셜을 회전하되 1시간 범위 내에서만 그렇게 하라고 지시해요. Vault가 1:00까지 크레덴셜을 회전할 수 없으면 다음 예정된 회전까지 회전 시도를 중지해요.
$ vault write auth/aws/config/client \
...
rotation_window="1h" \
rotation_schedule="0 * * * SAT"
...
disable_automated_rotation을 true로 설정해 루트 회전을 일시적으로 비활성화할 수 있어요. 이 필드를 설정하면 false로 재설정될 때까지 루트 크레덴셜의 모든 회전을 방지해요. rotation_period를 사용하면 disable_automated_rotation 설정 또한 크레덴셜 TTL을 재설정해요.
AWS Auth 엔진의 루트 크레덴셜 회전에 대한 자세한 내용은 루트 크레덴셜 회전 API 문서를 참고하세요.
플러그인 Workload Identity Federation (WIF)
이 기능에는 Vault Enterprise(새 탭에서 열림)가 필요해요.
AWS 인증 엔진은 플러그인 WIF 워크플로를 지원하고 플러그인 아이덴티티 토큰이라는 신원 소스를 가져요. 플러그인 아이덴티티 토큰은 Vault의 플러그인 아이덴티티 토큰 발급자가 내부적으로 서명한 JWT예요.
Vault와 AWS 사이에 workload identity federation을 통한 신뢰 관계가 구성되어 있으면 인증 엔진은 아이덴티티 토큰을 작업을 수행하는 데 필요한 수명이 짧은 STS 크레덴셜로 교환할 수 있어요.
아이덴티티 토큰을 STS 크레덴셜로 교환하면 AWS 인증 엔진이 민감한 IAM 보안 크레덴셜에 대한 명시적 접근을 구성하지 않고 작동할 수 있어요.
인증 엔진이 플러그인 WIF를 사용하도록 구성하려면:
- Vault openid-configuration 및 공용 JWKS API가 AWS에서 네트워크로 도달 가능한지 확인하세요. Vault API 노출을 제한해야 한다면 API 프록시나 게이트웨이를 권장해요.
- AWS에 IAM OIDC 아이덴티티 프로바이더를 만드세요.
- 프로바이더 URL은
/.well-known/openid-configuration접미사를 제거한 [Vault 플러그인 아이덴티티 토큰 발급자]를 가리켜야 해요. 예:https://host:port/v1/identity/oidc/plugins. - 플러그인 아이덴티티 토큰의 수신자를 오디언스로 고유하게 식별하세요. AWS에서 수신자는 아이덴티티 프로바이더예요. 구성된 각 아이덴티티 프로바이더마다 고유하므로 프로바이더 URL의
host:port/v1/identity/oidc/plugins부분을 수신자로 사용하는 것을 권장해요. - IAM OIDC 아이덴티티 프로바이더에 사용된 것과 동일한 오디언스로 AWS에 웹 아이덴티티 역할을 만드세요.
- IAM OIDC 오디언스 값과 웹 아이덴티티 역할 ARN으로 AWS 인증 엔진을 구성하세요.
$ vault write auth/aws/config/client \
identity_token_audience="vault.example/v1/identity/oidc/plugins" \
role_arn="arn:aws:iam::123456789123:role/example-web-identity-role"
이제 인증 엔진이 구성 크레덴셜에 플러그인 WIF를 사용할 수 있어요. 기본적으로 WIF 크레덴셜은 1시간의 time-to-live를 가지며 만료 시 자동으로 갱신돼요.
플러그인 WIF와 연관된 필드에 대한 자세한 내용은 API 문서를 참고하세요.
클라이언트 nonce (Client nonce)
참고: 이것은 ec2 인증 방식에만 적용돼요.
의도하지 않은 당사자가 아이덴티티 문서의 PKCS#7 서명(기본적으로 EC2 인스턴스에 접근하는 모든 프로세스와 사용자에게 제공됨)에 접근하면 인스턴스를 사칭하고 Vault 토큰을 가져올 수 있어요. 방식은 문서의 PKCS#7 서명을 제시하는 첫 번째 클라이언트가 인증되도록 하고 나머지는 거부하는 TOFU(Trust On First Use) 메커니즘을 사용해 이 문제를 해결해요. 이 설계의 중요한 속성은 무단 접근 감지예요: 의도하지 않은 당사자가 인증하면 의도한 클라이언트는 인증할 수 없고 조사를 위해 경고를 제기할 수 있어요.
첫 번째 로그인 중 방식은 인증한 인스턴스 ID를 accesslist에 저장해요. 방식의 작동 방법 중 하나는 역할의 disallow_reauthentication 옵션을 사용해 접근 목록에 포함된 인스턴스 ID에 대한 어떤 인증 시도도 금지하는 것이며, 이는 인스턴스가 한 번만 로그인할 수 있음을 의미해요. 그러나 이것은 토큰 회전에 대한 결과를 가져오는데, 토큰이 만료되면 후속 인증 시도가 실패할 것임을 의미하기 때문이에요. 기본적으로 이 방식에서는 재인증이 활성화되어 있으며 등록된 역할의 disallow_reauthentication 파라미터로 끌 수 있어요.
기본 작동 방식에서 방식은 첫 번째 인증 시도 중에 auth metadata의 일부로 고유 nonce를 반환해요. 클라이언트는 후속 로그인 시도를 위해 이 nonce를 제시해야 하며 방식의 identity-accesslist 항목에 캐시된 nonce와 일치해야 해요. 원래 클라이언트만 nonce를 알므로 원래 클라이언트만 재인증할 수 있어요. (이것이 이것이 거부 목록이 아니라 accesslist인 이유예요. 기본적으로 재인증이 허용된 클라이언트를 추적하는 것이지 허용되지 않은 클라이언트를 추적하는 것이 아니에요.) 클라이언트는 첫 번째 로그인 시도에서도 nonce를 제공할 수 있으며, 이 경우 제공된 nonce는 캐시된 identity-accesslist 항목에 묶여요. 이 경우 강력한 nonce 값을 사용하는 것이 권장돼요.
nonce에 대해 올바르게 동작하는 것은 클라이언트의 몫이에요. nonce를 디스크에 저장하면 재부팅에도 살아남을 수 있지만 인스턴스의 다른 사용자나 애플리케이션에 접근을 줄 수도 있어요. 클라이언트 nonce가 실제로 고유한지 확인하는 것도 운영자의 몫이에요. nonce 공유는 nonce 값의 손상으로 공격자가 EC2 인스턴스에 접근해 인스턴스의 합법적인 클라이언트를 모방할 수 있게 합니다. 이것이 nonce가 인스턴스당 단일 인증만을 위해 방식 측에서 비활성화될 수 있는 이유예요. 어떤 경우(예: ASG 사용 시) 인스턴스는 어차피 불변이고 단일 부팅이므로, 높은 최대 TTL과 함께 재인증이 필요하지 않을 수 있어요(필요하면 인스턴스를 종료하고 ASG가 새 것을 시작하도록 하면 돼요).
두 경우 모두 항목은 인스턴스 ID로 accesslist에서 제거될 수 있어, nonce를 분실(또는 사용하지 않음)하고 운영자가 과정을 승인하면 클라이언트가 재인증할 수 있어요.
한 가지 더: EC2 인스턴스와 함께 사용되는 OS/배포에서 사용 가능하다면 서명된 PKCS#7 메타데이터에 대한 접근을 방화벽으로 제한해 접근이 필요한 일치하는 사용자에게만 접근 가능하도록 하는 것도 나쁘지 않아요.
백엔드가 생성하고 인증 응답과 함께 반환하는 클라이언트 nonce는 평문으로 감사 로그에 기록될 거예요. 이것이 바람직하지 않다면 클라이언트는 로그인 엔드포인트에 사용자 지정 nonce를 공급할 수 있으며, 이 nonce는 반환되지 않으므로 감사 로그에 기록되지 않아요.
고급 옵션 및 주의 사항 (Advanced options and caveats)
역할 태그를 통한 동적 정책 관리 (Dynamic management of policies via role tags)
참고: 이것은 ec2 인증 방식 또는 유추가 사용되는 iam 인증 방식에만 적용돼요.
인스턴스가 담당하는 역할에 따라 사용자 지정된 정책 집합을 가져야 한다면 role_tag 옵션을 사용해 주어진 역할에 대해 인스턴스에 설정할 태그를 제공할 수 있어요. 이 옵션이 설정되면 로그인 중 PKCS#7 서명과 인스턴스 상태 검증과 함께 방식은 인스턴스에 연결된 구성된 키와 함께 특정 태그의 값을 query해요. 태그는 역할에 설정된 권한의 부분 집합을 나타내는 정보를 보유하며 해당 특정 인스턴스에 대한 역할의 권한 집합을 추가로 제한하는 데 사용돼요.
role_tag는 auth/aws/role/<role>/tag 엔드포인트로 만들 수 있으며 불변(immutable)이에요. 태그에 있는 정보는 SHA256 해시되고 HMAC 보호돼요. HMAC할 역할별 키는 방식에서만 유지돼요. 이는 적대적 운영자가 EC2 인스턴스에 설정할 때 태그를 수정해 권한을 상승시키는 것을 방지해요.
역할에서 'role_tag' 옵션이 활성화되면 인스턴스에 역할 태그가 있어야 해요. EC2 인스턴스에서 태그를 찾지 못하면 인증이 실패해요. 이는 인스턴스의 권한이 태그가 없거나 태그가 제거되어 상승되지 않도록 보장하기 위한 것이에요. 역할 태그 생성이 정책 구성 요소를 지정하지 않으면 클라이언트는 역할에 설정된 허용 정책을 상속해요. 역할 태그 생성이 정책 구성 요소를 지정하지만 정책이 없으면 토큰은 default 정책만 포함해요. 기본적으로 이 정책은 기존 토큰의 조작(폐기, 갱신, 조회)과 cubbyhole에 대한 접근만 허용해요. 이는 인스턴스가 데이터 저장을 위한 안전한 "스크래치 공간"(토큰의 cubbyhole을 통해)에 접근하되 Vault에서 제공하거나 상주하는 다른 리소스에 대한 접근을 부여하지 않는 데 유용할 수 있어요.
분실된 클라이언트 nonce 처리 (Handling lost client nonces)
참고: 이것은 ec2 인증 방식에만 적용돼요.
EC2 인스턴스가 클라이언트 nonce를 분실하면(재부팅, 클라이언트 중지/시작 등으로) 후속 로그인 시도가 성공하지 않아요. 클라이언트 nonce가 분실되면 일반적으로 유일한 옵션은 방식의 identity accesslist에서 인스턴스 ID에 해당하는 항목을 삭제하는 것이에요. 이는 auth/aws/identity-accesslist/<instance_id> 엔드포인트로 할 수 있어요. 이렇게 하면 다음 로그인 요청 중 방식이 새 클라이언트 nonce를 받아들일 수 있어요.
특정 상황에서 유용한 또 다른 설정이 있어요. 인스턴스가 생성 시 호스트에 배치되면 인스턴스 아이덴티티 문서에 pendingTime 값을 부여받아요(안타깝게도 AWS 문서는 이 옵션을 다루지 않아요). 인스턴스가 중지되고 시작되면 pendingTime 값이 업데이트돼요(그러나 재부팅에는 적용되지 않아요).
방식은 역할별로 설정되는 allow_instance_migration 옵션으로 이를 활용할 수 있어요. 이 옵션이 활성화되면 클라이언트 nonce가 저장된 nonce와 일치하지 않으면 인스턴스 아이덴티티 문서의 pendingTime 값이 확인돼요. 저장된 pendingTime 값보다 새로우면 방식은 클라이언트가 중지/시작되었다고 가정하고 클라이언트가 성공적으로 로그인하도록 허용하며, 새 nonce를 해당 클라이언트의 유효한 nonce로 저장해요. 이는 본질적으로 인스턴스가 중지되고 시작될 때마다 TOFU 메커니즘을 다시 시작하므로 주의해서 사용해야 해요. 초기 인증과 마찬가지로 합법적인 클라이언트는 인증이 거부되면 경고할 방법이 있어야 해요(또는 로그를 기반으로 경고가 트리거되어야 해요).
안타깝게도 allow_instance_migration은 중지/시작 작업 동안에만 도움이 돼요. 현재 메타데이터는 재부팅 중 이 자동 동작을 허용하는 방법을 제공하지 않아요. 필요한 메타데이터를 사용할 수 있게 되면 방식이 업데이트될 거예요.
allow_instance_migration 옵션은 역할별로 설정되고 역할 태그에도 지정될 수 있어요. 역할 태그는 동작만 제한할 수 있으므로 역할에서 옵션이 false로 설정되면 역할 태그의 true 값이 적용돼요. 그러나 역할에서 옵션이 true로 설정되면 역할 태그의 설정 값은 효과가 없어요.
재인증 비활성화 (Disabling reauthentication)
참고: 이것은 ec2 인증 방식에만 적용돼요.
특정 조직의 아키텍처에서 클라이언트가 수명이 긴 Vault 토큰을 가져오고 토큰을 회전할 필요가 없다면 해당 인스턴스 ID에 대한 모든 미래 로그인을 비활성화할 수 있어요. disallow_reauthentication 옵션이 설정되면 인스턴스당 하나의 로그인만 허용돼요. 의도한 클라이언트가 로그인 중 토큰을 성공적으로 검색하면 다른 엔티티가 토큰을 하이재킹하지 않는다는 확신을 가질 수 있어요.
disallow_reauthentication 옵션이 활성화되면 클라이언트는 로그인 중 nonce를 공급하지 않도록 선택할 수 있습니다(공급해도 오류는 아니며 nonce가 단순히 무시됩니다). 재인증은 기본적으로 활성화되어 있음을 주의하세요. 단일 로그인만 원한다면 disallow_reauthentication을 역할 또는 역할 태그에 명시적으로 설정해야 해요.
disallow_reauthentication 옵션은 역할별로 설정되고 역할 태그에도 지정될 수 있어요. 역할 태그는 동작만 제한할 수 있으므로 역할에서 옵션이 false로 설정되면 역할 태그의 true 값이 적용돼요. 그러나 역할에서 옵션이 true로 설정되면 역할 태그의 설정 값은 효과가 없어요.
역할 태그 거부 목록 (Deny listing role tags)
참고: 이것은 ec2 인증 방식 또는 유추가 사용되는 iam 인증 방식에만 적용돼요.
역할 태그는 특정 역할에 묶여 있지만 방식은 그 역할을 사용하는 인스턴스가 특정 역할 태그를 가져야 하는지 제어할 수 없어요. 그것은 순전히 운영자의 몫이에요. 역할 태그는 제한적일 뿐이지만(태그는 역할에 설정된 것보다 권한을 상승시킬 수 없음), 역할 태그가 잘못 사용된 것이 발견되고 관리자가 역할 태그가 더 이상 효과가 없도록 하려면 auth/aws/roletag-denylist/<role_tag> 엔드포인트를 통해 역할 태그를 deny list에 넣을 수 있어요. 이것은 이미 발급된 토큰을 무효화하지는 않으며 거부 목록에 넣은 태그가 연결된 인스턴스의 추가 로그인 요청만 차단한다는 점을 주의하세요.
denylist 및 accesslist 항목의 만료 시간과 정리 (Expiration times and tidying)
identity accesslist와 역할 태그 denylist의 만료된 항목은 자동으로 삭제돼요. 이 두 목록의 항목은 역할에 설정된 max_ttl, 역할 태그에 설정된 max_ttl, 그리고 방식 마운트의 max_ttl 값이라는 세 가지 요인에 의해 동적으로 결정되는 만료 시간을 포함해요. 이 세 값 중 가장 작은 값이 발급된 토큰의 최대 TTL을 결정하고 그에 상응해 이 항목들의 만료 시간으로 설정돼요.
auth/aws/tidy/identity-accesslist와 auth/aws/tidy/roletag-denylist 엔드포인트는 이 목록에 있는 항목을 정리하기 위해 제공돼요. 이 엔드포인트는 안전 버퍼를 정의할 수 있게 해요. 이에 따라 항목은 만료되었을 뿐만 아니라 안전 버퍼가 지시한 시간만큼 만료가 지나야 실제로 제거돼요.
만료된 항목의 자동 삭제는 방식의 주기적 함수에 의해 수행돼요. 이 함수는 접근 목록 역할 태그와 접근 목록 아이덴티티의 정리를 모두 수행해요. 주기적 정리는 기본적으로 활성화되고 72시간의 안전 버퍼를 가지며, 정리 작업이 수행되는 시점으로부터 72시간 전에 만료된 항목만 삭제돼요. 이것은 config/tidy/roletag-denylist와 config/tidy/identity-accesslist 엔드포인트로 구성될 수 있어요.
다양한 공용 인증서 (Varying public certificates)
참고: 이것은 ec2 인증 방식에만 적용돼요.
PKCS#7 서명을 검증하는 데 사용되는 공개 키를 포함하는 AWS 공용 인증서는 AWS 지역마다 달라요. 대부분의 AWS 지역을 포함하는 기본 AWS 공용 인증서는 Vault에 이미 포함되어 있으며 추가할 필요가 없어요. 기본 공용 인증서로 PKCS#7 서명을 검증할 수 없는 인스턴스는 여기에서 찾을 수 있는 다른 공용 인증서를 auth/aws/config/certificate/<cert_name> 엔드포인트를 통해 등록할 수 있어요.
매달린 토큰 (Dangling tokens)
EC2 인스턴스는 방식으로 인증한 후 Vault 토큰을 얻어요. 그 후 인스턴스가 어떤 이유로든 종료되거나 내려가면 방식은 그런 이벤트를 인지하지 못해요. 발급된 토큰은 만료될 때까지 계속 유효해요. 인스턴스가 토큰을 제때 갱신하지 못하면 토큰은 수명보다 일찍 만료될 가능성이 높아요.
크로스 계정 접근 (Cross account access)
Vault가 다른 계정의 IAM 프린시펄과 EC2 인스턴스를 인증할 수 있도록 Vault는 AWS STS(보안 토큰 서비스)를 사용해 다른 계정의 AWS IAM 역할을 가정하는 것을 지원해요. 각 대상 AWS 계정 ID에 대해 auth/aws/config/sts/<account_id>로 Vault가 가정할 IAM 역할을 구성하고, Vault는 그 역할 가정에서 얻은 크레덴셜을 사용해 대상 계정의 IAM 프린시펄과 EC2 인스턴스를 검증해요.
Vault가 실행 중인 계정(즉, 마스터 계정)은 원격 계정에서 가정되는 IAM 역할의 신뢰된 엔티티로 나열되어야 해요. 역할 자체는 추가 sts:AssumeRole 권한이 필요하지 않다는 점만 제외하고 권장 Vault IAM 정책에 지정된 권한을 허용해야 해요.
또한 마스터 계정에서 Vault는 가정될 IAM 역할에 대해 sts:AssumeRole 작업이 부여되어야 해요.
HCP(HashiCorp Cloud Platform)에서 Vault Enterprise를 실행한다면 크로스 계정 접근을 활성화하는 데 필요한 클러스터 ID는 지원팀에 문의하세요.
AWS 인스턴스 메타데이터 타임아웃 (AWS instance metadata timeout)
Vault 1.4 이상에 영향.
Vault가 EC2 인스턴스에서 인스턴스 메타데이터 서비스를 사용할 때마다(예: 인스턴스 프로파일에서 크레덴셜 얻기) 인스턴스 메타데이터 서비스 v2(IMDSv2) 도입으로 지연이 있을 수 있어요. Vault가 사용하는 AWS SDK는 먼저 IMDSv2에 연결을 시도하고, 타임아웃되면 v1으로 폴백해요. Vault 1.4에서 이 타임아웃은 최대 2분이 걸릴 수 있어요. Vault 1.5.5 이상에서는 이 수정으로 최대 2초가 걸릴 수 있어요: #10133.
타임아웃은 Vault와 IMDSv2 사이에 프록시가 있고 인스턴스 홉 제한이 Vault와 IMDSv2 사이의 "홉" 수보다 작게 설정된 상황에서 발생해요. 예를 들어 인스턴스 홉 제한이 1로 설정된 EC2 인스턴스의 docker에서 Vault가 실행 중이면 AWS SDK 클라이언트는 IMDSv2에 연결을 시도하고, 타임아웃되고, docker와 IMDS 사이의 추가 네트워크 홉 때문에 IMDSv1로 폴백해요.
타임아웃 동작을 피하려면 홉 제한이 기본 EC2 인스턴스에서 조정될 수 있어요. docker 예시에서 홉 제한을 2로 설정하면 Vault의 AWS SDK가 지연 없이 IMDSv2에 연결할 수 있어요.
참고: AWS는 계정 또는 개별 인스턴스 수준에서 IMDSv2를 시행할 수 있으며, 이는 IMDSv1 접근을 완전히 비활성화해요.
Vault AWS SDK는 AWS가 지원할 때 IMDSv2를 자동으로 사용하므로 인증 섹션에서 예시 PKCS#7 서명 가져오기 명령에 IMDSv2 토큰 흐름을 사용해요.
자세한 내용은 IMDSv2 시행에 대한 AWS 블로그 게시물을 참고하세요.
인증 (Authentication)
경고: Vault 또는 다음 예시 코드를 추가 네트워크 홉(컨테이너, 프록시) 뒤에서 실행할 계획이라면 시작하기 전에 AWS 인스턴스 메타데이터 타임아웃 섹션을 참고하세요.
CLI를 통해
Vault에서 AWS EC2 인증 활성화
$ vault auth enable aws
AWS API 호출에 필요한 크레덴셜 구성
지정하지 않으면 Vault는 표준 환경 변수(AWS_ACCESS_KEY_ID와 AWS_SECRET_ACCESS_KEY) 또는 가능하면 IAM EC2 인스턴스 역할 크레덴셜을 사용하려 시도해요.
크레덴셜이 매핑되는 IAM 계정 또는 역할은 ec2:DescribeInstances 작업을 허용해야 해요. 또한 IAM 역할 바인딩이 사용되면(아래 bound_iam_role_arn 참고) iam:GetInstanceProfile도 허용되어야 해요.
Vault에 IAM 보안 크레덴셜을 제공하려면 Vault 플러그인 workload identity federation(WIF)을 권장해요.
$ vault write auth/aws/config/client \
secret_key=vCtSM8ZUEQ3mOFVlYPBQkf2sO6F/W7a5TVzrl3Oj \
access_key=VKIAJBRHKH6EVTTNXDHA
$ vault auth/aws/config/client \
identity_token_audience="vault.example/v1/identity/oidc/plugins" \
role_arn="arn:aws:iam::123456789123:role/example-web-identity-role"
역할에 정책 구성
$ vault write auth/aws/role/dev-role auth_type=ec2 bound_ami_id=ami-fce3c696 policies=prod,dev max_ttl=500h
$ vault write auth/aws/role/dev-role-iam auth_type=iam \
bound_iam_principal_arn=arn:aws:iam::123456789012:role/MyRole policies=prod,dev max_ttl=500h
필수 X-Vault-AWS-IAM-Server-ID 헤더 구성 (권장)
$ vault write auth/aws/config/client iam_server_id_header_value=vault.example.com
로그인 작업 수행
EC2 인증 방식의 경우 IMDSv2 토큰 흐름을 사용해 PKCS#7 서명을 가져와요.
두 단계 접근을 사용하면 토큰 흐름이 IMDSv1 접근이 비활성화된 인스턴스를 포함한 모든 EC2 인스턴스에서 작동해요.
$ TOKEN=`curl -s -X PUT http://169.254.169.254/latest/api/token -H "X-aws-ec2-metadata-token-ttl-seconds: 600"` && \
SIGNATURE=$(curl \
-H "X-aws-ec2-metadata-token: $TOKEN" \
-s http://169.254.169.254/latest/dynamic/instance-identity/rsa2048 | \
tr -d '\n'
)
그런 다음 로그인 엔드포인트에 서명을 설정해요:
$ vault write auth/aws/login role=dev-role \
pkcs7=$SIGNATURE
참고: Vault는 SHA-1 서명이 있는 X.509 인증서를 지원하지 않아요. AWS
/rsa2048서명 엔드포인트 크레덴셜을 사용한다면pkcs7로그인 흐름을 사용해야 해요.
iam 인증 방식의 경우 서명된 요청 생성은 비표준 작업이에요. Vault CLI는 이를 생성하는 것을 지원해요:
$ vault login -method=aws header_value=vault.example.com role=dev-role-iam
이것은 AWS SDK가 크레덴셜을 검색하는 표준 위치(환경 변수, ~/.aws/credentials, IAM 인스턴스 프로파일, 또는 ECS 작업 역할, 그 순서로)에 AWS 크레덴셜이 구성되어 있다고 가정해요. 이 위치 중 어느 곳에도 IAM 크레덴셜이 없으면 명령줄에서 명시적으로 전달할 수 있어요(권장되지는 않지만), 해당되지 않으면 aws_security_token을 생략해요.
$ vault login -method=aws header_value=vault.example.com role=dev-role-iam \
aws_access_key_id=<access_key> \
aws_secret_access_key=<secret_key> \
aws_security_token=<security_token>
사용되는 지역은 기본적으로 us-east-1이지만 사용자 지정 지역을 지정할 수 있어요:
$ vault login -method=aws region=us-west-2 role=dev-role-iam
지역이 auto로 지정되면 Vault CLI는 앞서 설명한 표준 AWS 크레덴셜 우선 순위에 따라 지역을 결정해요. 어떤 방법을 사용하든 지정된 지역이 사용 중인 STS 엔드포인트의 지역과 일치하는지 확인하세요.
참고: AWS GovCloud를 사용하고 sts_endpoint와 sts_region 역할 파라미터를 us-gov-west-1 / us-gov-east-1로 설정한다면 로그인 요청에 region=us-gov-west-1 같은 일치 값을 가진 region 인수를 포함해야 해요.
login 방법에 필요한 요청 값을 생성하는 방법의 예시는 vault cli 소스 코드에서 찾을 수 있어요. 이와 같은 접근을 사용해 요청 파라미터를 생성하고 login 메서드에 전달할 수 있어요:
$ vault write auth/aws/login role=dev-role-iam \
iam_http_request_method=POST \
iam_request_url=aHR0cHM6Ly9zdHMuYW1hem9uYXdzLmNvbS8= \
iam_request_body=QWN0aW9uPUdldENhbGxlcklkZW50aXR5JlZlcnNpb249MjAxMS0wNi0xNQ== \
iam_request_headers=eyJDb2...JdfQ==
API를 통해
Vault에서 AWS 인증 활성화
curl -X POST -H "X-Vault-Token:123" "http://127.0.0.1:8200/v1/sys/auth/aws" -d '{"type":"aws"}'
AWS API 호출에 필요한 크레덴셜 구성
curl -X POST -H "X-Vault-Token:123" "http://127.0.0.1:8200/v1/auth/aws/config/client" -d '{"access_key":"VKIAJBRHKH6EVTTNXDHA", "secret_key":"vCtSM8ZUEQ3mOFVlYPBQkf2sO6F/W7a5TVzrl3Oj"}'
역할에 정책 구성
curl -X POST -H "X-Vault-Token:123" "http://127.0.0.1:8200/v1/auth/aws/role/dev-role" -d '{"bound_ami_id":"ami-fce3c696","policies":"prod,dev","max_ttl":"500h"}'
curl -X POST -H "X-Vault-Token:123" "http://127.0.0.1:8200/v1/auth/aws/role/dev-role-iam" -d '{"auth_type":"iam","policies":"prod,dev","max_ttl":"500h","bound_iam_principal_arn":"arn:aws:iam::123456789012:role/MyRole"}'
로그인 작업 수행
TOKEN=`curl -s -X PUT http://169.254.169.254/latest/api/token -H "X-aws-ec2-metadata-token-ttl-seconds: 600"` && \
SIGNATURE=$(curl -H "X-aws-ec2-metadata-token: $TOKEN" -s http://169.254.169.254/latest/dynamic/instance-identity/rsa2048 | tr -d '\n')
curl -X POST "http://127.0.0.1:8200/v1/auth/aws/login" \
export TOKEN=$(curl -s -X PUT http://169.254.169.254/latest/api/token -H "X-aws-ec2-metadata-token-ttl-seconds: 600") && \
export SIGNATURE=$(curl -H "X-aws-ec2-metadata-token: $TOKEN" -s http://169.254.169.254/latest/dynamic/instance-identity/rsa2048 | tr -d '\n')
curl -X POST "http://127.0.0.1:8200/v1/auth/aws/login" -d '{"role":"dev", "iam_http_request_method": "POST", "iam_request_url": "aHR0cHM6Ly9zdHMuYW1hem9uYXdzLmNvbS8=", "iam_request_body": "QWN0aW9uPUdldENhbGxlcklkZW50aXR5JlZlcnNpb249MjAxMS0wNi0xNQ==", "iam_request_headers": "eyJDb2...JdfQ==" }'
응답은 JSON 형식이에요. 예:
{
"auth": {
"renewable": true,
"lease_duration": 72000,
"metadata": {
"role_tag_max_ttl": "0s",
"role": "ami-f083709d",
"region": "us-east-1",
"nonce": "5defbf9e-a8f9-3063-bdfc-54b7a42a1f95",
"instance_id": "i-a832f734",
"ami_id": "ami-f083709d"
},
"policies": [
"default",
"dev",
"prod"
],
"accessor": "5cd96cd1-58b7-2904-5519-75ddf957ec06",
"client_token": "150fc858-2402-49c9-56a5-f4b57f2c8ff1"
},
"warnings": null,
"wrap_info": null,
"data": null,
"lease_duration": 0,
"renewable": false,
"lease_id": "",
"request_id": "d7d50c06-56b8-37f4-606c-ccdc87a1ee4c"
}
API
AWS 인증 방식은 완전한 HTTP API를 제공해요. 자세한 내용은 AWS Auth API 문서를 참고하세요.
Terraform
Vault Terraform 프로바이더로 AWS 인증 리소스를 프로그래밍 방식으로 관리할 수 있어요. 자세한 내용은 Terraform Registry 문서를 참고하세요.
- AWS 인증 방식 아이덴티티 구성 리소스
- AWS 인증 방식 클라이언트 리소스
- AWS 인증 방식 인증서 리소스
- AWS 인증 방식 역할 리소스
- AWS 인증 방식 STS 역할 리소스
- AWS 인증 방식 아이덴티티 화이트리스트 리소스
- AWS 인증 방식 역할 태그 리소스
- AWS 인증 방식 역할 태그 블랙리스트 리소스
- AWS 인증 방식 로그인 리소스
코드 예시 (Code example)
다음 예시는 AWS (IAM) 인증 방식으로 Vault에 인증하는 것을 보여줘요. (Go/C# 코드)
Go:
package main
import (
"context"
"fmt"
vault "github.com/hashicorp/vault/api"
auth "github.com/hashicorp/vault/api/auth/aws"
)
// Fetches a key-value secret (kv-v2) after authenticating to Vault via AWS IAM,
// one of two auth methods used to authenticate with AWS (the other is EC2 auth).
func getSecretWithAWSAuthIAM() (string, error) {
config := vault.DefaultConfig() // modify for more granular configuration
client, err := vault.NewClient(config)
if err != nil {
return "", fmt.Errorf("unable to initialize Vault client: %w", err)
}
awsAuth, err := auth.NewAWSAuth(
auth.WithRole("dev-role-iam"), // if not provided, Vault will fall back on looking for a role with the IAM role name if you're using the iam auth type, or the EC2 instance's AMI id if using the ec2 auth type
)
if err != nil {
return "", fmt.Errorf("unable to initialize AWS auth method: %w", err)
}
authInfo, err := client.Auth().Login(context.Background(), awsAuth)
if err != nil {
return "", fmt.Errorf("unable to login to AWS auth method: %w", err)
}
if authInfo == nil {
return "", fmt.Errorf("no auth info was returned after login")
}
// get secret from the default mount path for KV v2 in dev mode, "secret"
secret, err := client.KVv2("secret").Get(context.Background(), "creds")
if err != nil {
return "", fmt.Errorf("unable to read secret: %w", err)
}
// data map can contain more than one key-value pair,
// in this case we're just grabbing one of them
value, ok := secret.Data["password"].(string)
if !ok {
return "", fmt.Errorf("value type assertion failed: %T %#v", secret.Data["password"], secret.Data["password"])
}
return value, nil
}
C#:
using System;
using System.Text;
using Amazon.Runtime;
using Amazon.Runtime.Internal;
using Amazon.Runtime.Internal.Auth;
using Amazon.Runtime.Internal.Util;
using Amazon.SecurityToken;
using Amazon.SecurityToken.Model;
using Amazon.SecurityToken.Model.Internal.MarshallTransformations;
using Newtonsoft.Json;
using VaultSharp;
using VaultSharp.V1.AuthMethods;
using VaultSharp.V1.AuthMethods.AWS;
using VaultSharp.V1.Commons;
using VaultSharp.V1.SecretsEngines.AWS;
namespace Examples
{
public class AwsAuthExample
{
/// <summary>
/// Fetches a key-value secret (kv-v2) after authenticating to Vault via AWS IAM,
/// one of two auth methods used to authenticate with AWS (the other is EC2 auth).
/// </summary>
public string GetSecretAWSAuthIAM()
{
var vaultAddr = Environment.GetEnvironmentVariable("VAULT_ADDR");
if(String.IsNullOrEmpty(vaultAddr))
{
throw new System.ArgumentNullException("Vault Address");
}
var roleName = Environment.GetEnvironmentVariable("VAULT_ROLE");
if(String.IsNullOrEmpty(roleName))
{
throw new System.ArgumentNullException("Vault Role Name");
}
var amazonSecurityTokenServiceConfig = new AmazonSecurityTokenServiceConfig();
// Initialize BasicAWS Credentials w/ an accessKey and secretKey
Amazon.Runtime.AWSCredentials awsCredentials = new BasicAWSCredentials(accessKey: Environment.GetEnvironmentVariable("AWS_ACCESS_KEY_ID"),
secretKey: Environment.GetEnvironmentVariable("AWS_SECRET_ACCESS_KEY"));
// Construct the IAM Request and add necessary headers
var iamRequest = GetCallerIdentityRequestMarshaller.Instance.Marshall(new GetCallerIdentityRequest());
iamRequest.Endpoint = new Uri(amazonSecurityTokenServiceConfig.DetermineServiceURL());
iamRequest.ResourcePath = "/";
iamRequest.Headers.Add("User-Agent", "some-agent");
iamRequest.Headers.Add("X-Amz-Security-Token", awsCredentials.GetCredentials().Token);
iamRequest.Headers.Add("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");
new AWS4Signer().Sign(iamRequest, amazonSecurityTokenServiceConfig, new RequestMetrics(), awsCredentials.GetCredentials().AccessKey, awsCredentials.GetCredentials().SecretKey);
var iamSTSRequestHeaders = iamRequest.Headers;
// Convert headers to Base64 encoded version
var base64EncodedIamRequestHeaders = Convert.ToBase64String(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(iamSTSRequestHeaders)));
IAuthMethodInfo authMethod = new IAMAWSAuthMethodInfo(roleName: roleName, requestHeaders: base64EncodedIamRequestHeaders);
var vaultClientSettings = new VaultClientSettings(vaultAddr, authMethod);
IVaultClient vaultClient = new VaultClient(vaultClientSettings);
// We can retrieve the secret from the VaultClient object
Secret<SecretData> kv2Secret = null;
kv2Secret = vaultClient.V1.Secrets.KeyValue.V2.ReadSecretAsync(path: "/creds").Result;
var password = kv2Secret.Data.Data["password"];
return password.ToString();
}
}
}
더 알아보기 (Learn more)
- AWS 인증 방식 전체 API는 AWS Auth API 문서를 참고하세요.
- 정적 크레덴셜을 위한 Vault 플러그인 WIF 설정은 플러그인 workload identity federation 문서를 참고하세요.