跳转至

Deploy Vue3 to S3

IAM User, Role, Policy

設置順序是:

  • 創建 S3 Policy (為了有存S3的權限)

  • 創建 IAM Role 並附加該 Policy (為了限制特定角色能擁能擁有存S3的權限)

  • 設置信任關係,允許特定 User 擔任此 Role (為了確認該用戶是否具備該角色的權限)

這兩個方向的權限設置必須同時滿足,用戶才能成功擔任角色。這是 AWS 的一種安全機制,確保角色和用戶雙方都同意這種權限委派關係。

User

name: github-actions-user

添加 assume-role-policy 這個政策

AWS CLI確認該 User 相關權限

~ $ aws iam list-attached-user-policies --user-name github-actions-user
{
    "AttachedPolicies": [
        {
            "PolicyName": "assume-role-policy",
            "PolicyArn": "arn:aws:iam::my-id:policy/assume-role-policy"
        }
    ]
}

Role

name: GitHubActionsS3Role

Trust relationships

新版的 AWS SDK 和 GitHub Actions 用到了 OIDC 驗證中的 session tagging 功能

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "GitHubActionsS3RoleTaskV2",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::my-id:user/github-actions-user"
            },
            "Action": [
                "sts:AssumeRole",
                "sts:TagSession"
            ]
        }
    ]
}

增加角色的最大會話持續時間

aws iam update-role --role-name GitHubActionsS3Role --max-session-duration 3600

Policy

  1. name: assume-role-policy

GitHub Action使用 aws s3 sync 時可能還需要 s3:ListBuckets3:DeleteObject(因為有 --delete 選項)

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:PutObjectAcl",
                "s3:GetObject",
                "s3:ListBucket",
                "s3:DeleteObject"
            ],
            "Resource": [
                "arn:aws:s3:::fedoubt-prod-web-assets/task/v2/*",
                "arn:aws:s3:::fedoubt-prod-web-assets"
            ]
        }
    ]
}
  1. name: s3-put-policy

新版的 AWS SDK 和 GitHub Actions 用到了 OIDC 驗證中的 session tagging 功能

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AssumeRolePolicy",
            "Effect": "Allow",
            "Action": [
                "sts:AssumeRole",
                "sts:TagSession"
            ],
            "Resource": "arn:aws:iam::my-id:role/GitHubActionsS3Role"
        }
    ]
}

## S3 Bucket Policy

CloudFront 和 GitHub Actions 分成兩個獨立的 **Statement**

{
    "Version": "2008-10-17",
    "Id": "PolicyForCloudFrontPrivateContent",
    "Statement": [
        {
            "Sid": "AllowCloudFrontServicePrincipal",
            "Effect": "Allow",
            "Principal": {
                "Service": "cloudfront.amazonaws.com"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::fedoubt-prod-web-assets/*",
            "Condition": {
                "StringEquals": {
                    "AWS:SourceArn": "arn:aws:cloudfront::my-id:distribution/E2BB5HJ93U5T36"
                }
            }
        },
        {
            "Sid": "AllowGithubActions",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::my-id:role/GitHubActionsS3Role"
            },
            "Action": "s3:PutObject",
            "Resource": "arn:aws:s3:::fedoubt-prod-web-assets/task/v2/*"
        }
    ]
}

GitHub Actions

# 生成 AWS 認證
aws iam create-access-key --user-name github-actions-user

# 複製 AWS_ACCESS_KEY_ID & AWS_SECRET_ACCESS_KEY

New repository secret

進入 GitHub Repository → Settings → Secrets and variables → Actions → New repository secret,新增:

key value
AWS_ACCESS_KEY_ID AKIAEXAMPLE123456
AWS_SECRET_ACCESS_KEY wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
### **.github/workflows/deploy.yml**

GitHub Actions只會執行存在於當前分支上的workflow檔案。

確認在對的分支上創建workflow檔案:

workspace/
├── .github/workflows/deploy.yml
└── task-vue/
    └── my-vue-app/
        └── dist/
name: Deploy Vue3 to S3

on:
  push:
    branches:
      - task-vue  # 只在 push 到 main 分支時觸發

jobs:
  deploy:
    runs-on: ubuntu-latest

    permissions:
      id-token: write  # 啟用 OIDC 驗證
      contents: read

    steps:
      - name: Checkout repository
        uses: actions/checkout@v3

      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: 18

      - name: Install dependencies
        working-directory: ./task-vue/my-vue-app  # 完整路徑到Vue項目目錄
        run: npm install

      - name: Build project
        working-directory: ./task-vue/my-vue-app  # 完整路徑到Vue項目目錄
        run: npm run build

# ... AWS credential setup ...
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v2
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}        # 這是 User 的憑證
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} # 這是 User 的憑證
          role-to-assume: arn:aws:iam::my-id:role/GitHubActionsS3Role-task-v2
          aws-region: ap-southeast-2
          role-duration-seconds: 900  # 將此值減小,例如設為15分鐘

      - name: Deploy to S3
        run: aws s3 sync ./task-vue/my-vue-app/dist s3://fedoubt-prod-web-assets/task/v2 --delete