トップ 最新 追記

2017-04-17 [長年日記]

_ GitHub/BitbucketからAccess Tokenを使ってdeployする

あるいはサーバ上で private package を bundle(npm) install したい。

課題

今回の課題はこれ。

private な repos をサーバ上で clone したい

もう少し詳しく書くと直接の git clone もそうだし、bundle install や npm install で private repos から package を install したいが、もちろん

秘密情報は repos に入れたくない

というものである。

※ Access Tokenが使えれば他のサービスでもサーバでもよい。

解決方法

  1. 環境変数と.netrcを使う
  2. 環境変数と動的なURL書き換えを使う
1. 環境変数と.netrcを使う

この方法を知ったきっかけはこれ。

timshadel/heroku-buildpack-github-netrc: Heroku buildpack to access private Github repos over HTTPS without storing user/pass in your files.

やってることは、

  • 環境変数にトークンを保存
  • build 時に環境変数から ~/.netrc に保存し、git の機能で ~/.netrc の情報で認証を通す

これで確かにリポジトリに認証情報を残さずに private repos から clone できる。

もちろん token の権限設定は必要最小限にしておこう。

サーバ上の環境変数設定を簡単に行える環境ならこれが楽だと思う。

2. 環境変数と動的なURL書き換えを使う

Capistrano で clone することで deploy する際には上とは異なる方法を利用することにした。

Easier builds and deployments using Git over HTTPS and OAuth

の情報をもとに Capistrano を叩く環境に変数でトークンを保存したうえで URL を

set :repository, "https://#{fetch(:github_auth_token)}:x-oauth-basic@github.com/{user}/{repos}"

と、cap を叩く時に書き換える。Gemfile や package.json がないならこの方法も使える。

※ Gemfile や package.json がある場合は頑張って上の buildpack と同じようなことをしてあげることになると思う。

手元の環境からも deploy したい場合は dotenv のようなものを使うか、.netrc に情報を保存するのもアリ。Capistrano 側のコードはこんな感じになる。

set :github_auth_token, ENV['GITHUB_AUTH_TOKEN'] || Netrc.read['github.com']['login']

.netrc を読み書きできる便利 gem はこれ。

heroku/netrc: Reads and writes netrc files.

なぜ他の方法ではないのか?

ここから先はちなみに情報。

Git 自体が対応している認証情報の保存方法がいくつかある。最近では自分で手で作業する場合はこのうちのいずれかを利用しているケースが多いと思う。

Git - 認証情報の保存

によると

  • cache (15分だけメモリに保存)
  • store (永続的にファイルに保存)
  • osxkeychain (macのkeychainアプリにパスワードを保存)
  • wincred (Windowsのkeychainのようなもの)

の4つに対応している。

ただしこれらは、人間がパスワードを入力しその認証情報を保存する、という流れを想定しており、Coutinuous Deployment で利用するにはイマイチである。

Git でパスワードを入力せずに push / pull するということでロートルがすぐに思いつくのはパスフレーズなし鍵認証の ssh を使う方法である*1が、今回行おうとしているのは

サーバ上で git clone や bundle install や npm install したい

ということであり、サーバ上に余計なものは入れたくないし、まして Heroku などの PaaS 上では採用できない方法である。(deploy用の公開鍵を保存する機能はあっても秘密鍵を保存する機能が存在しなかったりする。)

なぜ.netrcで可能なのか?

最後になるけど、なんか普通に .netrc って言ってるけど、そもそもこれ何?って話。

  • git は http での転送の際に cURL を利用している
  • cURL は .netrc に対応している

.netrc って古の ftp ですよね?ってぼくは思っていたのですが、cURL 力不足ということのようでした。(実は cURL あまり好きじゃなかった)

cf.

Man page of NETRC

Tags: Git

*1 なぜなら Git で http での push / pull が使いものになるのは 1.6.6 で登場した Smart HTTP が使えるようになる 2009年以降の話であり、それまでは CVS や Subversion でもおなじみだった ssh と組み合わせる方法の方がポピュラーだったのだ。


2017-04-20 [長年日記]

_ mitmproxyで自動的にweinreを読み込ませるスクリプト書いたのでモバイルのデバッグが捗る

今さらなネタばかりですいません。

背景

2017年4月現在では Safari, Chrome に remote debug の機能が入っているので、対応している環境ではこれを使うことでスマホのブラウザの挙動に対しても効率的にデバッグできるようになってきている*1

が、なんかどうも安定しないし、例えば Windows からは Safari のリモートデバッグ使えるのかなぁ?

