S3へのFTPクライアント接続にIP制限を掛ける

f:id:jotaki:20200305110857j:plain

htmlを静的ホスティングしているS3バケットへのブラウザアクセスはバケットポリシーでIP制限が可能。
だけど、FTPクライアントでのS3接続はIAMユーザーのアクセスキー&シークレットを使うので、そのユーザーの権限で設定してあげる必要があります。
ほぼ初めてちょっとテクいことをしてみたので(全然難しくないんだろうけど)メモしておきます。

IAMユーザーの作成

コンソールでIAMから S3_ftp-client-user というユーザー名でユーザー作成。
アクセスキー、シークレットを取得する必要があるので「プログラムによるアクセス」にチェックを付ける。

f:id:jotaki:20200305110321p:plain

とりあえずこの段階でポリシーはアタッチせず、タグは適当なものを付ける。
アクセスキーとシークレットはFTPクライアントでの接続で使うので控えておく。

f:id:jotaki:20200305110334p:plain

IAMポリシーの作成

アクセス権限として下記を与える。
"Action": "s3:*", は絞る必要があるときは絞って、 "aws:SourceIp": [] の中に許可するIPアドレスを追加していく。

f:id:jotaki:20200305110345p:plain

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "s3:*",
            "Resource": "*",
            "Condition": {
                "IpAddress": {
                    "aws:SourceIp": [
                        "ここにIPアドレス01",
                        "ここにIPアドレス02",
                        "ここにIPアドレス03"
                    ]
                }
            }
        }
    ]
}

S3FullAccessOnlyPrivateNetwork というポリシーを作成。( Private ではなくネットワーク名がよい )

f:id:jotaki:20200305110358p:plain

IAMポリシーのアタッチ

最後に S3_ftp-client-user ユーザーに S3FullAccessOnlyPrivateNetwork のポリシーをアタッチしてあげる。
「アクセス権限の追加」を押して

f:id:jotaki:20200305110419p:plain

「既存ポリシーのアタッチ」から先ほど作ったポリシーをアタッチ

f:id:jotaki:20200305110436p:plain

動作確認

Transmit を使用して登録IPアドレスからの接続確認。

アクセスキー&シークレットを入力

f:id:jotaki:20200305110449p:plain

問題なくリストが表示される。

f:id:jotaki:20200305110501p:plain

登録していないIPからだと Access Denied となったのでOK

f:id:jotaki:20200305110513p:plain

まとめ

今回管理ポリシーを使ったのですが、あまり運用上推奨されるプラクティスではないと思うのでもう少しいいやり方がありそうです。
んまー管理ポリシー使うとしても、登録するIPアドレスはSystems Managerのパラメータストア使うとかがいいのかなと思ったり..実際にいじってみるといろいろ分かっていないなーという感じがしました。

microCMS をさわってみる その9

日本製のHeadless CMS、microCMSをさわってみる。その9

f:id:jotaki:20200303155515j:plain

GitHub: https://github.com/yuheijotaki/micro-cms-ramen
Netlify: https://ramen.yuheijotaki.dev/

ラーメンコンテンツの描画

前回作ったコンテンツを描画していきます。
curlpython -mjson.tool をつけると見やすく出してくれます。

curl "https://jtk.microcms.io/api/v1/demo" -H "X-API-KEY: ここにAPIキー" | python -mjson.tool

JSONの中身は下記のような感じ

