GithubActionsでOpenAPIをS3へアップロードしホスティング


# やりたいこと
1. GithubのmainブランチへOpenAPIの`yaml`をpushするとGithubActions起動
1. `redoc-cli`が動作。`yaml`→`html`を生成
1. s3バケットへ`html`をコピー
1. s3を参照しOpenAPIがブラウザ上から見れるように
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216527/0051006f-ee15-2bef-c3aa-e791693e8175.png)

# 構築手順

## s3バケット作成とサイト確認

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216527/6e5eece8-0e9b-124d-14e5-131cffa7fa73.png)


~~~ bash:CloudShell
# バケット作成
$ aws s3 mb s3://<<バケット名>>
make_bucket: <<バケット名>>

# for-test-pageバケットのアクセスブロックを設定し、公開できる状態に
$ aws s3api put-public-access-block --bucket <<バケット名>> --public-access-block-configuration "BlockPublicAcls=false,IgnorePublicAcls=false,BlockPublicPolicy=false,RestrictPublicBuckets=false"

# 設定の反映を確認
$ aws s3api get-public-access-block --bucket <<バケット名>>
{
    "PublicAccessBlockConfiguration": {
        "BlockPublicAcls": false,
        "IgnorePublicAcls": false,
        "BlockPublicPolicy": false,
        "RestrictPublicBuckets": false
    }
}
~~~

- バケットポリシー用のjson作成

~~~json:bucket-policy.json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::<<バケット名>>/*"
        }
    ]
}
~~~

~~~ bash:CloudShell
# バケットポリシーのアタッチ
$ aws s3api put-bucket-policy --bucket <<バケット名>> --policy file://bucket-policy.json
~~~

- 本来Redocになる`app.html`をホスティング確認のため適当な中身を作りs3へ手動アップロードして確認します

~~~ html:app.html
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
            <title>test page</title>
    </head>
    <body>
        This is test page
    </body>
</html>

~~~

~~~ bash:CloudShell
# s3 アップロード
$ aws s3 cp app.html s3://<<バケット名>>/app.html
upload: ./app.html to s3://<<バケット名>>/app.html
~~~

- アップロードされたファイルが確認できました

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216527/4ec9745e-d44e-7a12-c319-3b7dff4f29d4.png)



## GithubActions動作用IAMユーザー作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216527/4257e2f6-868c-63bb-f5f3-ca4a178549bd.png)

~~~ bash:CloudShell
# user作成
$ aws iam create-user --user-name <<ユーザー>>
# キー発行
$ aws iam create-access-key --user-name <<ユーザー>>
~~~

~~~json:user-policy.json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "s3:*",
      "Resource": "*"
    }
  ]
}
~~~

~~~ bash:CloudShell
# ポリシーの作成
$ aws iam create-policy --policy-name openapi-test-policy --policy-document file://user-policy.json
# ポリシーのアタッチ
$ aws iam attach-user-policy --user-name <<ユーザー>> --policy-arn arn:aws:iam::****:policy/openapi-test-policy
~~~

## Githubのリポジトリ作成、プロパティへIAM情報をシークレットへ登録
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216527/9fd9e639-1c76-8c94-63a4-1022ff8c8333.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216527/7c537a46-19e1-b298-dbd6-820bf724e5c0.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216527/6d35dae0-3daa-22b9-4837-7ca5b26be9a9.png)



## GithubActions作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216527/ef68c5b9-c949-0756-4c67-31fd6707bd13.png)

- `.github/workflows`

~~~ yaml:deploy_openapi.yaml
name: OpenAPI Build and Push HTML to S3

on:
  push:
    branches:
      - master

jobs:
  build:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node: ["12.x"]
    steps:
      - name: Checkout # 最新コードの取得
        uses: actions/checkout@v2

      - name: node setting # Redocでnpmを使うのでNodeの設定
        uses: actions/setup-node@v1
        with:
          node-version: ${{ matrix.node }}

      - name: install redoc # Redocのインストール
        run: npm install -g redoc-cli

      - name: build openAPI file # OpenAPIの定義をHTMLに変換
        run: redoc-cli bundle ./openapi.yaml --output app.html # プロジェクトのディレクトリに合わせて変更してください。

      - name: Output file contents # 問題があった場合に確認するために中身を出力
        run: cat ./app.html

      - name: Configure AWS credentials # S3にファイルを配置するために権限の設定
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: ${{ secrets.AWS_DEV_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_DEV_SECRET_ACCESS_KEY }}
          aws-region: ap-northeast-1

      - name: S3 copy # 生成したHTMLファイルをS3に配置する
        env:
          S3_BUCKET_NAME: ${{ secrets.AWS_DEV_BUCKET_NAME }}
        run: aws s3 cp ./app.html s3://$S3_BUCKET_NAME/app.html

~~~

# 動作確認

- 適当なOpenAPIファイルを作成し`master`へ`git push`
- GithubActionが動き出す

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216527/99841d3a-b093-5374-bd71-8091346f8d37.png)

- s3にファイルがアップロードされ、ReDocがみえることを確認

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216527/4d8d9af5-4629-5db3-39eb-2626d74f2fa5.png)

# 最後に
OpenAPIは見えるようになりました。
2つ課題は残っていて、いずれ解決したいなと思います。
- s3の前にCloudFrontを立てて署名付きURLに
- ベーシック認証をつけてアクセスを制御
    - バケットポリシーにIP制限つけるのもあり

[ベーシック認証を追加し改善を行ないました。](https://qiita.com/icck/items/37ecf2321922e9eeb586)