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

ターミナルでとにかくカレントディレクトリの .xcworkspace ファイルをXcodeで開くワンライナー

ターミナルで pod install とかしたらそのままターミナルからプロジェクトを開きたいですよね。

そういうときは open -a Xcode.app XXX.xcworkspace でプロジェクトを開けますね。でも、これ毎度入力するの面倒ですよね。

そこで、Dashとかに登録してスニペットにしたいですよね。

でもスニペットにするには XXX.xcworkspace ってのがプロジェクト毎にファイル名が異なるので難儀ですよね。

そこで ls した結果からうまいこと .xcworkspace を抽出して勝手に開いてくれるようにしたい。

(人によっては .xcodeproj かもしれないですが、今回はCocoaPodsとか使っていてワークスペースを作っている前提で。)

というわけでやってみました。

ls | grep -E \\.xcworkspace$ | xargs -J% open -a Xcode.app %

便利 ✧\\ ٩( 'ω' )و //✧

追記

もっとカジュアルにも出来るっぽい

ワイルドカード使えたのか...!

xcworkspace でも xcodeproj でもいけるワンライナー

力技...!

zshなら拡張子からファイル名を補完して楽に入力できる

標準のbashだと出来ないですが、zshだと拡張子でファイル名の入力補完が出来るみたいですね。便利!

mollifier.hatenablog.com

Alfredを使う

これですね↓ morishin.hatenablog.com

みなさんいろいろ技を持っているようです。ほかにもあったら教えてくださ〜い!!

【Apple iOS ATS】一部サイトではPV減も。NSAllowsArbitraryLoads とその InWebContent は違う件。

NSAllowsArbitraryLoadsInWebContent の挙動が予想外な件について(2016/12/13 13:26 最新のiOS10.2について追記あり)

お知らせ

App Transport Securityについて、こちらの勉強会でたっぷりお話しいたます。ご参加いただけますと幸いです。

nsstudy.connpass.com

いよいよApp Transport Security(ATS)必須化目前!

iOSアプリからのHTTP通信をブロックするセキュリティ機能、ATSの利用が、2016年の終わりからAppStoreへ提出されるアプリに必須化されます。

一時期、これによってHTTPサイトはアプリからのアクセスが激減する、とも言われました。しかし、Webブラウジング機能をもつアプリ向けに、WebViewについてはHTTP接続を許可するというオプションが提供されるため、多くのWebサイトは引き続きアプリからアクセスできるはずです。が、そうでない場合もありますという話です。

一部アプリが NSAllowsArbitraryLoadsInWebContent を採用開始。表示できないサイトが出ている。

2016/12/12 現在、WebViewのHTTP接続を許可するオプションである NSAllowsArbitraryLoadsInWebContentTwitterアプリが実際に採用したようですが、URLを開こうとした時にSSLエラーで表示できないケースが出ているようです。(追記: 2016/12/14リリースの6.68.1では改善されています。NSAllowsArbitraryLoads になったようです)

これらが発生するのは、 NSAllowsArbitraryLoadsInWebContent を利用した場合、ATSのHTTPS通信に関する制限が有効になるためです。

大まかにATSはHTTP通信をブロックすると説明しましたが、実は、ATSには一部基準を満たさないHTTPSをブロックする機能もあります。

iOS9時代からの NSAllowsArbitraryLoads (=ATSの無効化オプション)を利用していた場合、HTTPSの基準を含めて全てのATSの機能が無効化されていました。

しかしiOS10で登場した NSAllowsArbitraryLoadsInWebContent は、WebViewにHTTP接続を許可しつつ、HTTPSの基準は維持します。

(2016/12/13 13:17 追記: これはバグです。iOS10.2からUIWebViewはHTTPSの基準も無効化されました。iOS10.0以上iOS10.2未満のUIWebViewと、iOS10.0以上のWKWebViewでは依然HTTPSの基準は有効です。)

したがって NSAllowsArbitraryLoads だったアプリが、ATS必須化に備えて NSAllowsArbitraryLoadsInWebContent に移行すると、従来接続できていたWebサイトに接続できないケースが発生します。

※アプリのSSLエラーで困っている利用者の方へ

