Timers Tech Blog

グローバルな家族アプリFammを運営するTimers inc (タイマーズ) の公式Tech Blogです。弊社のエンジニアリングを支える記事を随時公開。エンジニア絶賛採用中!→ https://timers-inc.com/engineering

Swagger + CircleCI + S3 Static website hosting を使ってAPIドキュメントをサーバーレスで運用する

サーバーサイドエンジニアのいわむ(@k_iwamu)です! 実は来月AWS re:Inventに参加してきます!弊社は海外カンファレンス補助が充実しているので、そういった配慮に感謝してたくさんのことを学んできます!

さて、社内ではFammを中心としたいくつかのサービスや社内システムで複数のAPIが開発されています。会社の規模も大きくなるにつれ、それぞれのサービスを社内のエンジニアで分担しながら作っています。
そうした中で、2つの課題があげられるようになりました。

- サービスごとにAPIドキュメントの運用方法やフォーマットが統一されておらず、管理が難しい状況になっている
- APIドキュメントをホスティングするためにサーバーが立ち上がっており、その管理も必要になっている

そこで考えられた方針が、Swaggerを使ってドキュメントを統一化し、S3を使ってホスティングする方法です。理由は以下です。

- SwaggerはAPIドキュメントの標準フォーマットとして推進されている。
- S3はマネージドサービスであり、リソースの管理は不要である。さらにホスティングの設定も簡単に行える。

今回はその第一歩として、あるAPIに対して、Swagger + CircleCI + S3 を使ってAPIドキュメントを社内公開 + 自動更新 することを行いました。その作業をブログを通して紹介できればと思います!

Swagger とは

Swagger とは REST APIを構築するためのフレームワークです。「APIドキュメントのフォーマットの1つ」のイメージで知られていることが多いと思いますが、その他にもSwaggerを利用してAPIのスタブを作ったりなど、様々な用途に利用できます。 SwaggerはSmartBear Software 社によって作られました。そして某社はGoogleMicrosoftらと共に OAI(OpenAPI Initiative)という標準化推進団体を結成し、ドキュメント標準化をすすめており、Swaggerの普及を後押ししています。

一言でSwaggerと言っても、実態は2つに分類でき、JSONyamlで定義されたドキュメント仕様(Swagger Spec)と、Swagger Specを生成・編集・閲覧、もしくは利用するためのツール群に分けられます。

ツール群の代表としては、大きく4つが挙げられます。

ツール 説明
Swagger Editor Swagger Specを編集するエディタ
Swagger UI Swagger Specを可視化する
Swagger Core APIソースコードからSwagger Specを生成する
Swagger Codegen Swagger Specを利用してAPI(スタブ)を作成する

開発内容

以下の方針で進めていきました。

1. Swagger Specを記述する
2. CircleCIを使って、ソースコードPush時に自動でS3のSwagger Specを更新させる
3. Swagger UI をS3 Static website hosting でホストする
4. APIドキュメントにIP制限を行う

developer flow

1. Swagger Specを記述する

まずはSwagger UIをダウンロードし、dist/以下の部分をリポジトリに組み込みます。

git clone https://github.com/swagger-api/swagger-ui.git
cd swagger-ui
cp -r swagger-ui/dist <repository>/docs/api/

後述するS3での静的webホスティングのために、dist/index.htmlファイルを移動させます。それに伴ってindex.html内のファイル読み込み先も変更しておきます。

mv <repository>/docs/api/dist/index.html <repository>/docs/api/index.html 

次に swagger.yaml を作成し、Swagger Specを編集します。

touch <repository>/docs/api/swagger.yaml 

以下はサンプルのSwagger Specです。記法はたくさんあるので、調べてみてください。
また編集方法は、Swagger Editor を用いてもいいですし、ご自身で使っているエディタのプラグインを利用しても構いません。自分はVScodeプラグインを使用しました。

openapi: 3.0.0
info:
  version: 1.0.0
  title: Timers Tech Blog API
  description: This is a Timers Tech Blog API
paths:
  /users:
    post:
      summary: Add user (※ 新入社員募集中です!)
      description: Add user
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                  example: iwamu
      responses:
        '201':
          description: return created User data
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/User"         
components:
  schemas:
    User:
      type: object
      required:
        - id
        - name
      properties:
        id:
          type: integer
          example: 1
        name:
          type: string
          example: iwamu

