mmts1007’s diary

プログラミング関連の技術系ブログです。

Go 開発環境構築 [glide のインストール]

前回からの続きで今回はパッケージ管理ツール

Go のパッケージ管理ツール

Go のパッケージ管理ツールは以下の通り複数ある。
今回は Star 数の多い glide について記載する。

2017/11/02 現在

ツール名 Star
glide 5611
dep 5513
godep 5014
govendor 2615
gb 2006

注意点

公式がパッケージ管理ツール dep を開発している。
glide の READMEdep への移行を考えてくれと記載されているが、今回は glide を紹介する。

理由としては、以下の通りまだ大きな変更が入る可能性があるためである。
参考: https://github.com/golang/dep#current-status

  • 取り込まれるのは Go 1.10 以降である事 (参考: ロードマップ)
  • まだ厄介なバグが含まれている事
  • 遅い事

glide とは

github.com

  • npm, Maven, Bundler のようなGo 言語のパッケージ管理ツール
  • プロジェクトに依存するパッケージを vendor ディレクトリで管理する
  • プロジェクトごとに依存パッケージのバージョンを固定できる

glide のインストール

1コマンドでインストール可能
参考: https://github.com/Masterminds/glide#install

curl https://glide.sh/get | sh

glide の使い方

参考: https://github.com/Masterminds/glide#usage

glide の利用開始

$ glide create

glide.yaml ファイルが自動生成される

glide 経由でパッケージをダウンロードする

例として echo というパッケージをダウンロードする場合

$ glide get github.com/labstack/echo

vendor ディレクトリ配下に指定したパッケージがダウンロードされる

$ tree vendor/
vendor/
└── github.com
    └── labstack
        └── echo

また glide.yaml, glide.lock にダウンロードしたパッケージが記載される

# glide.yaml
package: github.com/mmts1007/glide_sample
import:
- package: github.com/labstack/echo
  version: ^3.2.3
# glide.lock
hash: d8348bf86f67e8762c036cca040e09d39a74eec9cbe7d8b4f5e6ad9148bc2495
updated: 2017-11-02T14:10:52.482634978Z
imports:
- name: github.com/labstack/echo
  version: cec7629194fe4bf83b0c72d9a02d340c7a1468ac
testImports: []

glide で管理しているパッケージのアップデート

glide.yaml に記載されているパッケージのアップデートを行う

$ glide up

依存パッケージのダウンロード

プロジェクトに glide.lock ファイルがある場合、glide.lock ファイルの内容を元に依存パッケージをダウンロードすることができる

$ glide install

glide の基本的な使い方は以上

Go 開発環境構築 [ワークスペースの構成]

mmts1007.hatenablog.jp

今回はワークスペースについて

ワークスペース

参考: Goコードの書き方 - The Go Programming Language

例えば、ホームディレクトリ直下の go ディレクトリをワークスペースとした場合は以下の通り

$ tree $HOME/go
/home/vagrant/go
├── bin
├── pkg
└── src

GOPATH

ワークスペースの場所については特に指定がないため GOPATH を使ってワークスペースの場所を教えてあげる必要がある

Goコードの書き方 - The Go Programming Language にも記載されているが、Goをインストールしたパスではない ことに注意。GOPATH は Go のワークスペースがどこなのかを教えるものである

私の場合 $HOME/goワークスペースとしたので GOPATH は $HOME/go になる。

また

利便性向上のため、以下のようにワークスペースのbinサブディレクトリをPATHに追加してください。

と記載されているので環境変数は以下の通り

$ export GOPATH=$HOME/go
$ export PATH=$PATH:$GOPATH/bin

プロジェクト

例えば、 GitHubhello_world パッケージを管理する場合は、以下のようなディレクトリ構成にする

$ tree $HOME/go
/home/vagrant/go
├── bin
├── pkg
└── src
    └── github.com
        └── mmts1007 # GitHub のアカウント
            └── hello_world # hello_world パッケージ
                └── main.go # Go コード

ワークスペースについては以上。次はパッケージ管理ツールについて

Go 開発環境構築 [goenv のインストール]

Go 言語を触る機会があったので、 Go 言語の開発環境構築方法をまとめておく
まずは goenv のインストールから

goenv とは

