読者です 読者をやめる 読者になる 読者になる

忙しい人のためのApp Transport Security (LT) | try! Swift Tokyo 2017 #tryswiftconf Day2-8 聞き起こし

try! Swift Tokyo 2017

twitter.com

WWDC2016にてATS(App Transport Security)の必須化がアナウンスされました。しかしご存知の通り、必須化は延期されました。また、iOS10で新たなATSの設定を行うInfo.plistのキーが導入されましたが、iOS10のマイナーバージョンごとに仕様が異なります。このLTでは、制度も情報も仕様も混乱しているATSを5分でマスターしていただくことに挑戦します。

忙しい人のためのApp Transport Security

f:id:niwatako:20170303161143j:plain

f:id:niwatako:20170303161202j:plain

f:id:niwatako:20170303161247j:plain

日本語で try! Swift のLive Blogを書いています。

f:id:niwatako:20170303161307j:plain

京都から来ました。

f:id:niwatako:20170303161316j:plain

京都には日本の文化や歴史を代表するものがたくさんあります。 この一面に金箔が貼られ建物(Pavilion)もその一つです。金閣と言います。 雪の中で輝いていて美しいですね!

f:id:niwatako:20170303161347j:plain

実は私の先祖が建てたそうです。 600年前に100億円もかかったそうです。 お金持ちですね。

f:id:niwatako:20170303161358j:plain

子孫の私はお金持ちではありませんが、ゴールドのMacBookを買いました。 こちらも、とても美しいですね。 気に入っています。

f:id:niwatako:20170303161412j:plain

私は “株式会社はてな” のiOSデベロッパーです。 日本における代表的なソーシャルブックマークサービスである “はてなブックマーク” のアプリを開発しています。

f:id:niwatako:20170303161424j:plain

今日は、AppTransportSecurityについてお話します。

f:id:niwatako:20170303161435j:plain

昨年のWWDCでApp Transport Securityの必須化が発表されました

f:id:niwatako:20170303161448j:plain

ところでApp Transport Security、ATSとは何でしょう。 これはiOS9で登場した機能です。

f:id:niwatako:20170303161459j:plain

ATSはアプリを作成したときからデフォルトで有効になっています

f:id:niwatako:20170303161511j:plain

ATSは、アプリが行うサーバーとの通信を 安全性の高いhttps だけに限定します。 それ以外の通信はブロックして、アプリの安全性を高めます。

f:id:niwatako:20170303161532j:plain

ところで、 httpsに 安全なも と 安全でないもの が ある というのはどういうことでしょうか?

f:id:niwatako:20170303161549j:plain

httpsにはハッシュアルゴリズム電子署名、暗号化などの技術の上に成り立っています。

Webサーバーが提供するこれらの技術が、古いものや、強度の弱いものであった場合、 https通信の安全性が低下してしまいます。

f:id:niwatako:20170303161607j:plain

developer.apple.com

そこでATSはある基準以上の 安全性を満たしたhttpsのみ 通信できるようにします。 詳しい基準については、AppleのInformation Property List Key Referenceを御覧ください。

f:id:niwatako:20170303161642j:plain

また、nscurlコマンドのats diagnosticsを利用すれば、 あるURLがATSの基準を満たしているかどうかを 調べることが出来ます。

f:id:niwatako:20170303161652j:plain

apple.comで試すと、ResultがPASSになります。

f:id:niwatako:20170303161655j:plain

swift.orgで試すと、ResultはFAILになります。 httpsなのにATSの条件を満たしていないことがわかります

f:id:niwatako:20170303161658j:plain

では、httpや、swift.orgなどの安全性の低いhttpsに接続したい場合は どうしたら良いでしょうか

f:id:niwatako:20170303161737j:plain

ATSのすべての機能を無効化する NSAllowsArbitraryLoads が用意されています。 Info.plistで設定することが出来ます。

f:id:niwatako:20170303161740j:plain

また、特定のドメインでのみATSを無効化すればよいのであれば、 NSExceptionDomainsを使って 特定のドメインのみをATSの例外にすることが出来ます。

f:id:niwatako:20170303161744j:plain

そして昨年のWWDCでは新しいオプションも登場しました

f:id:niwatako:20170303161747j:plain

AVFoundationの通信についてATSの制限を解除するNSAllowsArbitraryLoadsForMedia、

f:id:niwatako:20170303161751j:plain