{
    "contents": [
        {
            "category": [
                {
                    "category": "\u307f\u305d",
                    "createdAt": "2020-03-05T07:07:17.724Z",
                    "id": "5__2y6A9e",
                    "updatedAt": "2020-03-05T07:07:17.724Z"
                },
                {
                    "category": "\u30e9\u30fc\u30e1\u30f3",
                    "createdAt": "2020-03-05T07:05:54.951Z",
                    "id": "pM7WYjpvf",
                    "updatedAt": "2020-03-05T07:07:24.608Z"
                }
            ],
            "content": "<h3 id=\"hjzz2WrKPk3\">\u3010\u6c60\u888b \u5473\u564c\u30e9\u30fc\u30e1\u30f3\u3011</h3><p>\u30b7\u30c3\u30ab\u30ea\u3068\u3057\u305f\u6b6f\u5fdc\u3048\u306e\u9eba\u306f\u6fc3\u539a\u5473\u564c\u30b9\u30fc\u30d7\u3068\u76f8\u6027\u629c\u7fa4\u3067\u3059\u3002</p>",
            "createdAt": "2020-03-03T06:37:47.405Z",
            "id": "hanada",
            "image": {
                "url": "https://images.microcms-assets.io/protected/ap-northeast-1:ab97ca46-b946-408b-917a-fae46b705181/service/jtk/media/FireShot%20Capture%20062%20-%20%E9%BA%BA%E5%87%A6%20%E8%8A%B1%E7%94%B0%20%E6%B1%A0%E8%A2%8B%E5%BA%97%20-%20%E6%B1%A0%E8%A2%8B_%E3%83%A9%E3%83%BC%E3%83%A1%E3%83%B3%20%5B%E9%A3%9F%E3%81%B8%E3%82%99%E3%83%AD%E3%82%AF%E3%82%99%5D%20-%20tabelog.com.png"
            },
            "name": "\u9eba\u51e6 \u82b1\u7530 \u6c60\u888b\u5e97",
            "updatedAt": "2020-03-05T07:12:51.182Z",
            "url": "https://tabelog.com/tokyo/A1305/A130501/13109890/"
        }
    ],
    "limit": 10,
    "offset": 0,
    "totalCount": 1
}

詳細ページのテンプレート、出力部分だけとこんな感じになります。
JSONの形通りにVueで出力すればOKですね。

<template lang="pug">
  div
    h1 {{ post.name }}
    div(
      v-html="post.content"
    )
    h2 カテゴリー
    ul
      li(v-for="item in post.category") {{item.category}}
    h2 食べログURL
    p
      a(:href="post.url" target="_blank") {{ post.url }}
    p
      img(:src="post.image.url")
</template>

フロント(見た目)はこんなかんじになりました。

一覧

f:id:jotaki:20200305174128p:plain

詳細

f:id:jotaki:20200305174143p:plain

まとめ

一通り試したいことの最低ラインができたので一旦完了にします。
本来は、microCMSのその他機能

  • 下書きプレビュー
  • ステージングなどの環境分け

などもできれば実案件で使うときに役立てるかもしれないのですが、十分に検証はできたかと思います。

実案件でmicroCMS使う際の懸念点としていまだに残っているのは↑の2点ができるかということと、

  • プランや容量がどこまでの規模の案件で使えるかの確認
  • コンテンツの形式が限られているのでその要件に収まるか
  • GitHub + Netlify 以外のサービスと組み合わせる時の環境構築どうするか
  • API(microCMS)側のサーバーどこまで安定しているのか

などの検証や調査みたいなことが必要だと思っています。

ただ静的htmlで作っていた小規模のサイトにちょこっとお知らせエリアとか制作実績を加えたいみたいな要件に関してはすごい使えるなと思います。
それこそHeadless CMSの特徴なのでWPごと入れる手間に比べれば、かなりエンジニアにとってもいい流れにあるなあということを体感できました。

microCMS をさわってみる その8

日本製のHeadless CMS、microCMSをさわってみる。その8

f:id:jotaki:20200303155515j:plain

GitHub: https://github.com/yuheijotaki/micro-cms-ramen
Netlify: https://ramen.yuheijotaki.dev/

サブドメインあてる

前回 と同じ用に設定。
サブドメインつきで https://ramen.yuheijotaki.dev/ としました。

コンテンツ調整

せっかくなのでラーメン屋を登録していきます。 写真は持っていないので、食べログの画面キャプチャを貼り付けてリンクを貼ることにします。

カテゴリー機能も付けたいので、APIの新規作成から ramen-category を作成します。

f:id:jotaki:20200305162011p:plain

複数コンテンツの参照元となるのでリスト形式にします。

f:id:jotaki:20200305162028p:plain

スキーマを設定して作成。

f:id:jotaki:20200305162046p:plain

カテゴリーをコンテンツとして登録しておきます。

f:id:jotaki:20200305162059p:plain

次に、参照先のAPIにてスキーマ作成します。
「複数コンテンツ参照」を選択。

f:id:jotaki:20200305162113p:plain

