구현 목적
이 포스팅은 React로 구현된 정적 웹 파일들(.js, .html, .css)을 AWS S3 버킷을 통해 배포하는 간단한 예시이다. 여기에 GitHub Action을 활용해 CI/CD 파이프라이닝을 구축해보는 과정을 담았다.
Requirements
- create-react-app으로 만들어진 초기 버전의 React 앱
- 위 프로젝트의 Github Repository
- AWS 계정
AWS S3
버킷 생성
AWS S3 콘솔(https://console.aws.amazon.com/s3/)에서 S3 버킷을 생성하고자 한다. 콘솔 화면에서 버킷 만들기를 클릭한다.
버킷 이름을 입력하고, 원하는 AWS 리전을 선택한다. 너무 먼 리전을 선택할 경우, 응답속도가 지연될 수 있고, 다른 AWS리소스들과 리전이 다를 경우, 각 리소스들과의 호환이 어려울 수 있다. 이를 유의해서 리전을 선택하도록 한다. 이후, 버킷 만들기를 클릭해 버킷을 생성한다.
웹 사이트 호스팅을 위한 설정
생성된 버킷을 클릭하면 아래와 같은 화면을 볼 수 있다. S3 버킷의 객체가 호스팅되기 위해서 몇가지 설정이 필요하다.
퍼블릭 액세스 차단 해제
권한 탭 > 퍼블릭 액세스 차단(버킷 설정)을 변경할 것이다. 편집을 눌러 모든 퍼블릭 액세스 차단을 해제한다.
정책 추가
권한 탭 > 버킷 정책에 객체에 대한 액세스 권한을 추가 할 것이다.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-awsbucket-for-react-app/*"
}
]
}
"Resource"에는 생성한 버킷 ARN을 추가하고 마지막에 /*(와일드 카드)를 추가해주면 된다. 이는 객체 내부의 모든 파일에 대한 액세스를 허용하게 된다.
정적 웹 호스팅 설정
속성 탭 > 정적 웹 사이트 호스팅을 편집해 호스팅을 위한 설정을 할 것이다. 정적 웹 사이트 호스팅을 활성화하고, 호스팅 유형을 정적 웹 사이트 호스팅으로 설정한다. 인덱스 문서에 인덱스 문서 이름을 입력한다. cra로 생성된 인덱스 문서 이름은 'index.html'이므로 이를 입력하도록 한다.
GitHub OIDC
GitHub Action을 본격적으로 적용하기 전에, AWS 리소스 접근에 필요한 몇가지 설정이 있다. 리소스에 접근하기 위해선 인증 절차를 거치고, 인증서를 발급받아야 한다. 이는 'aws-actions/configure-aws-credentials'에서 추천하는 GitHub OIDC를 이용하도록 한다.
OIDC란?
OpenID Connect의 약자로, IdP(Identity Provider)가 자격 검증을 마치고 토큰을 발급해주는 방식의 OAuth2.0 프레임워크 기반 인증 표준이다. 이 토큰이 JSON형식이라 JWT(JSON Web Tokens)이라고 부른다. 여러 웹 사이트에서 지원하는 facebook 로그인, google 로그인, 카카오톡 로그인 등이 대표적인 예시이다.
- https://openid.net/developers/how-connect-works/
- https://docs.github.com/ko/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect
- https://www.samsungsds.com/kr/insights/oidc.html
AWS IAM에 IdP 등록하기
IAM 콘솔(https://console.aws.amazon.com/iam/)에서 새로운 자격 증명 공급자를 추가하도록 한다. 액세스 관리 > 자격 증명 공급자 창에서 공급자 추가를 클릭한다.
공급자 유형을 OpenID Connect으로 선택한다. 공급자 URL에 https://token.actions.githubusercontent.com을, 대상에 sts.ap-northeast-2.amazonaws.com 또는 sts.amazonaws.com을 입력한다.
https://token.actions.githubusercontent.com
sts.ap-northeast-2.amazonaws.com
AWS IAM에 역할 등록하기
IAM 콘솔(https://console.aws.amazon.com/iam/)에서 새로운 역할을 추가하도록 한다. 액세스 관리 > 역할 창에서 역할 만들기를 클릭한다.
신뢰할 수 있는 엔터티 선택
신뢰할 수 있는 엔터티 유형에 사용자 지정 신뢰 정책을 선택하고, 아래의 스크립트를 붙여넣는다.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:AssumeRoleWithWebIdentity",
"Principal": {
"Federated": "arn:aws:iam::111122223333:oidc-provider/token.actions.githubusercontent.com"
},
"Condition": {
"StringEquals": {
"token.actions.githubusercontent.com:sub": "repo:magae1/cd-react-on-s3:ref:refs/heads/main",
"token.actions.githubusercontent.com:aud": "sts.ap-northeast-2.amazonaws.com"
}
}
}
]
}
"Federated"에는 생성했던 자격 증명 공급자의 ARN을 입력한다. "Condition" 중 "~:sub"에는 "repo:<조직명>/<레포지토리명>:ref:refs/heads/<branch명>"형태로, "~:aud"에는 생성했던 공급자의 대상을 입력한다.
권한 추가
이 역할에는 S3에 대한 모든 접근 권한을 주도록 한다. 권한 정책에서 AmazonS3FullAccess 정책을 선택한다.
이름 지정, 검토 및 생성
역할 이름에 원하는 역할명을 입력하고, 역할 생성을 클릭한다.
GitHub Action
workflow 정의
원하는 GitHub Action을 사용하기 위해선 Workflow를 정의해야 한다. Workflow들은 .github/workflows 디렉토리 안 YAML 파일들에 저장된다.
# ./github/workflows/aws-s3.yml
name: AWS S3 workflow
on:
push:
branches: [ main ]
env:
BUCKET_NAME : "my-awsbucket-for-react-app"
AWS_REGION : "ap-northeast-2"
permissions:
id-token: write # This is required for requesting the JWT
contents: read # This is required for actions/checkout
jobs:
S3PackageUpload:
runs-on: ubuntu-latest
steps:
- name: Git clone the repository
uses: actions/checkout@v3
- name: Set up nodejs
uses: actions/setup-node@v3
with:
node-version: 20.5.0
- name: Install dependencies
run: npm ci
- name: Build React app
run: npm run build
- name: configure aws credentials
uses: aws-actions/configure-aws-credentials@v2
with:
role-to-assume: arn:aws:iam::111122223333:role/my-gitaction-practice
aws-region: ${{ env.AWS_REGION }}
audience: sts.ap-northeast-2.amazonaws.com
- name: Copy index.html to s3
run: |
aws s3 sync ./build/ s3://${{ env.BUCKET_NAME }}/
최종 확인
workflow가 종료되고, S3 버킷을 확인해보면 객체에 빌드된 파일들이 저장돼있다. 이후, 정적 웹 사이트 엔드포인트 url로 접속해보면 사이트가 정상적으로 호스팅된다.
참고자료
- https://docs.aws.amazon.com/ko_kr/AmazonS3/latest/userguide/WebsiteHosting.html
- https://docs.github.com/ko/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services
- https://medium.com/boca-code/deploy-your-react-app-to-aws-s3-bucket-and-with-ci-cd-1c9ce03023c2
- https://docs.aws.amazon.com/cli/latest/reference/s3/index.html
- https://backbencher.dev/deploy-react-app-amazon-s3-github-actions