HappyGoLucky

Web系サーバーサイド寄りの自動化大好きエンジニアの徒然なるブログ

ElasticBeanstalkのPlatform Versionを更新したらPaperclipでエラーが出た

TL;DR

  • Ruby on Rails 4.10, Ruby 2.4 な環境で
  • AWS ElasticBeanstalk Platform の version を Amazon Linux 2016.03 v2.1.0 から2017.09 v2.6.5 に更新した
  • PaperClip 4.7 でエラーが出るようになったので調べたら
  • ImageMagickpolicy.xmlHTTPS から直接画像を指定できないようになっていたためだった
  • なので、S3からダウンロードしてファイルパスを Paperclip に渡すようにした

経緯

もともと、Paperclip を使って S3 上の画像ファイルを使ってゴニョゴニョしていた。S3上のファイルは https の Endpoint を指定していた。
で、Ruby バージョンを更新することにしたので、それならついでに AWS ElasticBeanstalk Platform も更新するかー、としてみた。
すると、Paperclip を使った処理で Paperclip::Errors::NotIdentifiedByImageMagickError が発生するようになった。

原因特定と対策

Paperclip::Errors::NotIdentifiedByImageMagickError だけだと原因が分からないのだが、すでに以前、 ImageMagick の policy.xml が更新されたことで、rmagick が動かなくなる現象に出会ったことがあった。こちらも rmagickconvert に S3 の Endpoint を渡すようにしていたためで、この時は画像をダウンロードしてから使うことにした。
同じ原因だろう、とログを差し込んで、 Paperclip で https なEndpointを指定していることを確認して原因の特定は完了。

ImageMagick の policy.xml

2016年に公開された ImageMagick脆弱性対策のため policy.xml で制御する、という対策が取られた。
脆弱性の内容自体は次の記事が分かりやすい。
ImageMagickの脆弱性(CVE-2016-3714他)についてまとめてみた - piyolog ImageMagickの脆弱性(ImageTragick) - てきとうなメモ

Amazon Linux もこの対策を採用している。
https://alas.aws.amazon.com/ALAS-2016-699.html

Note: This update contains an updated /etc/ImageMagick/policy.xml file that disables the EPHEMERAL, HTTPS, HTTP, URL, FTP, MVG, MSL, TEXT, and LABEL coders. If you experience any problems after the update, it may be necessary to manually adjust the policy.xml file to match your requirements. Please take additional precautions to ensure that your applications using the ImageMagick library do not process malicious or untrusted files before doing so.

実際に EC2 上の policy.xml を見てみると HTTPS は制限されている。

<policymap>
  <policy domain="coder" rights="none" pattern="EPHEMERAL" />
  <policy domain="coder" rights="none" pattern="HTTPS" />
  <policy domain="coder" rights="none" pattern="HTTP" />
  <policy domain="coder" rights="none" pattern="URL" />
  <policy domain="coder" rights="none" pattern="FTP" />
  <policy domain="coder" rights="none" pattern="MVG" />
  <policy domain="coder" rights="none" pattern="MSL" />
  <policy domain="coder" rights="none" pattern="TEXT" />
  <policy domain="coder" rights="none" pattern="LABEL" />
  <policy domain="path" rights="none" pattern="@*" />
</policymap>

該当行をコメントアウトすると、今までどおりの処理がされた。

<policymap>
  <policy domain="coder" rights="none" pattern="EPHEMERAL" />
  <!--<policy domain="coder" rights="none" pattern="HTTPS" />-->
  <policy domain="coder" rights="none" pattern="HTTP" />
  <policy domain="coder" rights="none" pattern="URL" />
  <policy domain="coder" rights="none" pattern="FTP" />
  <policy domain="coder" rights="none" pattern="MVG" />
  <policy domain="coder" rights="none" pattern="MSL" />
  <policy domain="coder" rights="none" pattern="TEXT" />
  <policy domain="coder" rights="none" pattern="LABEL" />
  <policy domain="path" rights="none" pattern="@*" />
</policymap>

HTTPSの制御をコメントアウトして良いのか?

HTTPS で指定したファイルを使えるようにする、というのは果たして良いのだろうか?
せっかく塞いである穴を自ら開けることになるので、せめてホワイトリスト指定ができれば良い。

ImageMagick 6.9.7-7 では、そのような機能が入ったらしい。
Behavior of policy changed from 6.9.7-7 · Issue #377 · ImageMagick/ImageMagick · GitHub ImageMagick 6.9.7-7 から policy の挙動が変わりました - awm-Tech