この記事はアプリ開発者、Webサイト運営者向けの内容です。アプリでSSLエラーが発生して困っているユーザーの方は、URLをコピーしてSafariに貼り付けて開く、またはリンクを長押しして「Safariで開く」を選択できないか試してみて下さい。ATSの問題でエラーとなっている場合は、Safariを使えばWebサイトの閲覧自体は可能です。

記事の概要

  • ATSについて大まかに説明
  • NSAllowsArbitraryLoadsInWebContent の特性を説明
  • 対応方法
    • Webサイト
      • Webサイトに求められるHTTPSの基準
      • Webサイトにアクセス可能か確認する手順
    • iOSアプリ
      • 検討すべきこと
  • 進捗どうですか

ATSについて、おさらい

問題を理解するために、いったんATSについて大まかに説明します。

ATSとは

ATSはiOS9から導入されました。ATSはアプリを作成するとデフォルトで有効になっています。ATSは次の2種類の通信をブロックするアプリ単位のセキュリティ機能です。

  • HTTP通信
  • 基準を満たさない一部のHTTPS通信

ATSは盗聴が可能なHTTPや、暗号の強度が弱いHTTPS通信を遮断して、アプリのユーザーが安心して利用できる通信しか行わないようにします。

ATSを無効化する NSAllowsArbitraryLoads

しかし、Webブラウジングを必要とするアプリで http:// で始まるURLのサイトがATSにブロックされてアクセスできないと困ります。

そこで、自由な通信が必要なアプリでATSを無効化するために、iOS9で用意されていたオプションが NSAllowsArbitraryLoads です。

NSAllowsArbitraryLoads を利用すると、どんなHTTPにも、どんなHTTPSにも(不正でない限り)接続することが出来るようになります。

けれども、ATSの機能が有効か、 NSAllowsArbitraryLoads を使って全て無効化するか、2択では大雑把すぎます。そこで、iOS10になってから、より必要最低限の制限だけを部分的に解除出来るように、新しいオプションが増えました。

NSAllowsArbitraryLoadsInWebContent はその一つで、WebViewについてのみ、HTTPに接続可能にするオプションです。

NSAllowsArbitraryLoadsInWebContent の登場と、ATSの必須化のアナウンス

NSAllowsArbitraryLoadsInWebContent などの登場できめ細かなATSの制限コントロールが出来るようになるのと同時に、ATSの必須化もアナウンスされました。

どのアプリもなるべく安全に、ATSの制限解除は必要最低限にとどめることが求められます。

(予定通りならば、)2016年末から、Appleがすべてのアプリについて、AppStoreに公開される前のアプリの審査で、ATSの設定が適切かどうかチェックするようになります。

NSAllowsArbitraryLoadsInWebContent のバグ

NSAllowsArbitraryLoadsInWebContent は名前の通り、AppleがWebブラウジングを必要とするアプリのために設計したATSのオプションだと考えられます。

ATS必須化後のレビューでは、おそらくWebブラウジング機能を持ったアプリは NSAllowsArbitraryLoads の代わりに NSAllowsArbitraryLoadsInWebContent を使うように要求されるようになると思われます。

しかし、 NSAllowsArbitraryLoadsInWebContent のほうが制限が厳しくなるバグが有り、冒頭で述べた通り、一部のHTTPSのサイトへの接続がブロックされます。

NSAllowsArbitraryLoadsNSAllowsArbitraryLoadsInWebContent が違うバグ

AppleのATSについてのドキュメントを見てみます。

NSAllowsArbitraryLoads のDescriptionにはこのような記述があります。

NOTE Disabling ATS allows connection regardless of HTTP or HTTPS configuration, allows connection to servers with lower Transport Layer Security (TLS) versions, and allows connection using cipher suites that do not support perfect forward secrecy (PFS).

この記述には、 "HTTP通信を許可し、ATSの基準を満たさないHTTPSの通信も許可する" ということが書かれています。

ここで重要なのが、 "ATSの基準を満たさないHTTPSの通信も許可する" という点です。

ATSはHTTP通信をブロックするだけでなく、HTTPS通信についても、低いTLSのバージョンやPerfect Forward Secrecyをサポートしていない暗号化スイートをブロックします(Cocoa Keys - Availability of ATS for Remote and Local Connections)。

