Traffine I/O

Bahasa Indonesia

2022-09-05

Memperbarui Gambar AWS ECR Menggunakan OIDC dengan GitHub Actions

Memperbarui Gambar AWS ECR Menggunakan OIDC dengan GitHub Actions

Dalam siklus pengembangan perangkat lunak modern, CI/CD (Continuous Integration/Continuous Deployment) memainkan peran penting. Salah satu aspek penting dari proses ini adalah mengelola implementasi gambar Docker ke repositori berbasis cloud, seperti Amazon Elastic Container Registry (ECR). Artikel ini akan menjelaskan proses mengirimkan gambar ECR menggunakan GitHub Actions dan protokol OpenID Connect (OIDC).

Apa itu OIDC

Aliran kerja GitHub Actions digunakan untuk mengakses penyedia cloud seperti AWS, Google Cloud Platform (GCP), atau Azure untuk melakukan implementasi perangkat lunak atau memanfaatkan layanan cloud. Untuk memfasilitasi komunikasi yang aman antara platform-platform berbeda ini, digunakanlah OpenID Connect (OIDC).

OIDC adalah lapisan identitas yang memverifikasi identitas pengguna akhir berdasarkan autentikasi yang dilakukan oleh server otorisasi. Hal ini memungkinkan penerbitan kredensial selama eksekusi aliran kerja, yang dapat digunakan untuk otentikasi saat implementasi ke cloud. Kredensial ini bersifat sementara dan mengurangi risiko penyalahgunaan jika bocor, dibandingkan dengan penggunaan kunci akses permanen.

Per September 2022, penyedia cloud yang mendukung OIDC meliputi:

  • AWS
  • Azure
  • GCP
  • HashiCorp Vault

Kode Sumber

Struktur Direktori

Struktur direktori proyek kita diatur sebagai berikut:

.
├── .github/workflows/deploy-ecr.yml
├── Dockerfile
└── terraform
    ├── variables.tf
    ├── iam.tf
    └── ecr.tf

Terraform

Kode berikut mendefinisikan penyedia OIDC, peran, dan repositori ECR.

variables.tf
variable "env" {
  default = "dev"
}

variable "github_provider" {
  default = "arn:aws:iam::<AWS_ACCOUNT_ID>:oidc-provider/token.actions.githubusercontent.com"
}

variable "aws_account_id" {
  default = "123456789012"
}

variable "github_org" {
  default = "mycompany-inc"
}

variable "github_repo" {
  default = "my-repo"
}
iam.tf
resource "aws_iam_openid_connect_provider" "main" {
  url             = "https://token.actions.githubusercontent.com"
  client_id_list  = ["sts.amazonaws.com"]
  thumbprint_list = ["6938fd4d98bab03faadb97b34396831e3780aea1"]
}

resource "aws_iam_role" "github_actions" {
  name = "${var.env}-github-actions"
  assume_role_policy = jsonencode(
    {
      "Version" = "2012-10-17"
      "Statement" = [
        {
          "Principal" : {
            "Federated" : "arn:aws:iam::${var.aws_account_id}:oidc-provider/token.actions.githubusercontent.com"
          },
          "Action" : [
            "sts:AssumeRoleWithWebIdentity",
          ],
          "Effect" = "Allow",
          "Condition" : {
            "StringLike" : {
              "token.actions.githubusercontent.com:aud" : "sts.amazonaws.com",
              "token.actions.githubusercontent.com:sub" : "repo:${var.github_org}/${var.github_repo}:*"
            }
          },
        }
      ]
    }
  )
}

resource "aws_iam_policy" "github_actions_policy" {
  name = "${var.env}-github-actions-policy"
  policy = jsonencode(
    {
      "Version" : "2012-10-17",
      "Statement" : [
        {
          "Sid" : "ImageUploader",
          "Action" : [
            "ecr:GetDownloadUrlForLayer",
            "ecr:BatchCheckLayerAvailability",
            "ecr:PutImage",
            "ecr:InitiateLayerUpload",
            "ecr:UploadLayerPart",
            "ecr:CompleteLayerUpload",
            "ecr:GetAuthorizationToken",
          ],
          "Effect"   = "Allow",
          "Resource" = "*"
        }
      ],
  })
}

resource "aws_iam_role_policy_attachment" "github_actions_ecr_policy_attachment" {
  policy_arn = aws_iam_policy.github_actions_policy.arn
  role       = aws_iam_role.github_actions.id
}

resource "aws_iam_role_policy_attachment" "github_actions_ecs_full_access" {
  policy_arn = "arn:aws:iam::aws:policy/AmazonECS_FullAccess"
  role       = aws_iam_role.github_actions.id
}
ecr.tf
resource "aws_ecr_repository" "main" {
  name = "my-ecr-repo"
}

Github Actions

Daftarkan rahasia berikut dari Setting > New repository secret di GitHub.

  • AWS_GA_ROLE_ARN (ARN dari aws_iam_role.github_actions yang didefinisikan dalam Terraform)
  • AWS_ECR_REPO_NAME (nama repositori ECR yang didefinisikan dalam Terraform)

Secret setting

Dan tulis file YML berikut dalam .github/workflows/deploy.yml di repositori tersebut.

.github/workflows/deploy-ecr.yml
name: Deploy ECR Image

on:
  push:
    branches:
      - develop

permissions:
  id-token: write
  contents: read

jobs:
  build-and-push:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-region: ap-northeast-1
          role-to-assume: ${{ secrets.AWS_GA_ROLE_ARN }}

      - name: Login to Amazon ECR
        id: login-ecr
        uses: aws-actions/amazon-ecr-login@v1

      - name: Build and push Docker image to Amazon ECR
        env:
          ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
          ECR_REPOSITORY: ${{ secrets.AWS_ECR_REPO_NAME }}
        run: |
          docker build -t $ECR_REGISTRY/$ECR_REPOSITORY . --no-cache
          docker push $ECR_REGISTRY/$ECR_REPOSITORY

References

https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect
https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services
https://docs.aws.amazon.com/AmazonECR/latest/userguide/image-push.html
https://github.blog/changelog/2022-01-13-github-actions-update-on-oidc-based-deployments-to-aws/

Ryusei Kakujo

researchgatelinkedingithub

Focusing on data science for mobility

Bench Press 100kg!