ただし、URLをホワイトリスト指定する方法は調べた感じなさそう。ソースコードを追いかけたわけではないので、実装上できないのかは分からない。
また、私が使っている AmazonLinux 上の ImageMagick6.7.8-9 なので、そもそもホワイトリスト指定は使えない。yum update すれば良い話だけど。

やはりセキュリティの穴を自ら開けるのは嫌なので別の方法を検討する。

Paperclip コミュニティではどのように対策を?

Paperclipコミュニティでは、どのような解決方法を検討しているのか調べてみた。

結局ダウンロードしてからPaperclipに渡すことにした

他の手もあるとは思うが、仕方がないので PaperClip の Wrapper を作ることにした。 モンキーパッチは避ける主義なので、Wrapperクラスをべた書き。

Dir.mktmpdir do |tmpdir|
    image_file = File.basename(URI.parse(image_url).path)
    download_path = Pathname(dir).join(image_file)
    File.open(download_path, "wb") do |output|
      OpenURI.open_uri(image_url) do |data|
        output.write(data.read)
      end
    end
    Paperclip::Geometry.from_file(download_path)
end

HTML5 Conference 2017 に行ってきた

events.html5j.org

行ってきた理由

  • 本職のFrontendエンジニアではないので情報収集しておらず知識が古いので
  • 勉強する際のキーワード集め
  • 勉強意欲のモチベーション維持

午前

寝坊して基調講演とセッション1に間に合わず。

後日の動画公開を待つことにします… (任天堂のセッションは多分公開しないと思うけど…)

最近の Web パフォーマンス改善について知っておきたいコト

パフォーマンス改善のために使える最近の技術について。
全く知見のないジャンルだったので、私にとってはただただ新鮮な情報ばかりだった。

詳解 WebRTC

「HTMLの話は一切しません」から始まる「WebRTCのプロトコルの解説」
最後の「これだけのプロトコルを全て隠蔽したのがWebRTC APIです。良かったですね」が、本当に良かったと思える濃厚な解説だった。
WebRTCが依存しているプロトコルを遡ってUDPから取り上げられていて、めちゃめちゃ楽しかったけど内容はほとんど理解できていない。

Web 技術とブラウザ ーいま知っておくべき Web 最新動向ー

この一年で各ブラウザがどのような新機能を追加したかの話。
情報を追いかけていなかった身としては助かるセッションだった。
Microsoftが作っているSonarというLintツール知らなかったので使いたい。ぱっと調べた感じVimのPluginは見つからなかったけど、もうちょい調査。

まあまあ最近のCSSと、これからつらくなくなるために

今年のCSSの目玉新機能 GridLayout について。
これは前から気になっていて、情報収集しつつもがっつり取り組めていなかった。
基本的な使い方の説明が分かりやすかったので一気に理解が進んだ気がする。
後半は既存のページにGridLayoutを導入するためにやったことの説明で、そもそもコンポーネント志向なCSSじゃないとGridLayoutは難しい、という話だった。
margin で余白を〜、という世界はいずれ無くなりそう。無くなるといいなぁ。

スペシャルセッション(ライトニングトーク大会)

LT面白かったー! たくさん笑ったて刺激をもらった。 数が多いので感想のまとめは割愛。

モバイルバッテリー貰いました!

全体を通して

目的通り、最近の情報をそこそこ収集できたと思う。
まずは見たセッションで得た知見を少しでも試して目と指で記憶して、余裕があれば他のセッションの情報もキャッチアップしたい。

HTML5 Conference に行ったの初めてだったけど、すごく楽しめた。来年もあるなら行きたい。
というか今まで行かなかったの勿体なかったなぁ….。

第10回 Jenkins勉強会 に参加しました

www.meetup.com

場所: テクマトリックス株式会社

発表者用とTwitter垂れ流し用のプロジェクターが用意されていて非常に良かった。

挨拶

日本Jenkinsユーザー会のドメインが変わったとのこと。

日本Jenkinsユーザ会

講演1:「第三版Jenkins 実践入門 What’s newから見るJenkinsのトレンド」 @yuki_iwnrさん

www.slideshare.net

Jenkins 実践入門の内容紹介

発表中に口頭で取ったアンケートでは、参加者のほぼ全員がプロジェクトでJenkinsを使っていて、5~6割くらいが 2.0 を使っていて 3割くらいが Jenkinsfile を使っていた。 Jenkinsfile はもっと広まるといいのになぁ。