HTTP通信に加えて、これらの一部のHTTPS通信まで含めて、 NSAllowsArbitraryLoads を使うと制限がなくなり、接続できるようになります。

さて、この記述が NSAllowsArbitraryLoadsInWebContent にはありません。

では、記述がないだけなのか、機能がないのか、不安になりますが、残念なことに機能があったりなかったりします。バグです。

"NSAllowsArbitraryLoadsInWebContent" が基準を満たさないHTTPSへの接続をブロックするバグ

Appleが意図しているのかわかりませんが、実際に動作を確認した限りでは、 NSAllowsArbitraryLoadsInWebContent は、ATSの基準を満たさないHTTPSの通信をブロックするようです。

たとえば https://swift.org/HTTPSのWebサイトですが、 2016/12/12 07:57 時点で Perfect Forward Secrecy に対応していません(暗号化スイートが AES_128_GCM であるため)。

NSAllowsArbitraryLoadsInWebContent を設定したアプリのWKWebViewからhttps://swift.org/へアクセスすると、表示できません。 WKWebViewのWKNavigationDelegateの webView(_ webView:didReceive challenge:completionHandler:) を実装しても呼ばれず、OSレベルで即通信が遮断されるようです。

NSAllowsArbitraryLoads を設定したアプリのWKWebViewからは https://swift.org/ に接続できます。

InWebContent がついているかどうかの字面から、てっきり制限のレベルは同じかと思いこんでしまいますが、実は、HTTPS通信についてはこのような制限の違いがあるのです(先月まで一緒だと信じていました)。(2016/12/13 13:26追記: そしてバグだった)

2016/12/13 13:26 追記

意図していないようです。これはバグです。

iOS10.2以降のUIWebViewは、ATSの基準を満たさないHTTPSの通信を許可するようになりました。WKWebViewは、依然としてATSの基準を満たさないHTTPS通信はブロックされます。

どうしたらいいのか

Webサイト運営者とアプリ開発者がすること

バグであることがわかったので、 NSAllowsArbitraryLoadsInWebContent によって一部HTTPSに接続できないiOSは減っていくと思われます。ただし、既にリリースされたiOS10.0, 10.1、そして10.2以降もWKWebViewについては一部のHTTPSに接続できないままです。

(この問題を無視する、という選択肢もありますが、)HTTPSのWebサイト運営者は、 NSAllowsArbitraryLoadsInWebContent を設定したアプリから無事Webサイトが閲覧できるように、対策をとっておく必要があります。

アプリ開発者は NSAllowsArbitraryLoadsInWebContent を自分のアプリで利用するのが適切かどうか判断する必要があります(もちろん、適切でないと判断してさらに制限を緩める場合、審査で説得を試みてみないと許可されるかどうかは分かりません)。

Webサイト運営者: 必要な基準と、Webサイトにアクセス可能かどうか確認する方法

サイト運営者は、サイトのセキュリティレベルをATSの基準を満たす水準にしましょう。

ATSがHTTPSに求める基準について

ATSの細かい基準についてはドキュメントのこの辺りに書かれています。

Cocoa Keys - Requirements for Connecting Using ATS

確認コマンド

このようなコマンドをMacで実行することで、URLのATS対応状況を確認できます。

nscurl --ats-diagnostics https://google.com/
HTTPSで基準を満たしている場合

このような出力があれば安心です。ATSが有効でも利用できます。

Default ATS Secure Connection
---
ATS Default Connection
Result : PASS
---
HTTPSで基準を満たしていない場合

HTTPSのサイトであるにも関わらず、FAILとなる場合、 NSAllowsArbitraryLoadsInWebContent が設定されたiOS10.0以上10.2未満のUIWebViewとiOS10.0以上のWKWebViewを利用したアプリからは接続できない、安全性の低いHTTPS通信になっています。

Default ATS Secure Connection
---
ATS Default Connection
2016-12-12 20:51:33.166 nscurl[52077:19714548] CFNetwork SSLHandshake failed (-9824)
2016-12-12 20:51:33.167 nscurl[52077:19714548] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9824)
Result : FAIL
---

