s3 set iam permissions for Github Actions to achieve CIBuild an AWS s3 static website
S3 靜態網站設定
如果有打算限制能近來的域名,就請不要用靜態網站,就用預設的 RestApi 模式,接 cloudfront 透過 header 去限定。
官網教學很詳細! 要在 Amazon S3 上設定靜態網站,如果是使用 UI 的話,請按照以下步驟進行操作:
- UI: 建立新的 S3 Bucket 或選擇一個現有的 Bucket。(Cli:
aws s3 mb s3://me-profile --profile ford --region us-west-1
在 us-west-1 建立 s3 bucket,bucket 名稱是 me-profile,使用的 user 是 ford) - UI:在 Bucket 屬性中啟用靜態網站主機。
- UI:指定要使用的索引文件(index.html)和錯誤文件。(Cli:
aws s3 website s3://bucket-name --index-document index.html --error-document error.html
) - UI :將必要的文件添加到 Bucket 中。(可以用 也可以用 cli
Cli:
aws s3 sync ./dist/ s3://fordserver-front --delete --profile ford
) - UI :配置 Bucket 策略以允許公開訪問文件,預設會全擋。
- UI :新增儲存貯體政策,將儲存貯體內容設為可供大眾讀取,把這個 json 複製貼上
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": [
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::Bucket-Name/*"
]
}
]
}
Resource 更新為您的儲存貯體名稱!
- (可選)如果要配置自己買的域名, 把 cname 設置以指向 S3 網站端點。
按照這些步驟,您可以使用 Amazon S3 建立簡單且具成本效益的靜態網站。
接 clourfront
建立一個靜態網站之後,去建立 cloudfront,把流量導到 s3。
以下是建立 CloudFront 分發的步驟:
- 登入 AWS Management Console 並前往 CloudFront 控制台頁面。
- 點擊「建立 distribution」按鈕。
- 在「建立 distribution」頁面中,您可以從下拉式清單選擇「Web」或「RTMP」分發的類型。
- 對於 Web 分發,在 Origin 欄位中,從下拉式清單選擇您的 S3 桶的 REST API 端點或輸入您的 S3 桶的網站端點。網站端點和 REST API 端點之間的主要差異
- 在預設快取行為中,為 Viewer 協議原則選擇 HTTP 和 HTTPS 或重新導向 HTTP 到 HTTPS。 注意:選擇僅使用 HTTPS 會封鎖所有 HTTP 請求。
- 如果您沒有使用 CloudFront 的替代域名 (CNAME),則選擇「建立分發」以完成流程。如果您正在使用 CNAME,則在創建分發之前請按照以下額外步驟進行操作:
- 對於替代域名 (CNAME),請選擇「新增項目」,然後輸入您的替代域名。
- 對於自訂 SSL 憑證,從下拉式清單中選擇涵蓋您的 CNAME 的自訂 SSL 憑證,以將其指派給分發。(這裡可以用 aws 的自簽憑證會很方便!)
lab: Provide CI access to write to S3 resources
目標: 設定 github action 在 code 更新以後會把 build 好的資料由 build 資料夾底下東西發到 S3.
名詞定義:
STS: AWS Security Token Service API,提供信任的使用者暫時安全憑證,控制對於 AWS 資源的存取。
IdP: Identity Provider 身分識別資訊提供者
OIDC: OpenID Connect,Google 或 Salesforce。如果想要在 OIDC 相容的 IdP 作識別身份並和您的 AWS 帳戶 之間建立信任,請使用 IAM OIDC 身分提供者。
SAML: Security Assertion Markup Language(安全斷言標記式語言)的縮寫,是指在身分識別資訊提供者(IdP)與服務提供者(Service Provider,SP)之間傳送驗證以及授權資料的一種公開標準。
lab 1.用 IAM role 配合 ODIC 執行 CI
這邊示範用 ODIC,讓 aws 認可的 IdP 作身份驗證並連線到 AWS 存取並更新 S3
因為 github 對 aws 屬於外部資源,需要透過權威單位(OIDC)對你的非 AWS 資源做驗證身份,驗證這個資源是否是你的,通過驗證後,就會被當作一個 AWS 主體,透過給這個主體授予假設角色(sts:AssumeRoleWithWebIdentity)以給予臨時安全憑證,這樣就算是完成一個有暫時憑證的 role. 接下來就是透過 IAM policy 給這個 role 適當操作 aws 資源的權限! ::
在建立 IAM OIDC 身分提供者之後,必須建立一個或多個 IAM 角色。角色是 AWS 中的一個身分,並不擁有自己的憑證 (與 IAM 使用者不同)。在此情況中,角色以動態指派給聯合身分使用者,而該使用者由您組織的身分提供者 (IdP) 進行驗證。
順序:
建立Identity Providers->建立角色->自訂信任政策->連結許可政策->複製建立的角色ARN->設定github CI/CD的secret->建立yml檔
建立 Identity Providers
- AWS console 查詢 IAM,左方 nav 欄位選供應商類型後, 選 OpenID Connect.
- 供應商 URL, 輸入 https://token.actions.githubusercontent.com
- 按"取得指紋"
- 對象, 輸入 sts.amazonaws.com 以上建立之後,arn:aws:iam::930209118237:oidc-provider/token.actions.githubusercontent.com
- 把 ARN 複製準備建立 role.
建立角色
自訂信任政策->連結許可
這邊是比較難懂的一步,主要設定是為了讓 github 的 repo 能被 oidc 驗證 授權 聯合使用者主體,給 github repo 是 USERNAME/YOUR_REPO 的 pull or main 可以用此角色,以下記得替換成你的 repo 名稱歐!
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::9302XXX18237:oidc-provider/token.actions.githubusercontent.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"token.actions.githubusercontent.com:sub": [
"repo:USERNAME/YOUR_REPO:pull_request",
"repo:USERNAME/YOUR_REPO:ref:refs/heads/main"
],
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
}
}
}
]
}
因為 S3 許可設定真的太多了,這邊主要就勾選 list 跟幾個會用到的 delete/get/put object,許可設定參考官網這篇。在看許可過程中有看到 AWS cloudtrail 提供的 IAM 紀錄解析,幫你分析之前的操作並用最小權限去設定(這個情境官網有舉例: 開發時可能會把權限全開,但實際上 PROD 環境就要限制權限,可以透過 cloudtrail 去分析之前所有對 S3 操作有用到的權限,並設定之),但因為還沒實作,所以就先這樣。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:ListBucketMultipartUploads",
"s3:ListMultipartUploadParts",
"s3:AbortMultipartUpload",
"s3:DeleteObject",
"s3:ListBucket"
],
"Resource": "*"
}
]
}
另外因為需要執行 cloudfront purge,也請給該 Role: CloudFrontFullAccess 的權限.
github 設定檔,以下會執行 build,驗證 aws,把編譯後資料推到 s3,並 purge cloudfront。
permissions 一定要設定成 write,這樣設定是要設寫入權限才能請求 OpenID Connect JWT 令牌。沒設定就會跑出以下報錯 Error: Credentials could not be loaded, please check your action inputs: Could not load credentials from any providers :::
name: Deploy to S3 and purge cloudfront
on:
push:
branches:
- main
# Review gh actions docs if you want to further define triggers, paths, etc
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#on
permissions:
id-token: write
jobs:
deploy:
name: Deploy to GitHub Pages
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 18
cache: yarn
- name: Install dependencies
run: yarn install --frozen-lockfile
- name: Build website
run: yarn build
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-region: ap-northeast-3
role-to-assume: ${{ secrets.PROD_DEPLOY_ROLE }}
role-session-name: OIDCSession
- name: Deploy to S3 bucket
run: aws s3 sync ./build/ s3://yours3 --delete
- name: Purge cloudfront
run: aws cloudfront create-invalidation --distribution-id yourCloudFrontID(ex.E2HL0T0J5GSDCG) --paths /*