Declarative と Scripted のどっちを使うかは悩ましい… Jenkinsfileが大きくなると関数化したくなるんだけど、Declarative だと自分で定義した関数が使えない。 かといって Scripted は自由すぎてメンテし辛い。 今のところ Declarative をメインに使って、どうしても関数化・共通化したい部分だけ Scripted を使うようにしてる。

Jenkinsの情報収集方法について紹介があって凄く助かった。 Pluginの検索ページが新しくなってたの知らなかった…

講演2:「Multibranch Pipeline with Docker 入門編」@kimullaaさん

t.co

Jenkinsを使っていたプロジェクトの悩みを、新しいJenkinsでどのように解決していったか、という話。

Jenkins で Docker を使う方法がいくつかあって、その説明と、どう選択したかの話が凄く自分にとってタイムリーで参考になった。

LT

ピザとビールが振る舞われた! Jenkinsユーザー会から出ているとのこと….。ありがたや!

LT1:「巨大不明ビルドの継続的統合を目的とするビルドパイプラインを主軸とした作戦要綱」 @kiy0taka さん

Jenkins の ビルドの通知について。

LT2:「Multibranch Pipelineでいろいろ学んだこと」 @AHA_oretamaさん

Multibranch Pipeline を使いはじめて得た知見のあれこれ。 ビルドのTrigger設定はちょうどいじってたばかりなので、大変参考になった。

LT3:「Jenkinsfileのlintで救える命がある」 @miyajanさん

Declarative Pipeline の構文チェックについて。
jflint というツールを作ったとのこと

www.npmjs.com

違うツールもあるらしい

LT4:「来週から始める本番環境の継続的デリバリー 」 @int128さん

お堅い組織で本番環境デプロイするには、な話。
検証環境で実績を作って、本番でも同じ方法で行う、を徹底した。

LT5:「プルリクエストCI時の2つのTIPS」 @ikikkoさん

プルリクエスト駆動開発でのCIについて。
Jenkins pipeline は CircleCI や TravisCI と同じようにリポジトリにビルド情報(Jenkinsfile)を置くので、プルリクエストと抜群に相性が良くて、使わない手はない。

リポジトリ間に依存関係がある場合のCIについての話が参考になった。

メモ

スライド見ててふと、自分の Jenkinsfile の先頭に groovy のシェバン付けてなかったことに気付いた。
そりゃあ vim でハイライトされなくて書き辛いわけだ…。

Kotlin の coroutines + Android で簡単なカウントダウンタイマー

環境

Kotlin の coroutines 環境セットアップ

ググっても、Kotlinのバージョンによって差がありそうだったので素直に公式を見る。

github.com

私の手元では、↓2つのファイルに手を加えればOK

build.gradle (Module)

dependencied {
    ...
    def kotlin_coroutines_version='0.16'
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlin_coroutines_version"
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version"
    ...
}

gradle.properties

kotlin.coroutines=enable

coroutine を使う

非同期処理自体はこんな感じ。
launch は kotlinx.coroutines.experimental.launch
UI は kotlinx.coroutines.experimental.android.UI
delay は kotlinx.coroutines.experimental.delay
kotlinで全て完結する。

launch(UI) {
   while(isActive) {
        delay(1000)
        time--
    }
}

launch の戻り値は kotlinx.coroutines.experimental.Job で、 start()stop() といったいかにもなメソッドを持ってる。
なので、それをプロパティにもたせて、

class Timer(time: Int) {
    private var countDownJob: Job? = null

    fun countDownStart() {
        if (countDownJob != null) { return }
        countDownJob = launch(UI) {
            while(isActive) {
                delay(1000)
                time--
            }
        }
        countDownJob?.start()
    }

    fun countDownStop() {
        countDownJob?.cancel()
        countDownJob = null
    }
}

といった感じにすれば、カウントダウンタイマーの処理部分ができあがる。
*1

*1:毎回 launch してるのが無駄な気がする。

firedropを使ってみた

firedrop.ai

ずっと前に Subscribe してて忘れてたんだけど、beta版のお誘いメールが来て思い出したのでやってみた。
タイトルとリンクしか無いけど、作ってみたのが↓。

https://yasuhiroki.firedrop.me/

「AIがデザインしてくれる貴方のWebサイトを作るサービス」という触れ込みなんだけど、
今のところは、チャット形式で進むチュートリアルで簡単にWebサイトを公開できるサービスな感じ。

チャットっぽい画面に幾つかの選択肢が用意されていて、
たとえば Change Layout とか Publish Site といったボタンがあるのでクリックしてWebサイト作りを進める。
LayoutとかColorは勝手にいい感じにしてくれる…らしいんだけど、レパートリーが少ない気がする。