このとき、TLSのバージョン基準を下げたり、PFS(Perfect Forward Secrecy)の基準を下げたりしてトライした場合の結果も表示してくれるので、FAILの場合に原因がどこにあるのかも探ることが出来ます。

HTTPの場合

HTTPのサイトであれば、ATSが有効なアプリからは接続できません。

NSAllowsArbitraryLoadsInWebContent が設定されたアプリからは接続することが出来ます。

アプリ開発者は?

バグだったようなので事態は複雑です。

  • UIWebView
    • iOS10.0以上10.2未満において、 NSAllowsArbitraryLoadsInWebContent を利用するとATS基準を満たさないHTTPSに接続できない
    • iOS10.2以上において、 NSAllowsArbitraryLoadsInWebContent を利用するとすべてのHTTPとHTTPSに接続できる
  • WKWebView
    • iOS10.0以上において、 NSAllowsArbitraryLoadsInWebContent を利用するとATS基準を満たさないHTTPSに接続できない
    • 今後どのバージョンからか、 NSAllowsArbitraryLoadsInWebContent を利用するとすべてのHTTPとHTTPSに接続できるようになるはずである

アプリ開発者は、アプリの仕様として、サポートするiOSのバージョンと、安全性が十分でない(ATSの基準を満たさない)HTTPSのサイトの利用をサポートすることが必須かどうか検討する必要があります。

Appleは、おそらく NSAllowsArbitraryLoadsInWebContent を利用してほしいのではないでしょうか。 HTTPSを利用しているにも関わらず脆弱性があるサイトには接続できるべきではないと考えているかもしれません(とはいえバグである可能性もある)。 (→バグだった)

しかし、iOS10.0からどのようなWebサイトにも接続できるようにしたい場合、 NSAllowsArbitraryLoads を利用する必要があります。その場合は NSAllowsArbitraryLoadsInWebContent よりも審査の基準が難しくなるかもしれません。

バグのあるiOSバージョンではATS基準を満たさないHTTPS接続のサポートを諦めるという選択肢も考えられます。もっと諦めてSFSafariViewControllerを利用する道もあります。

デリゲートでSSLエラーを検知したら、Safariで開く選択肢を提示するような方法も考えられます。ただし、その場合メインフレームで読み込んでいるURLのATSによるSSLエラーは検知できますが、開いているサイトが外部から読み込んでいるJavaScriptなどのリソースがATSによってブロックされたことを検知することは出来ません。正しく動作しない可能性のあるWebサイトをアプリもユーザーも気づかないまま表示するおそれがあるので、是非について検討が必要です。

WebViewの利用目的がある程度限定されていて、特にこのサイトにはどうしても接続したい、というURLがある場合は、 NSAllowsArbitraryLoadsInWebContent を利用した上で、 NSExceptionDomains でそのサイトだけ接続できるような設定を利用するのがより良い手段だと思います。

バグの可能性もまだある バグだった

ドキュメントにおいて、 NSAllowsArbitraryLoadsInWebContent のDescriptionには次のように書かれています。

Set this key’s value to YES to obtain exemption from ATS policies in your app’s web views

このキーを設定するとアプリ内のWebViewがATSのポリシーの免除を受けられる、と書かれているので、HTTPS通信制限はATSのポリシーの一部ではないのか!!と突っ込みたくなります(とはいえ私は英語がわからないのでニュアンス的には文句言えない言い回しなのかもしれない)。

バグかもしれないし、バグではないのかもしれない。

2016/12/13 13:26 追記

バグでした。

↑フォーラムを見ると、バグが治るまで NSAllowsArbitraryLoads を使ってね、と書いているので、もしWKWebViewのバグが治らないままならば NSAllowsArbitraryLoads を利用しても審査で問題にならないかもしれない。

こうなって欲しいと思っていた

脆弱なHTTPSを駆逐したい気持ちもわかりますが、アプリとしてはそれでは不便な場合もあります。

ATSは、ドメイン毎に細かい条件を指定する事ができますが、これを "WebContent向けの細かい条件" のような切り口で設定できるようになったら良いのにな、と思ったのでした。

みんなでバグレポートを送ったら何か変わるかもしれない。