参照したいコンテンツに先ほど作成した ramen-category を選択します。

f:id:jotaki:20200305162127p:plain

参照先のコンテンツも登録しておきます。

f:id:jotaki:20200305162138p:plain

他にもコンテンツがあったほうがいいですが、一旦一つのみにして次回登録したコンテンツを取得していきます。

残りやること

  • コンテンツ調整
  • かるくスタイリングする

できれば

  • microCMSのその他機能
    • 下書きプレビュー
    • ステージング

microCMS をさわってみる その7

日本製のHeadless CMS、microCMSをさわってみる。その7

f:id:jotaki:20200303155515j:plain

GitHub: https://github.com/yuheijotaki/micro-cms-ramen
Netlify: https://ramen.yuheijotaki.dev/

webhook設定

microCMSを更新したら自動ビルドが走るようにするのでwebhookの設定を行う。
参考: ヘッドレスCMS × Static Site GeneratorでJamstackな爆速表示サイトを作ってみるチュートリアル - Qiita の「Step.4 Webhookの設定」

ビルドフックの作成

まず Netlifyの管理画面 => Settings => Build & Deploy => Build hooks にて適当な名前をつけてビルドフックを作成します。

f:id:jotaki:20200304161126p:plain

ビルドフックの登録

microCMSの管理画面 => API設定 => Webhook => Netlify にて先ほど作成したフックURLを入力します。

f:id:jotaki:20200304161151p:plain

以上で設定完了。

動作確認

動作確認としてmicroCMSでコンテンツを登録してみます。

f:id:jotaki:20200304161205p:plain

Netlifyでビルド状況確認すると「Building」になっている。

f:id:jotaki:20200304161215p:plain

ビルドが完了してNetlifyのURLを見ると無事動作の確認ができました。

f:id:jotaki:20200304161226p:plain

残りやること

  • コンテンツ調整
  • かるくスタイリングする
  • ドメインあてる?

できれば

  • microCMSのその他機能
    • 下書きプレビュー
    • ステージング

microCMS をさわってみる その6

日本製のHeadless CMS、microCMSをさわってみる。その6

f:id:jotaki:20200303155515j:plain

GitHub: https://github.com/yuheijotaki/micro-cms-ramen
Netlify: https://ramen.yuheijotaki.dev/

generate設定

Gitにプッシュした際に、APIから記事一覧情報取得して詳細ページを生成する必要があるので nuxt.config.js に設定を書く。
参考: Nuxt.jsとmicroCMSで採用ページを作成してみよう!

nuxt.config.js に追記

// generate時にaxiosを使って詳細ページを生成
const axios = require('axios')

export default {
  // ...
  // Netlifyへ詳細ページの自動デプロイ
  generate: {
    routes() {
      const demo = axios
        .get('https://jtk.microcms.io/api/v1/demo', {
          headers: { 'X-API-KEY': process.env.API_KEY }
        })
        .then(res => {
          return res.data.contents.map(post => {
            return '/posts/' + post.id
          })
        })
      return Promise.all([demo]).then(values => {
        return values.join().split(',')
      })
    }
  }
}

環境変数はビルド実行されるNetlify側へ設定する必要があります。
Settings => Build & deploy => Environment

f:id:jotaki:20200304143514p:plain

これで設定完了。
設定した nuxt.config.js をmasterにプッシュして動作確認してみます。

Netlifyのサイト管理画面 => Deploys で Building が1分以内には始まるのでクリック

Deploy log に

2:12:03 PM: ✔ Generated /posts/demo02
2:12:03 PM: ✔ Generated /posts/demo01
2:12:03 PM: ✔ Generated /posts/9itQJnwUs

があるので詳細ページの生成はうまくいっているよう。

f:id:jotaki:20200304143534p:plain

最後の Finished processing build request in XXXs を確認したらサイトをみにいく。
一覧ページのリンクをクリックして各詳細ページのコンテンツが描画されていれば成功。

f:id:jotaki:20200304143555p:plain

残りやること

  • webhook設定(microCMSを更新したら自動ビルドが走るようにする)
  • かるくスタイリングする

microCMS をさわってみる その5

日本製のHeadless CMS、microCMSをさわってみる。その5

f:id:jotaki:20200303155515j:plain