example_swagger

作業後のディレクトリ構成です。

.(repository)
├── docs
│   └── api
│       ├── dist
│        └── <略>
│       ├── index.html
│       └── swagger.yaml
├── src
│   └──  <略>

2. CircleCIを使って、リソースPush時に自動で更新させる

GitHubにPushしたら自動でS3にSwaggerファイルをアップロードさせます。

まず、CircleCI側では、以下の4つの環境変数をセットしておきます。

AWS_ACCESS_KEY: ${AWSのアクセスキー}
AWS_SECRET_ACCESS_KEY. ${AWSのシークレットアクセスキー}
AWS_DEFAULT_REGION ${S3を配置するリージョン}
AWS_S3_DOCS_BUCKET_NAME ${S3のバケット名}

次にCircleCIのジョブの内容を定義します
ちなみにCircleCI のバージョン2.1を利用すると、orbsというパッケージ機能を使えるようになり、AWS-CLIも簡単に使えるので便利です。

version: 2.1
orbs:
  aws-cli: circleci/aws-cli@0.1.16

jobs:
  deploy_api_docs:
    executor: aws-cli/default
    steps:
      - aws-cli/setup
      - run:
          name: update API docs
          command: aws s3 sync docs/api/ s3://${AWS_S3_DOCS_BUCKET_NAME}/

workflows:
  version: 2
  build:
    jobs:
      - deploy_api_docs

3. Swagger UI をS3 Static website hosting でホストする

S3には静的webホスティングという機能があり、指定のオブジェクトのHTMLファイルをホストする機能が備わっています。 今回はこの機能を有効にし、Swagger UIの静的ファイルをホストするようにします。

S3のバケットの「プロパティ」 => 「Static website hosting」 で設定ができます。 インデックスドキュメントは、先ほどディレクトリを移動させたindex.htmlを指定します。

static website hosting
settings static website hosting

有効にするとエンドポイントが払い出されるので、そのエンドポイントをアクセスしてSwagger UIが表示されていれば成功です。

※ 静的webホスティングをするだけだと、通信自体は暗号化されていません。暗号化(httpsで通信)するためには、CloudFrontやRoute53を利用してできるようになりますが、今回の記事の スコープからは外します。

4. APIドキュメントにIP制限を行う

S3にはいくつかの方法でアクセス制限ができ、IPアドレスの制限も可能です。バケットポリシーで指定IPアドレスのみ閲覧を許可する設定をします。(バケット名や許可するIPは書き換えてください)

s3 bucket policy

{
    "Version": "2008-10-17",
    "Statement": [
        {
            "Sid": "AllowPublicRead",
            "Effect": "Allow",
            "Principal": {
                "AWS": "*"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::<バケット名>/*",
            "Condition": {
                "IpAddress": {
                    "aws:SourceIp": "<許可するIP>"
                }
            }
        }
    ]
}

設定が正しく行われていれば、許可されていないIPアドレスからエンドポイントにアクセスするとステータスコード403が返ってくるようになります。
また、運用中に誤ってパブリックアクセス設定が行われないように、バケットのブロックパブリックアクセスは全てONに設定しておきましょう。

ブロックパブリックアクセス

最後に

SPAやマイクロサービスが技術トレンドになっている昨今では、API間のインタフェース仕様を管理するツールが重要となる現場は多くなっており、そういったケースにSwaggerはとても有効な手段の1つだと思います。
今回はAPIドキュメントを生成して可視化するところまで行いましたが、
他にもSwaggerを使ってモックのAPIを作成したりできますし、Swaggerを活用するライブラリが増えてきているので、汎用性はとても高く様々な用途に利用できます。
Swaggerを学んで役立つことは多いと思うので、是非試してみてください!

積極採用中!!

子育て家族アプリFammを運営するTimers inc.では、現在エンジニアを積極採用中!
急成長中のサービスの技術の話を少しでも聞いてみたい方、スタートアップで働きたい方など、是非お気軽にご連絡ください!
採用HP: http://timers-inc.com/engineerings

Timersでは各職種を積極採用中!

急成長スタートアップで、最高のものづくりをしよう。

募集の詳細をみる