CI/CD
배포용 GitHub Actions 권한을 contents: write에서 줄인 기준
동작하던 배포 워크플로의 넓은 토큰 권한을, 실제 단계별 필요 권한으로 줄인 보안 설정 메모.
처음에는 넓은 권한으로 통과시켰다
배포 워크플로가 릴리스 노트를 만들지 못했을 때 contents: write를 넣으니 해결됐다. 하지만 실제로는 서버에 SSH로 배포만 하는 작업이었다. 나중에 action 하나가 바뀌어도 저장소 쓰기 권한을 갖는 구조가 마음에 걸렸다.
단계별로 토큰 사용 여부를 표시했다
체크아웃은 읽기, 빌드와 SSH 배포는 저장소 토큰의 쓰기 권한이 필요 없었다. GitHub API로 릴리스를 만드는 단계가 없다면 기본 권한을 읽기로 고정할 수 있다.
name: deploy
on:
push:
branches: [main]
permissions:
contents: read
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci && npm run build
- run: ./scripts/deploy.sh
env:
DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }}
실패한 곳은 권한을 되돌리기 전에 분리했다
권한을 줄인 뒤 실패하면 로그에서 어느 action이 GitHub API를 호출하는지 먼저 봤다. 패키지 배포라면 해당 job에만 packages: write를 둔다. 전체 workflow에 쓰기 권한을 복구하는 방식은 피했다.
publish:
permissions:
contents: read
packages: write
배포 비밀값도 실행 경로를 좁혔다
외부 pull request에서 비밀값이 필요한 배포 job이 실행되지 않도록 branch 조건을 확인했다. SSH 키는 로그에 출력하지 않고, 호스트 지문은 별도 secret보다 known_hosts에 고정했다.
끝으로 저장소 설정에서 기본 GITHUB_TOKEN 권한도 읽기 전용인지 확인했다. 권한은 문제가 생길 때 넓히는 것이 아니라, 필요한 작업이 확인될 때 한 칸씩 여는 편이 추적하기 쉬웠다.