github.com

  • goenv は rbenv や pyenv のような Go 言語のバージョン管理ツール
  • 複数の Go 言語のバージョンをインストールできる
  • プロジェクト(ディレクトリ)ごとにバージョンを簡単に切り替えることができる

goenv のインストール

Mac であれば Homebrew でインストールできる

参考: https://github.com/syndbg/goenv#homebrew-on-mac-os-x

$ brew update
$ brew install goenv

Linux の場合は GitHub からクローンしてインストールする

参考: https://github.com/syndbg/goenv#installation

# GitHub からクローン
$ git clone https://github.com/syndbg/goenv.git ~/.goenv

# 環境変数を定義
$ echo 'export GOENV_ROOT="$HOME/.goenv"' >> ~/.bash_profile
$ echo 'export PATH="$GOENV_ROOT/bin:$PATH"' >> ~/.bash_profile

# goenv init を Shell に追加
$ echo 'eval "$(goenv init -)"' >> ~/.bash_profile

# .bash_profile に定義した内容を読み込み
$ source ~/.bash_profile

Go のインストール

goenv 経由で Go をインストールする

参考: https://github.com/syndbg/goenv/blob/master/COMMANDS.md#goenv-install

# Go 1.9.2 をインストール
$ goenv install 1.9.2

# システム全体で Go 1.9.2 を使用するよう設定
$ goenv global 1.9.2

# local でディレクトリごとにバージョンを変更することも可能
# cd 先に .go-version ファイルがあれば、ファイル内に記載されているバージョンに自動的に切り替わる
# (goenv local すると .go-version ファイルが自動生成される)
$ goenv local 1.9.2

goenv のインストールは以上でおしまい

SSL クライアント認証を試してみる

Web サーバへのアクセス制限をするために、 SSL クライアント認証を試してみた。

その時調べた内容や、動作確認をした時の内容などをまとめてみました。

SSL クライアント認証とは

SSL クライアント証明書を利用して、クライアントを認証する方法です。
SSL クライアント証明書を持っているクライアントしか利用できないため、セキュアと言えます。

SSL クライアント証明を理解するために参考になったページ

利用方法

SSL クライアント認証を利用するには

  • クライアント証明書
  • Web サーバの設定

が必要です。

今回は上記内容に加えて

も利用しました。

プライベート認証局

認証局がないと証明書を発行できないため、はじめに認証局を作成します。

プライベート認証局の証明書、サーバー証明書、クライアント証明書の作成方法について | レンタルサーバー・自宅サーバー設定・構築のヒント

を参考に作成しました。

サーバ証明書、クライアント証明書

こちらも

プライベート認証局の証明書、サーバー証明書、クライアント証明書の作成方法について | レンタルサーバー・自宅サーバー設定・構築のヒント

を参考に作成しました。

Web サーバの設定

今回 Web サーバは nginx を利用しました。
以下のリンクを参考に conf ファイルを作成しました。
(conf ファイルはしっかり調べてないので、ベストな設定ではないかも・・・)

ssl.conf

server {
    listen                 443 ssl;
    server_name            www.example.com;
    ssl_certificate        /etc/pki/CA/certs/www.example.com.crt;
    ssl_certificate_key    /etc/pki/CA/private/www.example.com.key;
    ssl_verify_client      on;
    ssl_client_certificate /etc/pki/CA/cacert.pem;
    ssl_protocols          TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers            HIGH:!aNULL:!MD5;

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }
}

この ssl.conf を /etc/nginx/conf.d/ に配置し、 nginx を再起動

$ ls /etc/nginx/conf.d/
default.conf  ssl.conf

$ sudo /etc/init.d/nginx start

デモ

Web サーバにリクエストすると、サーバから証明書を求められる f:id:mmts1007:20170909144301p:plain

適切な証明書を選択すると、 nginx の welcome ページが表示される f:id:mmts1007:20170909144327p:plain

証明書を渡さないと、エラーページに遷移される f:id:mmts1007:20170909144349p:plain

(基本参考のリンクばかりになってしまったw)

Docker で Rails の開発環境を構築する

Docker で Rails の開発環境を配れたら、楽できるのでは?思い、サンプルを作ったのでまとめる。

サンプルコード

github.com

Dockerfile と docker-compose.yml は以下の通り

Dockerfile.development