ということで環境を選びにくい古の weinre なわけだけど、これの何が問題って

  1. weinre の script を serve しなければいけない
  2. デバッグしたい HTML に <script> を書いて weinre のコードを読み込ませる必要がある

ところ。

対策

実はもう何年も前に思いついてはいたんだけど、誰か作ってるでしょと思ったら見つけることができず、どうでもよくなって放置していたんだけど、上の問題は

  • weinre を serve するサーバパッケージを用意する
  • local proxy サーバで HTML を書き換えてあらゆる HTML で自動的に weinre を読み込む <script> を入れる

ことで解決する。

準備

ということで作った。

まずは以下の道具を用意。

weinre はいつの間にかそれ専用の weinre コマンドが npm 上にできてたので、

$ npm install weinre -g

mitmproxy は Python で書かれているので普段 Python を使っている人は pip でもいいし、使ってない人はバイナリパッケージがあるのでそれを使うといい。Homebrew 使ってる人は

$ brew install mitmproxy

がいちばん簡単。

スクリプト

使い方

1) weinre を localhost 以外の IP アドレスで起動する

localhost でしか listen しないと weinre を起動した PC からしか繋がらない。

$ weinre --boundHost 192.168.0.5 --httpPort 8282

みたいな感じ。

2) スクリプトを読み込みながら mitmproxy を起動

この時、1 で起動した weinre の情報を与えてやる。上の例で言うと

$ mitmproxy -s "weinre.py 192.168.0.5 8282"

になる。

weinre も mitmproxy もデフォルトでは 8080 で立ち上がろうとするので、どちらかには port を明示的に指定して譲らなければいけない。

※ mitmproxy は https も proxy できる。mitmproxy で証明書を発行して、クライアントとなる OS、ブラウザにこの証明書をインストールする。この手順は十分簡単なので、公式のドキュメントを参照のこと。

3) ブラウザの proxy 設定で mitmproxy を指定する

これは各ブラウザの設定方法を参照。

これであらゆるサイトについて weinre の機能でリモートデバッグできるようになった。便利。

weinre の使い方についてはバッサリ割愛。

*1 Android 4.4+ / iOS 6+


2017-04-21 [長年日記]

_ PHPアプリのDB schemaをRubyのActiveRecordだけでdumpする

背景

schema.rbが欲しいのです。

我々は賢いので。

賢いかどうかはともかく、DB schema を手軽に確認する方法として schema.rb はそこそこ優れてると思うわけですよ。少なくとも何百とテーブルがあるわけじゃないならね。インデントも揃ってるし、SQL よりは読みやすく感じる。しかもこれが自動で更新され続けるんだから Rails をやる時は schema.rb は重宝します。特に普段触っていないものは。

ActiveRecordだけでschema dumpする

基本的には

ruby - ActiveRecord Schema Dump without rails - Stack Overflow

のお話。ただし注意点があって、

  • establish_connection は ConnectionPool を返す
  • そこからさらに connection を取得しないと Dumper に渡せない

具体的に言うと

AR::SD.dump(AR::Base.establish_connection.connection)

になるってことです。

上のコードはこれを避けるためなのか ActiveRecord::Base.connection を直接渡しているんだけど、手元ではうまく動かなかったので、動きを追ったらそうだった、ということでした。

Rails風にDB接続設定を持つPHPアプリのDBをActiveRecordでdump

上の方法で schema.rb は作成できるようになったけど、問題は DBMS 接続情報をどう取得するか。Rails なら database.yml になっているのでそれさえ探せばいいんだけど、この方式になっているフレームワークばかりではない。

具体的に今回のターゲットは Laravel なんだけど、Laravel の場合は大丈夫。

app/config/database.php にある

return array(
  'default'    => xxxx,
  'connection' => array(
    ...
  )
);

の部分に接続情報はまとまっている。この情報だけを取得するための以下のようなコードを用意する。

wrapper_script.php

<?php
print json_encode(require('app/config/database.php'));

これでデータベース接続情報を JSON で stdout に出力できる。こいつを Ruby 側から

JSON.parse(`php wrapper_script.php`)

とすれば Ruby のオブジェクトとして PHP アプリの接続情報を取得できる。あとは Ruby 側で好きに加工すればよい。

※ 先頭の <?php は特に忘れやすいので注意!!!

残りの課題は
  • driver -> adapter 変換
  • dsn -> 個別情報分解

の辺り。

探してみたけど、Ruby には単体の DSN parser はなさそうなので、自分で書いた方が早いかもしれない。それか

larskanis/ruby-odbc: ODBC binding for Ruby

辺りを使うと何か嬉しいことがあるかも。そこは試してませんので悪しからず。

Tags: PHP DBMS Ruby