Appleの証明書関連を調べるときに公式ドキュメントの「証明書」ページを読んでおくととても捗る
Appleの証明書関連を検索するとき、かなり検索しにくく感じるときがありますが、
のページに目を通しておくと公式ドキュメントのググラビリティが非常に上がります。というか、先に読んでおくもののはずなんですが、ググり方がわからなかったので、メモ。
また、上記ページの各種証明書がApple Developer AccountのどのフォームからDLされるものか、について追加でまとめます。
Apple Worldwide Developer Relations Certification中間証明書
ここのフォームからDLするだけだと拡張子が .cer
なだけでどの種類の証明書かわかりにくいんですが、このファイルをDLした.cerを開いたとき、キーチェーンに追加されるのが
となっています。
Apple Push Notification Service証明書
俗称・Push通知用の証明書、 .p12
に書き出すやつ
Identifiers > App IDs > 特定のApp ID
をクリックして下の方のEditボタンを押して出て来る
のフォームで作成・再作成・DLするもの。
iOS配布用証明書(App Store)/ iOS配布用証明書(社内用アプリケーション)
英語版のページと
Certificates - Support - Apple Developer
Provisioning Profile の作成フォームを見比べて
Provisioning Profile のこと。
みなさまにおかれましては、独自の証明書を使った認証の 利用者が不慣れな*1仕組みを実装、ならびにそのドキュメントを作成するときは拡張子(とサンプルファイル名)も書いていただけると非常に話がスムーズなので何卒よろしくお願いします。
現場からは以上です。
*1:調べてたら一般的な仕組みとわかってきた(また今度まとめよう...)ので訂正
RSpecでクラスの挙動や定数をテスト用のダミーにする、見慣れなかったマッチャ、普段は実行しないテストのスキップ、などの話
参加しているプロジェクトのRSpecを見ていたら見慣れないことがいろいろあったので、復習しておきます。
RSpecでクラスの挙動をダミー用のものにする
target_obj = double("target_obj") # initializeの文字のほうに深い意味はないらしい target_obj.stub(:string) { "Stub test" } # 以上は上と同じ target_obj = double("target_obj", :string => "Stub test") allow(target_obj)to receive(:post) # ダミーオブジェクトである target_obj に postメソッドを生やす # テストしたいメソッドの中で使われているクラスを初期化したらテスト用に用意したダミー実装が使われるようにする allow(Real::Target).to receive(:new).and_return(target_obj) # def testing_method # Real::Target.new.copy.string # end expect(testing_method).to eq "Stub test" # 所定のspecでだけ定数を置き換えたい stub_const("TARGET::CONST", 100)
参考
http://web-k.github.io/blog/2012/10/02/rspec-mock/ https://qiita.com/jnchito/items/640f17e124ab263a54dd
http://codenote.net/ruby/rspec/1800.html https://relishapp.com/rspec/rspec-mocks/docs/mutating-constants
match_array マッチャ便利かも
ActiveRecordから要素を取り出してくるけど、テスト用にベタがきする値と順序が一致していないので汚いコードを書いて... という記憶があったのでよさそう。
参考
https://qiita.com/jnchito/items/a4a51852c2c678b57868
RSpecで普段は実行しないテストをスキップする
describe Hoge do it "heavy test", type: :model, very_heavy_tests: true do # スキップ用のオプションはRails5で追加された type オプションの後に書きます hoge.should eq(fuga) end end describe Hoge do it "normal test", type: :model do # 書いてない場合は very_heavy_tests: false 扱いでこのテストは普段から実行される hoge.should eq(fuga) end end
RSpec.configure do |c| c.filter_run_excluding :very_heavy_tests => true end
参考
https://qiita.com/semind/items/cffd5c9e7ef9a108c871
現場からは以上です。
インフラエンジニアの教科書2を読みました
DockerとかAWSとか色々勉強しなければいけない感じなのですが、DockerやAWSの説明に出てくる用語がわからないということで、その辺りの基本的なことが載ってそうだし、薄いし、ということで「インフラエンジニアの教科書2」を読みました。
さらっとわかりやすい文体で書いてあるのですが、内容は
あたりから、使う順に引っ張ってきました、という感じで、やさしそうな顔して濃いです。濃さの割にすらすら読めるので、わかった気になってないだろうか、と1ページ1ページなかなか読み進められず2~3週間くらいかかってました。
個人的に、特にありがたかったのが2章のOSのところで、自分はこの本を読んで学んだのですが、短めにまとめたそれでさえかなり重たくて読み終わった後感覚としては結構手ごたえがあったんですが、自分が何に対して手ごたえを得たのかちょっと要領を得ない感じでもやもやしていたのが結構すっきりした気がします。
この本読んで、コード的にもうちょっとどうなってるの... って思ったらこの本をめくってみると楽しいかもです。
逆に4章は、ちょっとシャーディングがレプリケーションと同じノリで書かれていたことに対してやや驚いていて、検索で出てきてほしい結果がユーザやユーザの属する組織、みたいな単位を超えるかどうか、とか、11章の拠点間のデータ保存のところみたいな部分を検討してからでないとなんとも言えないのでは。。と思いました。
他には、6章のSSL通信の基本的なところの説明や8章のセキュリティ攻撃のところがわかりやすくて、SSL通信は長いことひっそり知ったかぶりしていたので、ほっとしたのでした。
以下、読書メモの中で印象的なところを置いておいて、現場からは以上です。
- 経路情報
- ルータがパケットを受け取るたびにそのルータが次の転送先を自動的に選んで送り出す
- ルータには次の経路を決めるためのルールが登録されている必要がある
- 各ルータが経路を決める手段
- スタティックルーティング
- ダイナミックルーティング
- 周りのルータと経路情報を交換し合うことで動的にルーティングが更新される
- IGPとEGPの2種類
- IGP(Interier Gateway Protocol)
- 自分が管理するLAN内部のルータ同士で経路情報を交換し合うプロトコル
- 規模別: 小規模 RIPv2, IGRP 中規模以上 OSPF, IS-IS, EIGRP
- RIPv2
- OSPF(Open Shortest Path First)
- EGP(Exterior Gateway Protocol)
- VLAN
- 「 VLAN(Virtual LAN)とは、スイッチ内を論理的に分割する機能」
- 上の前提として、L2スイッチにはデフォルトではVLAN1しかなく、すべてのポートがVLAN1のポートになっている(なので、すべてのポート間でイーサネットフレームの転送ができる)
- VLAN1しかなく = 1つのネットワークアドレスしかなく
- VLAN1つにローカルネットワークのネットワークアドレスを1つ割りふれる
- 1つの(物理的な)スイッチの中で複数のVLANをもてたりすると何が嬉しい?
- 物理的に機器を用意する制約が緩和
- ポートVLAN
- 1台のL2スイッチ中のポートをいくつかのVLANに割りふれる
- 複数台のネットワークアドレスのために複数台のスイッチがいる ... でもスイッチ買う予算なんて ... う...
- (1つ1つのVLANにつなぐぽーと数が少ない小規模なVLANなら)ポートVLANを使えば物理的なスイッチは1台でもいけるかも...?
- タグVLAN
- 1つのVLANがめっちゃでかくて、レイヤー2スイッチ1台だけでは扱えず、複数のレイヤー2スイッチを使いたい ... タグVLAN
- ダーティリード、ファジーリード、ファントムリードとは、トランザクションの隔離が不十分な場合に発生する可能性のある三つの異常な読み込み現象のことを指す
- SSL通信
- WEBブラウザからWEBサーバに対して安全に共通鍵を送付するために公開暗号方式を使う
- Java SEとJava EE
- ポートスキャン
- DoS攻撃とDDoS攻撃
- オープンリレー
- MTAが外部からアクセスできる状態だと、スパムメールの転送のために利用される(ふつうは自社ネットワーク内など信用できる送信元のみ転送するように設定)
mysql2のgemのインストール時にchecking for mysql_query() in -lmysqlclient... no が出ていたらC言語版のMySQLのクライアントライブラリがない
mysql2のgemをインストールするときに、
checking for mysql_query() in -lmysqlclient... no ...
のエラーが出て失敗する場合、C言語版のMySQLのクライアントライブラリがないです。
なので、たとえばMac OS X(10.11.6)の場合、
$ brew mysql
でC言語版のMySQLのクライアントライブラリ(コマンドでmysqlって入れたら動きだすやつ)を入れたらインストールを進めることができます。
Macの場合は、上記のようにHomebrewを使ったり、MacPorts, MySQLのインストーラを使ってインストールした場合パスの指定は不要となりますが、他のパスにすでにMySQLのクライアントが入っていてそちらを利用したい場合はオプションでそのパスを指定する必要があります。
--with-mysql-dir[=/path/to/mysqldir]
MySQLのインストールされたパス*1--with-mysql-config[=/path/to/mysql_config]
MySQLにはMySQLのコンパイル方法やMySQLのクライアントへの接続方法が入っている mysql_conf という設定ファイルがあって、そのパスを指定する
なお、上記の2つのオプションは一度にどちらかひとつしか使えません。
native extensionのgem苦手意識あって毎回この辺どたどたしてたんですが、めずらしくすっきりしたのでメモ!
参考
RailsのFormクラスについて
Railsでバリデーションを書くケースといえばビジネスロジックで場所はModel(ActiveRecord)が多いのではないかと思います。
これは、たとえばRails Tutorialで扱うような、フォームで扱うModelが一つかつ単純な場合には特に迷う必要はありません。RailsのフォームでsubmitされたパラメータをModelに渡してそのままActiveRecordのバリデーションを使うことができます。
しかし、実際のアプリケーションでは、たとえば住所+配送方法など複数のModelをユーザーの利便性を考えたりすると一つのフォームで扱うことはありうるでしょう。
こういう場合、submitされたパラメータを処理するController側がModelに対応するようにパラメータを編集するか、Model側がフォームの中身を知ってパラメータの形式とModelの対応のコードを引き受けるか、ということになりがちです。
個人的には(Webブラウザという)クライアントからくるリクエストパラメータの形を見てビジネスロジックが扱うクラスが処理できる形にして渡すのはどちらかというとコントローラ側の仕事であって、ModelがいちいちViewのことを知るな、と思うんですが、どちらにせよ見通しが悪くなりがちです。
そこで、Railsでは具体的なテーブルと対応しないForm用のモデルクラスを用意して、Modelの属性とフォームで入力するパラメータの構成が綺麗にマッチしない部分を処理させる実装のパターンがあり、それに利用するクラスをform objectというようです。
form objectで嬉しいのは
- ActiveRecordと同じバリデーションの作法が使える
- formオブジェクトにActiveRecordのモデルと同様に渡すことができ、バリデーションエラーのメッセージを渡す処理が書きやすい
- これまでActiveRecordのModelに書いたりControllerに書いたりで置き場所が落ち着かなかったロジックをまとめやすい
あたりだと思います。
具体的なコードは参考元を見るとして、コード上の要点としては
- ActiveRecordと同じバリデーションを使うために
ActiveModel::Model
をinclude - ActiveRecordと違って対応するスキーマがないので扱うパラメータを明示するために
attr_accessor
を書く - form object は form_for に渡せる(バリデーションエラーを渡したりなど便利)
参考
- https://robots.thoughtbot.com/activemodel-form-objects
- http://api.rubyonrails.org/classes/ActiveModel.html
- http://tech.medpeer.co.jp/entry/2017/05/09/070758
短いですが、今週の現場からは以上です。
fluentdについてのメモ
fluentdとは
参考: https://docs.fluentd.org/v0.12/articles/quickstart
基本Cで書かれていてRubyの薄いラッパーがあるログ収集用のライブラリ。 Fluentdは入ってきたログをJSONとして扱う。
インプットプラグインとアウトプットプラグイン
参考: https://docs.fluentd.org/v0.12/articles/quickstart 参考: https://docs.fluentd.org/v0.12/articles/life-of-a-fluentd-event
Fluentdには
- 入力を受け付け、入力されたデータをFluentd上で共通して扱える形式であるJSON + αに加工するインプットプラグインと、
- インプットプラグインから出力されたデータを他の場所へ時刻などをつけて整形したりフィルタリングしたりして出力するアウトプットプラグイン
がある。どのプラグインを使用するかは .conf
の拡張子を持った設定ファイル(デフォルトでは fluent.conf
. 詳しいパスは https://docs.fluentd.org/v0.12/articles/config-file )にxmlのような形で書いていく。
インプットプラグインは、source
要素を使い、種類(@type
)と種類に対応したパラメータを指定することで、IP, ポート, 流れてきたデータの加工方法を指定される。
たとえば、 https://docs.fluentd.org/v0.12/articles/life-of-a-fluentd-event の例の
<source> @type http port 8888 bind 0.0.0.0 </source>
では、 localhostのTCPポート 8888
番から json=<JSON文字列>
のボディを持つHTTPリクエストがきたら、Fluentdで扱えるJSONのデータが内部で取れる、ということになる。
アウトプットプラグインは、match
要素を使い、インプットプラグインが出してきたJSONのデータをフィルタリングしたり、特定のキーの値を加工したり、別のファイルや標準出力へ出力したりする。
match tag
のように書くことで、特定のタグを持ったログのみを出力に渡すことができて、むしろフィルタリングしない場合も **
など、なにかしら書かないといけない。
また、 https://docs.fluentd.org/v0.12/articles/life-of-a-fluentd-event の例を眺めてみると
<match test.cycle> @type stdout </match>
となっていて、 test.cycle
のタグがついたログだけを標準出力((これは @type stdout
の指定による。標準出力へログを出すアウトプットプラグインを使う、という意味))に出す、という意味になる。
インプットプラグインにより、ログがJSONとして扱えるよう加工されている
参考: https://docs.fluentd.org/v0.12/articles/life-of-a-fluentd-event
Fluentdは入ってきたログをJSONとして扱う
というのを読んだ時、一瞬JSONの形でFluentdに渡さなければいけないのかと思ったのですが、そんなことはない。
たとえば、Apache のログが /var/log/httpd-access.log
のパスで以下のような形式になっているとして
192.168.0.1 - - [28/Feb/2013:12:00:00 +0900] "GET / HTTP/1.1" 200 777
fluent.conf
で入力元を Apache
のログとするように
<source> @type tail format apache path /var/log/httpd-access.log tag apache.access </source>
のように適切にプラグインの指定をすれば、このsourceから出てきたログを受け付けるアウトプットプラグインを書く時は、JSONのキーを加工して... みたいな感じでパラメータの指定ができる。
便宜上、Fluentdの上ではJSONとして扱う、と言ってますが、sourceで指定したインプットプラグインから出力されるデータは Event
と呼ばれていて、JSON形式のデータ以外に、時刻とタグがつく。
Eventを複数の出力へ送る
参考: https://qiita.com/nagais/items/ca96af840b8061102551 参考: https://docs.fluentd.org/v1.0/articles/out_copy
基本的にログを加工して送る先は1つだと思うんですが、タグAがついたログとタグBがついたログは別のS3のバケットに送りたい、とかそういう場合は out_copy
プラグインを使う。
<match pattern> @type copy <store> @type file path /var/log/fluent/myapp1 ... </store> <store> ... </store> <store> ... </store> </match>
一旦 out_copy
プラグインを使うmatch要素でsourceから来た入力を受けて、store
要素で指定した別のmatch要素に送り直す形となる。
Eventをフィルタリングしたり、加工する
参考: https://docs.fluentd.org/v1.0/articles/life-of-a-fluentd-event#filters 参考: https://docs.fluentd.org/v1.0/articles/filter_record_transformer
全部のログを取ると多すぎるので、注目したいイベントのログだけ保管用のストレージへ転送、といったこともなくはないと思うけれど、そういう場合は filter
要素を使って書くフィルタープラグインを使う。
filter
要素は source
要素と match
要素の間に書くみたい。
また、Fluentdはログの転送だけじゃなくて加工も行うのだが、加工を行う場合もフィルタープラグインを使い、代表的なものが record_transformer
プラグイン。
たとえば、
<filter foo.bar> @type record_transformer <record> adding_key "Sample" </record> </filter>
のようにすれば、EventのcontentsのJSONに "Sample"
という値の adding_key
というキーが追加される。
現場からは以上です。
ウィンドウ関数に触ってみる
下準備
http://sqlfiddle.com/ の Postgress SQL 9.6 でテスト。
CREATE TABLE books ( id int, name varchar, author varchar, price int ); INSERT INTO books VALUES ( 1, 'Introduciton For Dog', 'Pochi', 200 ); INSERT INTO books VALUES ( 2, 'High Performance For Dog', 'Pochi', 350 ); INSERT INTO books VALUES ( 3, 'Master Of Dog', 'Pochi', 1000 ); INSERT INTO books VALUES ( 4, 'Introduciton For Cat', 'Tama', 500 ); INSERT INTO books VALUES ( 5, 'High Performance For Cat', 'Tama', 700 );
まずは集約関数
SELECT author, COUNT(*) FROM books GROUP BY(author);
// 結果 author count Tama 2 Pochi 3
はじめてのウィンドウ関数
// 関数をかける列を指定するイメージ(関数で使う列の値で行を並び替えて...みたいなイメージ)はGROUP BYに似ているが // WINDOW関数の基本的な構文の場合、SELECT句にOVER(PARTITION BY 列) と書く SELECT author, COUNT(*) OVER(PARTITION BY author) FROM books;
author count Pochi 3 // countで出ている数はGROUP BYの場合と同じだが、 Pochi 3 // ウィンドウ関数の場合は集約処理がなされていないので Pochi 3 // 行がたくさんでてくる Tama 2 Tama 2
ウィンドウ関数は
- 集約関数と同じく特定の列でグループ化された行の中で処理をするけど
- 集約のように1行にまとめるのではなく、1行ごとに結果が欲しい
という場合に使うと便利で、代表的なものとしてRANKがある。ウィンドウ関数が使用可能なのはSELECT句とORDER BY句。
SELECT author, name, RANK() OVER(ORDER BY price DESC) as rank FROM books;
author name rank // ウィンドウ関数は処理を行う列以外もSELECTできる Pochi Master Of Dog 1 // 集約する際に集約に使わない行を消すが、その際、集約に使った列以外はどこを残すか、 Tama High Performance For Cat 2 // といった問題が発生しないので表示できる状態にしてても困らないとか? Tama Introduciton For Cat 3 Pochi High Performance For Dog 4 Pochi Introduciton For Dog 5
一つのSQLの中に複数のウィンドウ関数を書くことができ、それぞれのウィンドウ関数に異なるOVER句を記述することが可能。
複数のウィンドウ関数で同じOVER句を使う場合は OVER(ORDER BY price DESC)
の ORDER BY price DESC
の部分にWindow句で名前をつけることができて、OVER句内で参照することができる。
SELECT author, name, RANK() OVER price_order as rank FROM books WINDOW price_order AS (ORDER BY price DESC);
参考: https://www.postgresql.jp/document/9.4/html/tutorial-window.html