FROM ruby:2.4.1
MAINTAINER mmts1007

ENV APP_ROOT=/usr/src/app

WORKDIR $APP_ROOT
EXPOSE 3000

RUN apt-get update && apt-get install -y \
      nodejs \
      mysql-client

COPY . $APP_ROOT
RUN bundle install

CMD ["bundle", "exec", "rails", "s", "-b", "0.0.0.0"]

docker-compose.yml

version: '3'
services:
  db:
    image: mysql
    environment:
      MYSQL_ROOT_PASSWORD: root
    volumes:
      - mysql-data:/var/lib/mysql
  web:
    build:
      context: .
      dockerfile: Dockerfile.development
    volumes:
      - .:/usr/src/app
    ports:
      - "3000:3000"
    depends_on:
      - db
volumes:
  mysql-data:

工夫した点

  • 開発時は DB も必要になるため、 docker-compose を利用して 1コマンドで開発に必要がものが揃うようにした
  • 修正したソースコードをすぐに反映したかったため、ソースコードは Docker コンテナにマウント
  • DB に書き込んだデータは保持したかったので、 volumes を使って永続化

使い方

docker-compose build

$ pwd
/path/to/docker-rails/simple_note
$ docker-compose build
...
Successfully tagged simplenote_web:latest

docker-compose up

$ docker-compose up
Starting simplenote_db_1 ... 
Starting simplenote_db_1 ... done
Recreating simplenote_web_1 ... 
Recreating simplenote_web_1 ... done
Attaching to simplenote_db_1, simplenote_web_1
...
web_1  | Use Ctrl-C to stop

ブラウザから http://localhost:3000 にアクセス

その他

初回起動時は DB、テーブルが存在しないため作成する

$ docker-compose run web bundle exec rake db:create
$ docker-compose run web bundle exec rake db:migrate

追記

Gem ファイルの永続化

記事を公開したところ、先輩に「Gemfile 更新時に、全 Gem インストールし直しになっちゃうから Gem ファイルのインストール先も Volume にするのが良いよ」とコメントを頂きました。(ありがとうございます!)

確かに Gemfile 更新した時に毎回 build して、イメージに含めてあげないと動かない状態でした・・・

Gemfile に Kaminari を追加

gem 'kaminari'

bundle install

$ docker-compose run web bundle install
...
Fetching kaminari-core 1.0.1
Installing kaminari-core 1.0.1
...
Fetching kaminari-activerecord 1.0.1
Installing kaminari-activerecord 1.0.1
Fetching kaminari-actionview 1.0.1
Installing kaminari-actionview 1.0.1
...
Fetching kaminari 1.0.1
Installing kaminari 1.0.1
...
Bundle complete! 18 Gemfile dependencies, 76 gems now installed.
Bundled gems are installed into /usr/local/bundle.

もう一度 bundle install を実行すると キャッシュされて Gem は何もインストールされないことを期待していましたが・・・

$ docker-compose run web bundle install
...
Fetching kaminari-core 1.0.1
Installing kaminari-core 1.0.1
...
Fetching kaminari-activerecord 1.0.1
Installing kaminari-activerecord 1.0.1
Fetching kaminari-actionview 1.0.1
Installing kaminari-actionview 1.0.1
...
Fetching kaminari 1.0.1
Installing kaminari 1.0.1
...
Bundle complete! 18 Gemfile dependencies, 76 gems now installed.
Bundled gems are installed into /usr/local/bundle.

全く同じログが出ました・・・

新たに作成したコンテナに Gem をインストールし、そのコンテナは破棄されてしまうため、このような現象が起きてしまいました。

docker-compose.yml を以下のように変更し、インストールした Gem を永続化するようにしました。

iff --git a/simple_note/docker-compose.yml b/simple_note/docker-compose.yml
index 18e6132..c824f93 100644
--- a/simple_note/docker-compose.yml
+++ b/simple_note/docker-compose.yml
@@ -12,9 +12,11 @@ services:
       dockerfile: Dockerfile.development
     volumes:
       - .:/usr/src/app
+      - gem-store:/usr/local/bundle
     ports:
       - "3000:3000"
     depends_on:
       - db
 volumes:
   mysql-data:
+  gem-store:

この状態であればコンテナが破棄されたとしても Gem 自体は残るので、先ほどの問題は発生しなくなりました!

参考

docs.docker.com

qiita.com

SAML 認証を Ruby on Rails で試してみた

SAML 認証に触れる機会があったので、 Ruby on RailsSAML 認証するサンプルアプリを作ってみた
折角なので、SAML とは何なのか?あたりからまとめてみようと思います。

SAML とは

まずは、SAML とは何なのか

  • 読み方は サムル
  • Security Assertion Markup Language の略
  • 異なるサービス、アプリケーション間で認証情報を交換するための仕組み
    • これによりシングルサインオン(1度のログインで、複数のアプリが利用可能になること) が実現できる

登場人物

Identity Provider

  • 略称は IdP
  • 実際の認証処理を行う人。認証したユーザの情報(ID、 メールアドレス等)を提供してくれる

Service Provider

  • 略称は SP
  • 認証情報を利用する人

今回は SP のサンプルを作成しました。

認証フロー

SAML の認証フローのイメージです。 f:id:mmts1007:20170121235429p:plain

  1. ユーザは SP に対してログインを試みる
  2. SP は Idp に対して認証リクエストを送信する
  3. IdP はユーザにログイン画面を表示する
  4. ユーザはログイン情報を入力する(ex. ID / Password)
  5. IdP は入力情報を検証し、正しければ SP に認証結果を送信
  6. SP は認証結果を検証し、正しければユーザをログインさせる


SAML の説明はこのあたりにして、サンプルアプリについて説明します

構成

IdP

サンプルアプリを動かすためには IdP が必要なので、今回は IdP に Azure Active Directory を利用しました。

azure.microsoft.com

SP

SP は以下の技術要素で作成

また、SAML のライブラリとして ruby-saml を使用しました。

github.com

サンプルアプリ

サンプルアプリはメモ管理アプリとなっています。
Azure AD で認証したユーザのメモ一覧・登録・更新・削除ができる簡単なものです。

SAML 連携部分の実装は https://github.com/onelogin/ruby-saml のサンプル https://github.com/onelogin/ruby-saml-example をベースに
少し修正を入れたものになっています。
(SAML 部分の実装はほぼサンプルのままです)

github.com

動作確認

http://localhost:3000 にアクセス
「Azure AD で Login」をクリック f:id:mmts1007:20170122020523p:plain

Microsoft アカウント(IdP)のログインページが表示される
ID / Password を入力 f:id:mmts1007:20170122020841p:plain

メモアプリ(SP)にログインする f:id:mmts1007:20170122020539p:plain

まとめ

SP を作るためにはもっとゴリゴリ書く必要があるかと思っていたのですが、
https://github.com/onelogin/ruby-saml がとても使いやすく、IdP の設定情報を記述するだけで動かすことができました。サンプルもあるのも良かったです。

Grafana を使ってサーバメモリ使用率、CPU使用率を可視化する

top コマンドや free コマンドなどで確認していたサーバ負荷状況をグラフィカルに見やすできないのかと思い調べたところ、Grafana という可視化ツールがあったので試してみました。

Grafana とは

grafana.org

  • インフラや、アプリケーションの分析データなど時系列データを可視化するためのダッシュボードツール
  • デフォルトで複数のデータストアをサポートしている
    • Graphite
    • Elasticsearch
    • Cloudwatch
    • Prometheus
    • InfluxDB

今回は InfluxDB を利用しました。

構成

VagrantVM を 2個立ち上げて作成しました。

  • 負荷状況を送信するサーバ(CentOS 6.7)
  • Grafana, InfluxDB サーバ(CentOS 6.7)
    • 本来は Grafana と InfluxDB は別サーバにすべきだと思いますが、お試しのため同居させています。

f:id:mmts1007:20170110182941p:plain

  1. 負荷情報を確認したいサーバの CPU, メモリ情報を InfluxDB に送信
  2. InfluxDB は CPU, メモリ情報を DB に格納
  3. ブラウザから Grafana ダッシュボードにアクセス
  4. Grafana はダッシュボードを表示するために必要な情報を InfluxDB から取得し、ダッシュボードを表示する

インストール手順

Grafana のインストール

http://docs.grafana.org/installation/rpm/ を参考に Grafana をインストール