そして UIWebViewやWKWebViewの通信についてATSの制限を解除する NSAllowsArbitraryLoadsInWebContent です。

f:id:niwatako:20170303161754j:plain

さらに iOS10が実際にリリースされたときには、 ローカルのホストに対する通信についてATSの制限を解除する NSAllowsLocalNetworking も加わっていました。

f:id:niwatako:20170303161838j:plain

iOS10 以降はこれらのオプションの中から適切なものを選ぶことが求められます。

f:id:niwatako:20170303161842j:plain

私のアプリは、 ユーザーがブックマークしたWebサイトを表示します。

サイトはhttpかもしれないし、httpsかもしれません。どちらも表示できるべきです。

そのためにはATSを無効化する必要がありますが、 WebViewが接続できれば良いので、ATSをすべて無効化する必要はありません。

f:id:niwatako:20170303161844j:plain

そこで私はWebViewだけを対象にATSを無効化する NSAllowsArbitraryLoadsInWebContent を試してみました すると厄介な問題を発見したのでご紹介します

f:id:niwatako:20170303161847j:plain

これは私がATSの仕様を説明するためによく利用する図です。

http、安全でないhttps、安全なhttpsに対して、 WKWebView、UIWebView、NSURLSessionが それぞれ接続可能かどうか この図を使って説明したいと思います。

f:id:niwatako:20170303161850j:plain

まず、なにも設定しておらずATSが有効になっている時 安全なHTTPSに対してのみ通信が出来ます。

f:id:niwatako:20170303161853j:plain

NSAllowsArbitraryLoadsはすべての通信が可能になります。

f:id:niwatako:20170303161856j:plain

では、次に NSAllowsArbitraryLoadsInWebContent を使ってみましょう。

(Thanks @d_date!!)

f:id:niwatako:20170303161950j:plain

こうなります。

f:id:niwatako:20170303161956j:plain

WKWebViewとUIWebViewから HTTPの通信が可能になりました。

f:id:niwatako:20170303161959j:plain

ところが、安全性の低いHTTPSには接続できないままです。 これは仕様でしょうか?

。。。これは、 iOS10.0 の場合です。

f:id:niwatako:20170303162003j:plain

iOS10.2 では、UIWebViewが 安全性の低いHTTPSに対して通信可能になりました。

f:id:niwatako:20170303162009j:plain

NSAllowsArbitraryLoadsInWebContentを利用しても 依然としてWKWebViewが安全性の低いHTTPSに接続できないのは バグです。

f:id:niwatako:20170303162012j:plain

これでは、NSAllowsArbitraryLoadsInWebContentは WebViewのATSを無効にするもの、というよりは “HTTP通信を許可” するものであって 言ってみれば AllowsHTTPLoadsInWebContent ということになります。

f:id:niwatako:20170303162015j:plain

このままではWKWebViewを使っている私のアプリは swift.org を表示する事ができません どうしたら良いでしょう

f:id:niwatako:20170303162019j:plain

それに、iOS10.1以下と

f:id:niwatako:20170303162021j:plain

iOS10.2以降で UIWebViewの挙動が変化するのもとても厄介です。 私たちはどうしたら良いのでしょうか。

f:id:niwatako:20170303162203j:plain

ところで、end of 2016から必須と言われたATSですが、

f:id:niwatako:20170303162206j:plain

結局必須化は延期されました。

f:id:niwatako:20170303162210j:plain

ですから、 現在はひとまず NSAllowsArbitraryLoads を使えば良いという事になります。 いろいろありましたが、結論としては、何もしなくて良いという答えになってしまいました。

f:id:niwatako:20170303162213j:plain

私が今日お伝えしたかった大切なことは、みなさんがATSに対応する際の注意事項です。

ATSには今日ご紹介したようなバグがあります。 ですから、Appleのドキュメントを信じるだけではダメです。実際にはバグでうまく動かないかもしれません。 また、実機でうまく動いたからといってそれがあるべき形で実装できているとも限りません。バグによってたまたまうまく動いているだけで、バグが直ると正しく動かなくなるかもしれません。 仕様と、実際の挙動の、両方を確認しましょう。 実際の挙動を確認するためには、iOSのマイナーバージョンごとに動作確認をしたほうが良いでしょう。

必須化(Enforcement)は延期されましたが、対応する際は今日お話したことを思い出していただきたいと思います

私の話は以上です。ご清聴ありがとうございました。