Beta版なので機能が少ないだけかな。
私自身、デザインはからっきしなので、機械にお願いできるならお願いしたい。期待してる。

Elixir Conf 2017 に行ってきた

www.elixirconf.jp

行ってきた。Elixir歴2週間(といってもハンズオンでちょっと触った程度)でも十分楽しめた。

経緯

Elixirはずっと気になってたので、イベントが告知された段階ですぐに申し込んだ。
全く触ってなくてもとりあえず行ってみようと思っていたが、Elixir Confの申込後にハンズオンの募集が始まったので、

  1. Elixir Conf 申し込み
  2. ハンズオン申し込み
  3. ハンズオンに行く
  4. Elixir Conf に行く

というスタックのようなスケジュールだった。
当初は、全く経験なしでも行こう、と思っていたが、実際のところ、ハンズオンで説明を受けながら触った経験があって良かった。
それが無かったら、今ほど Conf を楽しめてなかったかもしれない。

感想

始めはElixir作者 José さんのKeynote
ゆっくりで、簡単な英語を使ってくれていて分かりやすかった。
今後の予定として型について言及があり、質問もTwitterも盛り上がってた。

午前中は基礎的な話。
Rubyが好きだけど業務ではJavaScriptなエンジニアなので、関数型プルぐラミング・並列プログラミングのどちらも馴染みがなかったが、 どちらもきちんと説明してくれていたので有難かった。
「Elixir Way」を分かってないと、逐次的な実装になりがちで、それって並列で処理されないからせっかくElixirで書いてるのにもったいない、らしい。頭で分かっても実際に実装できるかは…慣れだなぁ….。

午後からはガチ話が増えてきて、分かるようで分からない話がちらほら。OTPはまだ全く分かってない。
Elixir/Erlangの特性が活きる、小さな処理を大量にさばくために活用している話がほとんど。
もう少し触ってからスライドを見直すのが良さそうだけど、そもそも今の私には紹介されたような事例と出会う場面がなさそう。

LTはやっぱり楽しい。こういうイベントにLTは欲しい。
特別枠はすごく熱い話だった。

最後に時雨堂のVさんのKeynoteで締めくくり。
フリートークに近い話の進め方だったけど、Erlangをがっちり使い続けた方の話なので、これが面白くないわけがない。楽しすぎる。

全体を通して刺激ある一日だった。
無線環境も安心のCONBUさんで快適だった。
電源がなかったことだけが悩みだった・・・。

Elixir初心者向けハンズオンに行ってきた

beam-lang.connpass.com

Elixir楽しい。

きっかけ

1年くらい前に Rebuild.fm や 勉強会などで Elixir の名前を知って興味を持っていたが、 同じくらいの頃に業務で TypeScript を触り始めたので、同時 2つの言語を勉強する力が無く、ずっと放置していた。 最近になって、ようやく時間に余裕ができたぞ、と思ったタイミングでこのイベントを知り、すぐに申し込んだ。

流れ

会場はレバレジーズ。 会場の案内や挨拶の後、 @ohrdevさんによるElixirの概要説明を受け、いざハンズオン。

やったこと

github.com

↑を進めてElixir でチャットアプリを作った。 Pub/Subも WebSocket も初めてだったけどすんなり動いた。

Twitter/Gitter/口頭で質問できるので、進捗ダメです、なことにはならない、と思う。

一通り終わったら人によってやることは様々で、私は Elixir School を読み進めてた。 パターンマッチ面白い。この辺もっと深掘りしたい。

メモ

以下、メモ書き

  • Elixirはコンパイル言語(知らなかった!)
  • %{a: 1, b: 2} == %{:a => 1, :b => 2} != %{"a" => 1, "b" => 2 }
    • 特に Json の手癖で %{"a": 1} とか書くと、それは %{"a" => 1} とは別物になる
    • Atom(Rubyで言うSymbol) かどうかが鍵
      • 何となく分かるけど 腑に落ちてない。触り慣れれば分かってきそう。
  • OTP
    • Open Telecom Platform
    • 並列プログラミング用のフレームワーク・開発環境・ライブラリ集
    • 汎用的な処理のパターン(ビヘイビア)を提供
    • 全く分かってないので調べる
  • mix
    • mixコマンドで Elixir のプロジェクトを作成・管理する
      • こういうツールが標準で入ってると便利…

おまけ

ファイルの空行を削除するElixirのワンライナー書いた