しかし、iOS10.1まではもう正式にリリースされてしまっているので、バグでも、改善がなされても、もうどうしようもないのですが。

ところでiOS開発者のみなさま進捗、どうですか?

TwitteriOS開発者の皆様にATS対応状況のアンケートをとってみました。まだ着手していない人も多数。案外対応は順調な方も多いようです。

f:id:niwatako:20161212202349p:plain

明日までですが投票はこちらから → にわタコ on Twitter: "ATS(App Transport Security)対応、進捗どうですか?"

App Extension 上で UINavigationBar.appearance() が HostApp から影響を受ける問題を回避する

ちょっとマニアックな情報ですが、ドキュメントのどこにも書かれていないとっておきのネタです。

Action Extension、またはShare Extensionを開発していて、UINavigationBarを利用しているという方はぜひご覧ください。


この記事は Cocoa Advent Calendar 2016 6日目の記事です。昨日の記事はnaochi___さんの[iOS] Xibを使って自前のダイアログを作るでした。

この記事では、id:kaniza さんの4日目の記事 第 70 回 Cocoa 勉強会関西に行ってきた - kanizaのブログ で触れられている、 第70回 Cocoa勉強会関西 で私が発表した内容について書きます。

"App Extension 上で UINavigationBar.appearance() が HostApp の影響を受ける問題" とは?

このような画面のAction Extensionを作成したとします。以降このTargetを"Action" Extensionと呼びます。

f:id:niwatako:20161204190651j:plain

NavigationBarのBar Tintがオレンジに、DoneボタンのTintが白になっています。

f:id:niwatako:20161204190655j:plain

予定では、このエクステンションを起動するとこのような画面になるはずです。ここで見えているオレンジ色のNavigationBarがこの問題の主役です。

f:id:niwatako:20161204190658j:plain

実際に起動するとどうなるでしょうか。Safari上で試してみます。共有ボタンから開いたアクションシートで今作成した "Action" Extensionを開きます。すると設定通りの画面が表示されます。

f:id:niwatako:20161204190702j:plain

同じことをPocketというアプリの上でやってみます。共有ボタンから "次を使用して共有:" を選んで開いたアクションシートで、"Action" Extensionを開きます。そうすると今度は、NavigationBarが意図した色になっていません。

f:id:niwatako:20161204190705j:plain

これが "AppExtension上でUINavigationBar.appearance()がHostAppの影響を受ける問題" です。

何が原因か

原因は UINavigationBar.appearance() 周りにあります。

Pocket上でNavigationBarが白くなってしまったのは、Pocketが自身のアプリ上のNavigationBarの見た目をカスタマイズするために、UINavigationBar.appearance().barTintColorを白に設定しているため、と考えられます。

f:id:niwatako:20161204190708j:plain

試しにUINavigationBar.appearance().barTintColorを赤にするアプリを自作し、そのアプリからExtensionを起動すると、今度はNavigationBarが赤くなります。

UIAppearanceの設定は、そのアプリ上で利用するApp Extensionにまで影響を及ぼすのです。

f:id:niwatako:20161204190712j:plain

この問題にどうやって対応するのか

この問題を防ぐ方法は、密かにiOS10から利用できるようになっています。App ExtensionのInfo.plistに設定することが出来る NSExtensionOverridesHostUIAppearance キーです。 NSExtensionのDictionaryの中にBooleanでYESを設定します。

f:id:niwatako:20161204190716j:plain

これを設定した "Action" Extensionをもう一度Pocket上で起動してみます。すると、今度は意図した通りのカラーでNavigationBarが表示されました。

f:id:niwatako:20161204190719j:plain

この NSExtensionOverridesHostUIAppearance については、ドキュメントには書かれていません。しかしiOS10から機能します。また、このキーを利用してもAppStoreの審査で問題になることはありません。

UINavigationBar.appearance()がHostAppの影響を受ける問題はShare Extensionでも発生します。Extension上でUINavigationBarを利用している場合は、Info.plistに NSExtensionOverridesHostUIAppearance を追加しておくと良いと思います。

参考

ここのIssueでも言及されています。調査中ステータスのままですが。

github.com

インターネット上で NSExtensionOverridesHostUIAppearance に言及しているサイトはこの記事が2番目のはず...