Masteries

技術的なことや仕事に関することを書いていきます.

Go言語でMixed Contentsをなるべく発見する

ウェブサービス/ウェブサイトのHTTPS化にあたっては, Mixed Contentsへの対応が求められます. 既にHTTPSを有効にする作業が完了している状態で, Mixed Contentsが発生していないかを確認したいのであれば, (Node.js製のツールですが)Mixed Contentsの発見のために mcdetect などを使うことができるでしょう.

www.npmjs.com

例えば, このブログ(https://papix.hatenablog.com/)を mcdetect でチェックすると, 次のような結果になります:

$ mcdetect https://papix.hatenablog.com/
Checking https://papix.hatenablog.com/ ...

Targets checked: 1
Errors (blockable content): 0
Warnings (optionally blockable content): 0

ここでの Errors (blockable content)Warnings (optionally blockable content) は, どちらもHTTPSのページでHTTPのコンテンツを読み込んでいる状態ですが, 前者はそのコンテンツがHTTPのみで配信されている状態, 後者はそのコンテンツがHTTPとHTTPSの両方で配信されている状態(= コンテンツを読み込むときのURLを, http://... から https://... にすればMixed Contentsが解決できる)を指します.

mcdetect の課題

mcdetect は, 実際にHeadless Chromeを利用してMixed Contentsの検出を行います. そのため, Mixed Contentsを検索する対象ページは, (前述の通り)HTTPS化が有効になっている必要があります. 実際, mcdetect にHTTPのURLを与えると, Mixed Contentsを見つけるために, 自動的にHTTPSのURLとしてアクセスを行い, Mixed Contentsの検出を行います:

$ mcdetect http://example.com/
Checking https://example.com/ ...

Targets checked: 1
Errors (blockable content): 0
Warnings (optionally blockable content): 0

そのため, 実際にHTTPS化を有効にする前に, なるべくMixed Contentsを見つけたい! という用途には利用できません.

Go言語でMixed Contentsをなるべく発見する

※ "なるべく"とあるように, 以下のコードで全てのMixed Contentsが発見出来るわけではありません. あくまでMixed Contentsを見るける上での参考情報としてお使い下さい.

そこで, Go言語でMixed Contentsを"なるべく"見つけるコードを書きました:

package main

import (
    "fmt"
    "log"
    "regexp"
    "strings"

    "github.com/PuerkitoBio/goquery"
)

func main() {
    doc, err := goquery.NewDocument("https://papix.hatenablog.com/")
    if err != nil {
        log.Fatal(err)
    }

    for _, tag := range []string{"img", "audio", "video", "script", "iframe"} {
        doc.Find(tag).Each(func(i int, s *goquery.Selection) {
            src, _ := s.Attr("src")
            if strings.HasPrefix(src, "http://") {
                fmt.Printf("error\t%s\t%s\n", tag, src)
            }
        })
    }

    doc.Find("link").Each(func(i int, s *goquery.Selection) {
        rel, _ := s.Attr("rel")
        if strings.HasPrefix(rel, "stylesheet") {
            href, _ := s.Attr("href")
            if strings.HasPrefix(href, "http://") {
                fmt.Printf("error\tlink\t%s\n", href)
            }
        }
    })
}

前述の通り, "なるべく"なので100%のMixed Contentsを見つけられる訳ではないですが, これである程度のMixed Contentsを見つけることができます. ここでは,

  • img, audio, video, script, iframeタグのsrcにHTTPのURLがないか
  • linkタグで, かつrelstylesheetのときに, hrefにHTTPのURLがないか

を見ています. 加えて目視で,

  • style タグの中でHTTPのコンテンツを呼び出していないか
  • scriptタグで呼び出しているJavaScriptや, linkタグで呼び出しているスタイルシートでHTTPのコンテンツを呼び出していないか

...辺りを確認しておくと, 更に良さそうです.

まとめ

Go言語のgithub.com/PuerkitoBio/goqueryを使って, なるべくMixed Contentsを見つけるコードを紹介しました.

前述の通り, 実際にHTTPS化した後にMixed Contentsの対応を出来るのであれば, mcdetect を利用する方が確実ではありますが, そうもいかない場合はこういうったスクリプトである程度Mixed Contentsを潰した後, HTTPS化を実施して, mcdetectで最終チェックをする, という手が有効になるかもしれません.

「Hatena Engineer Seminar #10」ではてなブログのHTTPS化についてトークをしました

hatena.connpass.com

ご参加頂いた皆様, ありがとうございました!

当日の発表資料です. サービスのHTTPS化に際してはMixed Contentsの解決が最大の壁になりますが, それに対してただひたすらに, 丁寧に立ち向かって行った... という, 割と地味な話をしました.

id:aereal さんが当日発表された, AWSを活用した証明書の自動取得システムも順調に開発が進んでいます. 独自ドメインのHTTPS対応を提供できるまで, もう少しお待ち下さい.

宣伝

はてなでは, 一緒にはてなブログを開発する仲間を募集しています!!! 「思いは言葉に」するプラットフォームの"次"を, 一緒にやっていきましょう!!!!!!

hatenacorp.jp

「カイゼン・ジャーニー」読んだ

最近話題の「カイゼン・ジャーニー」を読みました. ...だいぶ前に. 感想エントリ書いたつもりだったのだけれど下書き状態のままで, 公開されていなかったのでした... そしてこの本ですが, Twitterとかで id:daiksy さん等たくさんの方々が絶賛していたので, サクッと買っていました.

カイゼン・ジャーニー たった1人からはじめて、「越境」するチームをつくるまで

カイゼン・ジャーニー たった1人からはじめて、「越境」するチームをつくるまで

この本は3部構成の物語仕立てになっていて, 1人の主人公を中心に, 1部では「一人で」, 2部では「チームで」, そして3部では「チームを越えて」, アジャイルのプラクティスを活用することで, チームを"カイゼン"していく様子が描かれています. 1つの部には, それぞれ複数の話があり, そこでは最初に主人公が直面した課題の紹介と, それに対してアジャイルのプラクティスで立ち向かっていく様子が小説で綴られていて, その後に, そこで取り入れられたプラクティスについて詳解するというスタイルになっています

それぞれのプラクティスの説明も丁寧ですし, 何より小説パート(?)の出来がものすごく良くて, 特に終盤の, (自主検閲)が(自主検閲)の(自主検閲)だったシーンはちょっと胸が熱くなってしまいました(?). そういう意味では, 以前読んだ「アジャイルサムライ」よりも, (オタクにとっては)とっつきやすさがある(?)ように思います.

papix.hatenablog.com

...次はこれまた各所で評判だった, 「エンジニアリング組織論への招待」を読み進めていく予定です.

エンジニアリング組織論への招待 ~不確実性に向き合う思考と組織のリファクタリング

エンジニアリング組織論への招待 ~不確実性に向き合う思考と組織のリファクタリング

ところで...

最近こういった本を読んでいたのは, 今期から「テックリード」という役割を任されることになったのが大きいです. はてなにおけるテックリードの役割は, "チームの技術的な窓口"と定義されていますが, とはいえそれに留まらず, これまでよりも一つ上の視点で, チームを客観的に捉えようと思って, チームを見つめ直した結果, 今の自分たちのチームにはたくさん改善出来る所があり, それができれば自分たちはもっとやっていけるのでは? と思ったのでした. 「アジャイルサムライ」とか, 「カイゼンジャーニー」とかは, その改善のヒントを見つけられれば... という気持ちで読んでいたのです.

...で, こういった本で得た知識をそのまま今のチームに導入すると当然うまくいかないパターンが多いので, チームの状況に応じてアレンジをして, 「こういう取り組みをやってみませんか?」という提案を続けた結果, 最終的に「一通り任せてみよう」という話になり, 来週から実験的にチームのスクラムマスターをやることになりました. 前職でスクラムマスターと一緒にスクラムを回した経験はあるものの, 言うまでもなくスクラムマスターという役割を担うのは初めてです. そういう意味で, 現時点では正直不安しかないのですが, とはいえ社内には id:daiksy さんといった有識者がいますし, チームとしても現状維持で良いという意見は全くなくて, スクラムの導入に対してプラスの印象を持ってもらっているので, そういった後押しを力に変えて, うまくスクラムを回していきたいという気持ちです.

というわけで, 今後はそういった領域の気付きや知見なども, ブログに書いていけたらと思っています. 頑張るぞ!!!

AWS::CLIWrapperにPull Requestを投げた

AWSの機能を任意の言語から利用するためのSDKですが, 悲しいことにPerl向けのものはありません. 従って, Perl Monger達はAWSのCLIであるawsコマンドをラップしてPerlから実行する, AWS::CLIWrapperというモジュールを駆使しています.

metacpan.org

さまざまな事情があって, AWSに最近追加された機能をPerlから使いたかったので, さっくりとPull Requestを投げました.

github.com

即座にマージ頂いて, 1.13としてリリースされました. 対応ありがとうございました!

おもしろポイント

AWS::CLIWrapper, たくさんあるAWSの機能に対してどのようにして対応しているのだろう...? と前々から思ったのですが, 今回Pull Requestを出すにあたって眺めてみたところ, aws helpコマンドを使ってAWSの各機能を利用するためのコードを, 自動的に生成していました: https://github.com/hirose31/AWS-CLIWrapper/blob/master/lib/AWS/CLIWrapper.pm#L259-L261

# aws help | col -b | perl -ne 'if (/^AVAILABLE/.../^[A-Z]/) {  s/^\s+o\s+// or next; chomp; next if $_ eq 'help'; my $sn = $_; $sn =~ s/-/_/g; printf "sub %-18s { shift->_execute('"'"'%s'"'"', \@_) }\n", $sn, $_ }'
# aws help | col -b | perl -ne 'if (/^AVAILABLE/.../^[A-Z]/) {  s/^\s+o\s+// or next; chomp; next if $_ eq 'help'; my $sn = $_; $sn =~ s/-/_/g; printf "=item B<%s>(\$operation:Str, \$param:HashRef, %%opt:Hash)\n\n", $sn}'
# =item B<s3>($operation:Str, $path:ArrayRef, $param:HashRef, %opt:Hash)

ドキュメント(ヘルプ)から自動生成すれば漏れがないので, 「なるほど賢い!」と思いました.

Nature RemoのGolang用APIクライアント「go-nature-remo」を書き始めた

最近業務でちまちまとGolangを書く機会がありました. そこで学んだことの復習を兼ねてNature RemoのAPIクライアントを書いてみています. 名前はgo-nature-remoです.

github.com

...実のところ, 現時点ではNature RemoのAPIのうち, Cloud APIのごく一部しか実装出来ていません. 残りは適宜実装していくつもりです(Pull Requestも歓迎です!).

活用例

以前作ったmackerel-plugin-nature-remoは, Nature RemoのCloud APIからdeviceをGETするAPIさえ叩ければ良いので, 早速go-nature-remoで置き換えてみました:

github.com

Golangの感想

ここ数年, Golangに挑戦しようとしては何度か挫折というか足踏みをしていましたが, やはり業務で取り組む機会が出来るとだいぶ習熟度が上がっていきますね. 特に, はてなはGolangが得意なエンジニアが多いので, そういった方々から丁寧なレビューやアドバイスを受けることが出来るので, 徐々にですが理解が深まってきています.

今後はGolangネタもちまちまとブログに書いていけると良いかなと思っています. 目下の課題はGoroutineを理解するところなので, そこでの学びとか, 書いていけたら良いかなーと思っています.