[References]
https://aws.amazon.com/ko/blogs/security/use-iam-roles-to-connect-github-actions-to-actions-in-aws/
If you configure an OpenID Connect (OIDC) identity provider (IdP) inside an AWS account, you can use IAM roles and short-term credentials, which removes the need for IAM user access keys.
안녕하세요, Sean 입니다. IAM User 의 long term credential 을 이용하여 서드파티에 권한을 부여하는 방식은 권장되지 않습니다. 자격 증명이 외부로 유출되면 그 위험이 크기 때문입니다. 따라서 이 글에선 STS를 기반한 임시 자격 증명을 사용하여 IAM role 을 assume 하는 방법에 대해 알아봅니다.
그림과 같은 환경을 구축합니다. 저는 실습을 위한 환경을 Terraform 을 이용하여 구성하였으므로, Terraform 에서 리소스를 생성하겠습니다. 실습을 진행하는 과정은 다음과 같습니다:
- AWS에 OIDC IdP 등록
- IAM role 생성
- Github Actions 워크플로우 파일 구성
- CloudTrail audit log 확인
AWS에 OIDC IdP 등록
가장 먼저 Identity Provider(IdP) 를 생성합니다. aws_iam_openid_connect_provider 리소스는 IAM OpenID Connect provider 를 제공합니다.
resource "aws_iam_openid_connect_provider" "github_actions_idp" {
url = "https://token.actions.githubusercontent.com"
client_id_list = ["sts.amazonaws.com"]
thumbprint_list = [var.github_thumbprint]
}
variable "github_thumbprint" {
description = "Github OIDC thumbprint"
type = string
}
- url: Provider URL 입니다. iss claim 과 대응하는 값입니다.
- client_id_list: audiences 로도 불리는 값으로, 저희는 IdP를 통해 AWS STS 가 호출되도록 허용할 것이므로 “sts.amazonaws.com” 를 입력합니다.
- thumbprint_list: CA 로부터 발급받는 서명입니다. 이 필드를 채워넣기 위해선 아래의 certificate thumbprint 가져오기 과정이 필요합니다.
(선택) certificate thumbprint 가져오기
2024년 12월 12일 업데이트: 더이상 thumbprint값을 필수적으로 요구하지 않습니다. 해당 필드를 삭제하셔도 될 것 같습니다.
현재로써는 thumbprint 입력이 필수입니다. 따라서 이를 외부에서 가져오는 과정이 필요합니다. 이 단계는 개인적으로 없어져야 하는 단계라고 생각합니다. 해당 단계에 대한 제 의견을 포스팅 해두었습니다. 공식 가이드를 따라가고자 하신다면 다음을 참고하세요.
해당 작업이 번거롭다면
번거로운 작업을 넘어가고자 하신다면, github_thumbprint variable 에 다음과 같이 입력하세요:
variable "github_thumbprint" {
description = "Github OIDC thumbprint"
type = string
default = "1b511abead59c6ce207077c0bf0e0043b1382612"
}
직접 thumbprint 가져오고 등록하기
우선 OpenSSL 을 설치해야 합니다. MacOS 를 사용하시는 분이라면 OpenSSL 이 내장되어 있습니다. terminal 에서 다음을 입력하여 설치가 되어있는 것을 확인합니다:
openssl --version
Windows, 혹은 다른 환경의 유저라면 다음을 참고하세요.
터미널에서 다음 명령어를 입력해 출력을 확인합니다:
openssl s_client -servername token.actions.githubusercontent.com -showcerts -connect token.actions.githubusercontent.com:443
출력 중 다음과 같은 Certificate 필드를 찾습니다. 여러개라면 마지막 것을 확인합니다.
-----BEGIN CERTIFICATE-----
MIIEyDCCA7CgAwIBAgIQDPW9BitWAvR6uFAsI8zwZjANBgkqhkiG9w0BAQsFADBh
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
...
chDYABPPTHPbqjc1qCmBaZx2vN4Ye5DUys/vZwP9BFohFrH/6j/f3IL16/RZkiMN
JCqVJUzKoZHm1Lesh3Sz8W2jmdv51b2EQJ8HmA==
-----END CERTIFICATE-----
certificate.crt 파일을 만든 후 Cerfiticate 내용을 붙여넣습니다.
mkdir test
cd test
vi certificate.crt
(paste content)
이후 다음 명령어를 입력합니다:
openssl x509 -in certificate.crt -fingerprint -sha1 -noout | sed 's/sha1 Fingerprint=//; s/://g'
다음과 같은 결과물을 얻을 수 있습니다:
1A611ABEAD59C6CE207027S0BF8E0043BA3N2168
먼 길 오셨습니다. 이제 이 값을 테라폼의 thumbprint_list에 입력합니다.
IAM role 생성 및 권한 할당
이제 IAM role 을 생성하겠습니다.
resource "aws_iam_role" "github_actions_role" {
name = "GitHubActions-AssumeRoleWithAction"
description = "IAM role to be assumed by GitHub Actions"
assume_role_policy = jsonencode({
Version = "2012-10-17",
Statement = [
{
Effect = "Allow",
Principal = {
Federated = aws_iam_openid_connect_provider.github_actions_idp.arn
},
Action = "sts:AssumeRoleWithWebIdentity",
Condition = {
StringEquals = {
"token.actions.githubusercontent.com:sub" = "repo:${var.github_repository_name}:ref:refs/heads/${var.github_branch_name}",
"token.actions.githubusercontent.com:aud" = "sts.amazonaws.com"
}
}
}
]
})
}
variable "github_repository_name" {
description = "Github repository name for Github Actions"
type = string
default = "Repick-official/repick-server-v2" # 여러분의 깃허브 정보에 맞게 변경하세요
}
variable "github_branch_name" {
description = "Github branch name for Github Actions"
type = string
default = "fix/github-actions" # 여러분의 깃허브 정보에 맞게 변경하세요
}
output "github_actions_role_arn" {
description = "The ARN of the IAM role for Github Actions"
value = aws_iam_role.github_actions_role.arn # 나중에 쓰이니 적용 후 복사해두세요
}
- Federated: 위에서 정의한 github_actions_idp 리소스의 ARN 을 입력합니다.
- Condition: 조건에서 저희가 사용하길 원하는 깃허브 레포지토리와 브랜치 이름을 정의합니다.
- output 블록에서 생성한 IAM role 의 ARN 을 확인합니다.
이제 모든 테라폼 리소스 정의를 마쳤다면 적용합니다!
terraform apply
Github Actions 워크플로우 파일 구성
워크플로우 파일을 구성해봅시다. 간단한 예제와 함께합니다:
on:
push:
branches: [ main ]
env:
AWS_REGION : "ap-northeast-2" # Change to reflect your Region
# Permission can be added at job level or workflow level
permissions:
id-token: write # This is required for requesting the JWT
contents: read # This is required for actions/checkout
jobs:
AssumeRoleAndCallIdentity:
runs-on: ubuntu-latest
steps:
- name: Git clone the repository
uses: actions/checkout@v3
- name: configure aws credentials
uses: aws-actions/configure-aws-credentials@v1.7.0
with:
role-to-assume: arn:aws:iam::111122223333:role/GitHubAction-AssumeRoleWithAction # github_actions_role_arn 값을 가져옵니다.
role-session-name: GitHub_to_AWS_via_FederatedOIDC
aws-region: ${{ env.AWS_REGION }}
# Hello from AWS: WhoAmI
- name: Sts GetCallerIdentity
run: |
aws sts get-caller-identity
워크플로우에 대한 설명은 다음과 같습니다:
- OIDC IdP 를 통하여 IAM role 을 assume 합니다.
- aws sts get-caller-identity 를 호출하여 UserId, Account, Arn 을 가져옵니다. WhoAmI 라고 생각하시면 됩니다.
push 후 정상적인 작동을 확인합니다:
CloudTrail audit log 확인
거의 다 왔군요. 이제 CloutTrail 을 통한 audit 이 가능합니다. AWS 매니지먼트 콘솔에서 다음의 작업을 수행합니다:
- CloudTrail 서비스로 이동합니다.
- 좌측의 Event History 를 선택합니다.
- 검색창의 Lookup attributes 를 Event source 로 선택합니다.
- sts.amazonaws.com 를 입력합니다.
GetCallerIdentity 와 AssumeRoleWithWebIdentity 이벤트를 확인할 수 있습니다.
- GetCallerIdentity 이벤트는 워크플로우의 Hello from AWS: WhoAmI 스텝에서 생긴 이벤트입니다.
- AssumeRoleWithWebIdentity 는 Github Actions 가 GitHubAction-AssumeRoleWithAction IAM role 을 assume 할 때 생기는 이벤트입니다.
assume 하는 role 의 권한을 조정하며 최소 권한 원칙에 따라 action 을 실행할 권한을 부여하세요. 임시 자격 증명을 기반하여 기존의 방식보다 더 안전한 권한 관리를 달성하신 것을 축하합니다. ㅎㅎ
'AWS' 카테고리의 다른 글
AWS re:Post web crawler with AWS Serverless services (0) | 2024.08.08 |
---|---|
Terraform의 aws_iam_openid_connect_provider에 관하여 (0) | 2024.07.18 |
[AWS IAM] Identity Federation & Cognito Basics (0) | 2024.07.16 |
[AWS IAM] STS Basics (0) | 2024.07.15 |
[AWS CloudWatch] CloudWatch Agent와 stress를 통해 스왑 메모리 사용량 지표 추출하기 (0) | 2024.07.09 |