GitHub: https://github.com/yuheijotaki/micro-cms-ramen
Netlify: https://ramen.yuheijotaki.dev/

API連携(詳細ページ)

詳細ページを作成する。
Nuxtでは pages/_id.vue とすると pages/[ContentID]/ ページへと動的ルーティングできるので _id.vue を作成する。

<template lang="pug">
  div
    p id: {{ post.id }}
    p title: {{ post.title }}
    div(
      v-html="post.content"
    )
    p
      nuxt-link(to="/") index
</template>

<script>
import axios from 'axios'

export default {
  async asyncData( { params } ) {
    const { data } = await axios.get(
      `${process.env.API_URL}/${params.id}`,
      {
        headers: { 'X-API-KEY': process.env.API_KEY }
      }
    )
    return {
      post: data
    }
  }
};
</script>

一覧側のコンポーネント Post.vue には <nuxt-link> をつけてあげる。

<template lang="pug">
  li
    nuxt-link(:to="`/posts/${post.id}/`")
      p id: {{ post.id }}
      p title: {{ post.title }}
</template>

できあがった画面は、一覧

f:id:jotaki:20200304142212p:plain

詳細

f:id:jotaki:20200304142220p:plain

残りやること

  • generate設定
  • webhook設定(microCMSを更新したら自動ビルドが走るようにする)

microCMS をさわってみる その4

日本製のHeadless CMS、microCMSをさわってみる。その4

f:id:jotaki:20200303155515j:plain

GitHub: https://github.com/yuheijotaki/micro-cms-ramen
Netlify: https://ramen.yuheijotaki.dev/

API連携(一覧ページ)

.env設定

まず.envにAPIキーなど環境設定を行います。
下記の記事通りでいけます。
Nuxt.jsとmicroCMSで採用ページを作成してみよう!

nuxt.config.js

require("dotenv").config();
const { API_KEY, API_URL } = process.env;

export default {
  // ...
  env: {
    API_KEY,
    API_URL
  }
  // ...
}

.env
microCMSのAPIキーは「APIリファレンス」から取得したものを貼り付けます。

API_KEY=APIキー
API_URL=https://jtk.microcms.io/api/v1/demo

これで各.vueファイルで process.env.API_KEY のように process.env. を前につけて環境設定を読み込めます。

下ごしらえができたら、一覧ページのAPI連携をしてみます。

  • components/Posts.vue (リスト用)
  • components/Post.vue (アイテム用)

の.vueファイル2つ作ります。

index.vue

トップページの大元ファイルではPosts(リスト用コンポーネント)を読み込みします

<template lang="pug">
  div
    Logo
    Posts
</template>

<script>
import Logo from '~/components/Logo.vue'
import Posts from '~/components/Posts.vue'

export default {
  components: {
    Logo,
    Posts
  }
}
</script>

components/Posts.vue (リスト用)

一覧用コンポーネントファイルでは axios 使ってAPIを読み込みします。
また子コンポーネント Post に値を受け渡すので :bind しておきます。

<template lang="pug">
  ul
    Post(
      v-for="(post,index) in posts"
      :key="index"
      :post="post"
    )
</template>

<script>
import axios from 'axios'
import Post from '~/components/Post.vue'

export default {
  name: 'Posts',
  components: {
    Post
  },
  data() {
    return {
      posts: []
    }
  },
  mounted :function(){
    axios.get(
      process.env.API_URL,
      {
        headers: { "X-API-KEY": process.env.API_KEY }
      }
    )
    .then( response => {
      this.posts = response.data.contents
    })
    .catch( error => {
      console.log(error)
    })
  }
}
</script>

components/Post.vue (アイテム用)

アイテム用コンポーネントファイルでは props でデータを受け取って描画します。

<template lang="pug">
  li
    p id: {{ post.id }}
    p title: {{ post.title }}
</template>

<script>
export default {
  name: 'Post',
  props:{
    'post': {
      type: Object,
      default: ''
    }
  }
}
</script>

これで投稿の描画を実装できました。

f:id:jotaki:20200304130640p:plain

残りやること

  • API連携(詳細ページ)
  • generate設定
  • webhook設定(microCMSを更新したら自動ビルドが走るようにする)