# Grafana のインストール
$ sudo yum install https://grafanarel.s3.amazonaws.com/builds/grafana-4.0.2-1481203731.x86_64.rpm

# Grafana を起動
$ sudo service grafana-server start

http://192.168.33.10:3000/login にブラウザからアクセスし、Grafana のログイン画面が開くことを確認 f:id:mmts1007:20170110190024p:plain

InfluxDB のインストール

https://www.influxdata.com/downloads/ に記載されている「RedHat & CentOS」のとおり実施

f:id:mmts1007:20170110191059p:plain

# influxDB をダウンロード
$ wget https://dl.influxdata.com/influxdb/releases/influxdb-1.1.1.x86_64.rpm

# インストール
$ sudo yum localinstall -y influxdb-1.1.1.x86_64.rpm

# InfluxDB 起動
$ sudo service influxdb start

InfluxDB データベースの作成

https://docs.influxdata.com/influxdb/v1.1/introduction/getting_started/ を参考にデータベースを作成します。

$ influx
Visit https://enterprise.influxdata.com to register for updates, InfluxDB server management, and monitoring.
Connected to http://localhost:8086 version 1.1.1
InfluxDB shell version: 1.1.1
> CREATE DATABASE grafana

# DB が作成されているか確認
> SHOW DATABASES
name: databases
name
----
_internal
grafana

Grafana のセットアップ

Grafana の管理画面から利用するデータストアや、ダッシュボードの設定します。

  1. http://192.168.33.10:3000/login にブラウザからアクセス(admin/admin でログイン)
  2. 左上 Grafana アイコンクリック → 「Data Sources」 をクリック f:id:mmts1007:20170110202657p:plain

  3. 「Add Data Source」をクリック f:id:mmts1007:20170110202952p:plain

  4. InfluxDB の情報を入力、「Add」をクリック f:id:mmts1007:20170110203120p:plain

負荷情報の取得方法

InfluxDB へのデータアクセス方法は、複数サポートしています。
今回は負荷情報を確認したいサーバから InfluxDB の HTTP API を利用して負荷情報を送信します。

CLI

https://docs.influxdata.com/influxdb/v1.1/tools/shell/

$ influx -execute 'SELECT * FROM "h2o_feet" LIMIT 3' -database="NOAA_water_database" -precision=rfc3339
name: h2o_feet
--------------
time                           level description        location         water_level
2015-08-18T00:00:00Z     below 3 feet               santa_monica     2.064
2015-08-18T00:00:00Z     between 6 and 9 feet  coyote_creek  8.12
2015-08-18T00:06:00Z     between 6 and 9 feet  coyote_creek  8.005

HTTP API

https://docs.influxdata.com/influxdb/v1.1/tools/api/

$ curl -i -XPOST "http://localhost:8086/write?db=mydb&precision=s" --data-binary 'mymeas,mytag=1 myfield=90 1463683075'

クライアントライブラリ

https://docs.influxdata.com/influxdb/v1.1/tools/api_client_libraries/

実際に利用したコマンドは以下のとおり

メモリの使用率を取得するスクリプト

while true; do
  curl -i -s -XPOST 'http://192.168.33.10:8086/write?db=grafana' --data-binary "memory,host=serverA,region=jp_east value=`free -t | grep Total | sed 's/[\t ]\+/\t/g' | cut -f3`"
  sleep 5
done

CPU の使用率を取得するスクリプト

while true; do
  idle=`mpstat | tail -n 1 | sed 's/[\t ]\+/\t/g' | cut -f11`
  rate_of_cpu=`echo "100-${idle}" | bc`
  curl -i -s -XPOST 'http://192.168.33.10:8086/write?db=grafana' --data-binary "cup,host=serverA,region=jp_east value=${rate_of_cpu}"
  sleep 5
done

まとめ

ダッシュボードを作成し、以下のような値が取得できるようになりました。 f:id:mmts1007:20170111000020p:plain

過去のデータも確認することができますし、毎回サーバにログインする手間もなくなるので楽になりそうですね。

本番で運用するためには Grafana の admin ユーザのパスワード変更や、InfluxDB の パスワード設定などセキュリティの設定をする必要があります。(今回は Vagrant 上にお試しで作ったのでセキュリティ部分に関しては設定していません)