【読書メモ】「成長する企業はなぜ SSO を導入するのか」

最近チームのメンバーが誕生日で、よくバラエティ番組で流れる曲「Happy Birthday - Stevie Wonder」が頭から離れない sekitats です。

今月は個人的に認証について学ぶ月間で、本を3冊読みました。認証周りわからんことばかりだったので。

OAuth については、別記事を書いてみたのでそちらも興味があれば読んでみてください。

ratatatat30.hatenablog.jp

2冊目の Auth0 + Nuxt + Rails のデモも試した。

本記事は3冊目「成長する企業はなぜ SSO を導入するのか」の要約となります。
引用元:日本ヒューレット・パッカード株式会社 (著) . 『成長する企業はなぜSSOを導入するのか 』. 日経BP, 2017

なぜ、この本を読んだのかというと、SSO に関する本を amazon で検索したら、本書しかなかったからです。(あとはミリタリーバックパック

認証はすでに経営課題

以下のような企業における認証の課題があげられている。

  • 社員のパスワードの使い回しによってパスワード盗難リスクが高まる。企業側の危機意識が低い
  • 厳しすぎるパスワードポリシーが返って生産性を低下させる
  • 個々の業務システムの担当者は、自分が担当している業務システムだけを考えて対策を立ててしまう傾向にある → サイロ化
  • サイロ化した中で認証強化してもそれは「部分最適化」でしかない。「全体最適化」とは程遠い。

    ※ サイロ化:企業内にある部門が他部門との連携をすることなく、自らの業務の部分最適化のみを優先するようになった状態をいう。元々サイロとは穀物などを貯蔵するタンクのことだが、英語圏では「窓がなく周囲が見えない」という意味も含んでいる。

出ました。サイロ化。大規模になればなるほどサイロ化の弊害は大きくなっていく。

企業経営にまで影響を与える問題となっているということ。

パスワード認証の課題

ユーザーの本人確認を行う認証にも問題は多い。

  • 他人に知られた場合になりすましが可能
  • 安易なパスワードの場合類推や解読が容易
  • 忘れたり間違えたりしやすい
  • 複雑なパスワードは記憶が困難
  • パスワードの使い回しにより、安全性が低下

パスワード認証は、「知られない」、「推測されない」、「同じものを使い続けない」、「同じものを使わない」といった「努力」をユーザーに強いていて、その「努力」には限界がある。

パスワード認証を強化する他要素認証(ワンタイムパスワード、生体認証)も導入が難しい。

そんな、企業の課題、ユーザーの課題を SSO(シングルサインオン)が解決してくれると言うてます。

SSO 導入メリット

  • SSO とは、業務システムで個別に行っている認証を一元化し、ユーザーがいずれかのシステムを利用する際に認証を一度行えば、連携している全てのシステムが利用できるようになる。ユーザー ID,パスワード、ユーザー属性などのユーザー情報の管理や、問い合わせ対応の負荷が軽減される。
  • SSO が導入されるということは、入口が1カ所で管理されるということ。唯一の入口に防犯対策をを一本化できる。情報漏洩の防止策として SSO は役に立つ。
  • 新規に導入する業務システムだけでなく、既存の業務システムにも SSO は効果を発揮する。既存の業務システムで管理されているユーザー情報に大きな変更を加えないため、導入も用意で短期間かつ少ない労力で導入できる
  • 導入によってユーザーの利便性が向上するだけでなく、認証に関する管理の負荷も軽減される。
  • 今後登場する未知のクラウドサービスの導入と行った変化にも柔軟に対応できる
  • 各業務システム間のサイロ化の課題も、個々の業務システム担当者に大きな負担を強いることなく解決でき、IT 投資を効率化できる。

なんのことはない。一つのユーザーID・パスワードだけ管理できるようになれば問題は解決する。

SSO の 4 つの方式と特徴

方式には「リバースプロキシ方式」、「エージェント方式」、「クライアントエージェント方式」「フェデレーション」の 4 つ紹介されているが、最初の 3 つはオンプレミスでSSOを用意する方式。クラウドサービスを利用するものが「フェデレーション」。SSO = フェデレーションと捉えてしまってよい。

フェデレーションの仕組み

フェデレーションの仕組みの一つとして「SAML」や「OpenID Connect」といった。「標準規約」が用意されている。
SAML とは(Security Assertion Markup Language)の頭文字で、OASIS(Organization for the Advancement of Structured Information Standards)が定めた、クラウドサービスと企業の間で認証の連携を行う標準規格のこと。ほとんどのクラウドサービスがこの SAML に対応しており、クラウドサービスと認証の連携を行う場合は、SAML を利用することが多い。

OpenID Connect つまり JWT を使うこともできるのだろう。が、SSO では SAML を使う。

SSO(フェデレーション) はシンプル

本書では、フェデレーションの仕組みをパスポートの仕組みに例えて説明している。

パスポートは所持する本人の国籍の国で発行され、その発行には比較的厳格な本人確認、つまりユーザーの認証が求められる。 ただし、一旦パスポートが発行されれば、渡航先の国ではパスポート自体が本人確認となる。 入国の際にパスポート以外の本人確認の手続きは必要とされない。

f:id:sekilberg:20210713002050p:plain

  1. IdP(IdentityProvider)で厳格な本人確認をする
  2. IdP がアサーションSAML = パスポート)を発行
  3. アサーションがブラウザを介して SP(Service Provider = アプリケーション)に提示される
  4. アサーションの正当性と信頼した IdP による発行かどうかを SP が確認する
  5. SP がユーザーに利用を許可する

SAMLアサーションがパスポートと異なるのは、一度発行されたアサーションは特定の SP へのログインにしか使えないこと。SP 毎にアサーションを発行することが必要。(これは SAMLの仕様)


IdP による厳格な審査を通過していることとSPとの信頼関係によって成り立っているわけですね。

おまけ

いきなり、IdP(IdentityProvider)、SP(Service Provider)といった用語が出てきました。 OAuth(= 認可)の世界での登場人物は、リソースオーナー、クライアント、認可サーバー、リソースサーバーですが、OpenID Connect や SAML(= 認証)の世界になるとユーザー、SP、IdPといった用語になるところも混乱しがちなところです。(トークン→アサーションとか)

まとめ

そもそも技術書ではないし、SSO導入事例、オンプレ導入方法といった企業の経営者や情報システム担当者向けの内容だったので、OneLogin, okta などの IDaaS に関するお目当ての情報はなかった。
ただ、SSOの概要は理解できました。特にパスポートに例えた説明がわかりやすく、OAuth に比べずっとシンプルに感じました。(どう実装するかは別として。。)SSO=パスポートの仕組みということがわかっただけでも収穫アリですね。

SAML に関してはほとんど説明されていませんが、id token のような個人情報が XML 形式になっただけと捉えれば良いかと思います。

近い将来 SSO による生体認証が当たり前になって、フォームに E メール, パスワードを入力していたことが時代遅れになる未来もそう遠くないのかもしれません。

鬼○の刃で学ぶ OAuth

OAuth を身近なものでわかりやすく説明できないか。
ブログ記事にするなら面白い記事にしようと思った矢先、点と点が一本の線で繋がりました。

OAuth は 鬼滅の刃で説明できる。

今や国民的アニメとなった「鬼滅の刃

柱一同が会する、鬼滅の刃の第22話「お館様」は OAuth でできていた。

※ 注意

初心者向けの内容となっています。
順番が前後しています。(OAuth は順番があります。)
初心者が OAuth を理解するために無理矢理こじつけた内容なので、OAuth についてきちんと学びたい方は独自で調べてみてください。

登場人物の紹介

  • リソースオーナー(○館様)

ユーザーです。リソースオーナーはリソースの所有者。リソースに対して全ての操作の決定権を持ちます。

  • クライアント(炭○郎)

主にあなたが作るサービス(サードパーティアプリ)のことです。リソースオーナーはクライアント経由でリソースアクセスします。

  • 認可サーバー(鱗○さん)

リソースオーナーの同意を得る。アクセストークンを発行します。例. GoogleFacebook などの OAuth サーバー

  • リソースサーバー(は○ら)

リソースオーナーが許可したアクセスのみを受け入れます。その手段がアクセストークンです。

f:id:sekilberg:20210712221601p:plain

引用元:(C)吾峠呼世晴集英社アニプレックスufotable.

第22話「お館様」

目が覚めると、そこにはリソースサーバー(は○ら)がいました。

f:id:sekilberg:20210712221806p:plain
炭○郎
は○ら?はし○って何だ?何のことだ。この人たちは誰なんだ?ここはどこだ!?
f:id:sekilberg:20210712221548p:plain
は○ら
ここは鬼○隊の本部です。


⑤クライアント(炭○郎)からリソースサーバー(は○ら)へのアクセス。

f:id:sekilberg:20210712221758p:plain
○蝶
なぜ鬼○隊員でありながら、鬼を連れているんですか?
f:id:sekilberg:20210712221806p:plain
炭○郎
妹は鬼になったけど、人を食ったことは無いんです
f:id:sekilberg:20210712221551p:plain
○黒
くだらない妄言を吐き散らすな。そもそも身内ならかばって当たり前。言うこと全て信用できない。俺は信用しない


リソースサーバー(は○ら)は、クライアント(炭○郎)が悪意のあるアプリケーション(人食い鬼を連れているの)ではないかと疑っています。 401 エラーが返っています。

f:id:sekilberg:20210712221620p:plain
○髄
口先だけでなくド派手に証明して見せろ!
f:id:sekilberg:20210712221555p:plain
甘○寺
あの~、でも疑問があるんですけど……○館様がこのことを把握してないとは思えないです。勝手に処分しちゃっていいんでしょうか?


⑤クライアント(炭○郎)は、リソースの追加(禰󠄀○子を鬼○隊として入隊)を要求をします。

f:id:sekilberg:20210712221806p:plain
炭○郎
妹は……妹は俺と一緒に戦えます 鬼○隊として、人を守るために戦えるんです
f:id:sekilberg:20210712221610p:plain
不○川
鬼が何だって?坊主ゥ。鬼○隊として人を守るために戦えるゥ?そんなことはなァ ありえねぇんだよ馬鹿がァ


また、401 エラーが返っています。

f:id:sekilberg:20210712221544p:plain
子供たち
○館様のお成りです


ここで、リソースオーナー(○館様)が登場します。全ての権限はこの人にあります。
※ 順番は前後していますが、こじつけなので目を瞑ってください。

f:id:sekilberg:20210712221607p:plain
○館様
そうだね。驚かせてしまってすまなかった。炭○郎と禰󠄀○子のことは私が容認していた。そして、みんなにも認めて欲しいと思っている。


③ リソースオーナー(○館様)は、クライアント(炭○郎)へのアクセス権の委譲(禰󠄀○子の鬼○隊への入隊)について同意(容認)している。

f:id:sekilberg:20210712221802p:plain
○獄
心より尊敬する○館様であるが、理解できないお考えだ。全力で反対する!


⑤それでもまだリソースサーバー(は○ら)はリソースへのアクセス(禰󠄀○子の入隊)を許可しません。(反対します)

f:id:sekilberg:20210712221607p:plain
○館様
手紙を


④ 認可サーバー(鱗○さん)からのアクセストークン(飢餓状態であっても人を食わず、そのまま2年以上の歳月が経過したという事実。証明)の発行。(を読み上げる。)

f:id:sekilberg:20210712221616p:plain
鱗○さん
炭○郎が、鬼の妹とともにあることをどうかお許しください。禰󠄀○子は強靭な精神力で人としての理性を保っています。


晴れて、クライアント(炭○郎)は認可サーバー(鱗○さん)のアクセストークン(手紙の内容)を持ってリソース(鬼○隊に禰󠄀○子)の追加(入隊)を許可されました。

⓪は、○館様が炭○郎と禰󠄀○子の存在を認識していること。
①は、過去に炭○郎と禰󠄀○子が鱗○さんの元を訪れていること。
②は、鱗○さんから○館様への手紙。

と考えると良いかとおもいます。

この後、不○川が禰󠄀○子を屋敷にあげて禰󠄀○子が人を食わないことを証明するくだりは、アクセストークン(手紙の内容)に不正がないかリソースサーバーが検証するくだりと捉えてもよいでしょう。

まとめ

おわかりいただけただろうか。

柱合裁判とは OAuth でできていたのである。

鬼を連れているというところが、悪意あるサービスかもしれないサードパーティアプリの表現にぴったりですね。

順番が前後していますが、登場人物や役割(ロール)のイメージはしやすいのではないでしょうか。 クライアントからリソースを操作するまでの間にこんなドラマがあると思えば、分かりづらい OAuth の理解もしやすいのではないかと思います。

ぜひ、アニメを見返しながら読んでください。

Autify を使ってみた所感と Puppeteer と Playwright

sekitats です。

さて、back check では E2Eテストツール Autify が導入されました。

f:id:sekilberg:20210613194119p:plain

1日触ってみたので所感を書きたいと思います。

よかった点

まず、海外発サービスかと思いきや、日本人が作った感のある馴染みやすいUIが良い。

シナリオ作成では、ブラウザでの操作をそのままレコーディングしてテストシナリオとして保存できるのが画期的だ。すぐに使い方を覚えることができた。 これであれば誰でもテストシナリオを書くことができるだろう。

そして、何よりクロスブラウザテストをサポートしているところが嬉しい。これだけで導入するだけの価値はある。

また、AI技術を使って変更の差分を検出するなど、きめ細かなサポートが素晴らしい。

ダミーのメールアドレスを生成してそれを使いまわせるのが便利だし、開発者にとっては JavaScript でコードを実行できるのも柔軟さがあっていい。

気になった点

使い心地で不便を感じたのは、シナリオ作成途中で修正が発生した場合、基本的にブラウザでレコーディングをする以外の方法がないことだ。

それから、例えば、コードであれば当然あるシナリオをコメントアウトやスキップするなりして一部のシナリオを実行させないことができる。一部シナリオを無効化するなどできると嬉しいと感じた。

細かくシナリオを区切ってパーツ化したとしても、最終的に一つのテストプランに書き出すマスタリングのような工程が必要なため、つぎはぎのままではテストを実行できない。

それから、ローカルでの設定、ステージングでの設定など、設定を簡単に切り替えられるのもコードなら簡単にできる。

テストが異常終了した場合もコンソール上であれば分かりやすい。

それなら Autify である必要がないのはもっともだ。

結局、細かいところの制御はコードには勝てない。

要は用途によって使い分けるべきということでしょうか。

しかし、E2Eテストをここまで進化させた Autify を応援したい気持ちでいっぱいです。Autify の更なる進化に期待せざるを得ません。

Master of Puppeteer

f:id:sekilberg:20210613203131p:plain

私は Puppeteer でテストシナリオを書き始めた。Puppeteer は E2E テストフレームワークではないが、Autify で不便に感じたところを解消できそうな気がしたのである。

Puppeteer と聞くと、Metallica“Master of Puppets” が思い浮かぶ。 Metallica の代表的な曲であり海外では有名な曲なので聞いたことない人は一度聞いてみて損はない。(ギターリフを全て異常な速さのダウンピッキングで弾いていることでも有名)

話が脱線しましたが Puppeteer の tips を共有。

iframe 内の要素にアクセス

const frame = await page.frame().find(f => f.name() === 'preview-html')
const button = await frame.$('.button')

タブの切り替え

const pages = await browser.pages() // 全タブを取得
const newTab = pages[pages.length - 1] // 開いたタブを取得

新規タブが開いたあと画面がローディング中のまま進まないことがあった。 一度他のタブに切り替え、新規タブに切り替え直すとローディングから先に進むようになった。

const pages = await browser.pages() // 全タブを取得
...
const prevTab = pages[pages.length - 2] // 一個前のタブ
await prevTab.bringToFront() // 一個前のタブを前面に
await prevTab.waitForTimeout(2000) // 2秒待機
await newTab.bringToFront() // 開いたタブをもう一度選択する

クリップボードにコピー

const documentHandle = await page.evaluateHandle('document');
await page.evaluate((document) => {
    // documentHandle を渡すと evaluate 内でdocumentにアクセスできる
    const oneTimePass = document.getElementById('password').innerText
    navigator.clipboard.writeText(password)
}, documentHandle)
await documentHandle.dispose() // 使い終わったら破棄

クリップボードの中身を取得

const password = await page.evaluate(async () => {
    return await navigator.clipboard.readText()
})

ちなみにクリップボードのアクセスを許可しておかなければならない。

const browser = await puppeteer.launch()
await browser
  .defaultBrowserContext()
  .overridePermissions(' host名 ', ['clipboard-read'])

おまけ playwright も触ってみた

f:id:sekilberg:20210614131150p:plain

playwright とは

Playwrightとは、Microsoftが提供しているWebDriverやpuppeterと同じ種類の自動テスト用のライブラリです。2020年2月1日に、オープンソースで公開されました。ChromiumFirefoxWebKitといったブラウザの動作をプログラムで再現し、自動的にテストをすることができます。

ざっくりいうと puppeteer の制作チームが Microsoft に行って Chromium だけでなく Firefox, WebKit にも対応した新しいライブラリを作ろうってことで puppeteer の改良版 playwright を作ることになったてな感じでしょうか。

今回、最初から playwright で書けば良いのではと聞こえてきそうだが、“Master of Puppeteer” ってどうしても言いたかったのでよいのである。

puppeteer と Playwright との詳細な違いは他の記事に任せるとして、puppeteer とのざっくり変更点。browser インスタンス生成のところだけ変えただけでだいたい動いた。

const { chromium, webkit } = require('playwright');

const browser = await chromium.launch({ ...config })
const context = await this.browser.newContext()
await context.grantPermissions(['clipboard-read'], ' host名 ')

playwright になってタブの操作方法が変わった(以前の書き方でもできそうだが、context ってのを使うっぽい)

const [newPage] = await Promise.all([
  context.waitForEvent('page'),
  page.click('a[target="_blank"]') // Opens a new tab
])
await newPage.waitForLoadState();
console.log(await newPage.title());

(新規タブが開いたあと画面がローディング中のまま進まないところは以前として解決できない。これは他の原因がありそう。)

playwright について言えば、なんとユーザー操作からコードを生成するなんてことができるようだ。機会があれば使ってみて記事を書いてみたい。

まとめ

Autify は素晴らしいツールだ。人力でやっている非効率な作業から解放され、プロダクトの価値向上のためによりリソースを使える。こういったサービスがさらに進化し続け、世の中の負の解消になれば良いと思う。

他のE2Eテストフレームワークもどんどんと進化を続けている。 Karma によるブラウザの自動操作を初めて見たときは衝撃を受けた。もちろん Selenium もあったし、ヘッドレスブラウザに関しては、PhantomJS, CasperJS, Nightwatch.jsNightmare もあった。IEやレガシーEdge がなくなった世界になれば、E2Eテストはさらに楽になる。願ってやまない。

それから今回同じく E2Eテストフレームワークcypress も触ってみた。しかし、cypress は別タブ遷移ができないので痒いところに手が届かなそう、ということで断念。

結局何が言いたかったかというと、Metallica も E2Eテストでも何でも進化を止めてはいけない。という雑なまとめで締めたいと思う。

Date系ライブラリとIE11とタイムゾーン

sekitats です。backcheck で主に送りバントをしています。

さて、これまで backcheck では Date系ライブラリとして moment-timezone.js を使っていました。2020年9月 moment.js はすでにメンテナンスモードに入っており、backcheck ではこの度重い腰を上げて代替ライブラリへの移行をすることになりました。

以下の候補から最適なライブラリを選択するため調査を行いました。

  • date-fns (date-fns-tz)
  • Day.js
  • Luxon
  • js-joda(js-jodaについてはほぼ調査していませんが、念の為候補としてあげています。)

IE11 サポートとタイムゾーンの壁

前提として、Backcheck では IE11のブラウザ使用率が数%あり、IE11のサポートを完全に切ることができません。 選定の課題として IE11上でタイムゾーンの機能が正常に動作するかという点が必須項目となりました。

以下メリデメを表にしました。

ライブラリ名 メリット デメリット
Day.js ・他のライブラリと比べて最もファイルサイズが軽い
・moment に寄せて作られているため移行コストが最も安い
・開発継続性高い
・学習コストがほぼいらない
・IE11や timezone 関連のサポートの信頼性が低い(ライブラリの中では最もモダンブラウザに振り切ってる印象)
・IE11で意図した出力がされなかったため致命的と判断
date-fns(date-fns-tz) ・IE11での動作を確認
・採用しているプロジェクトが多い
・開発継続性高い。
・使用経験者がいる
・関数型設計のため、NuxtプロジェクトやPHPユーザーとは相性が悪い
・学習コストが要る
Luxon ・IE11での動作を確認
・moment.js のコントリビューターをしている人が作っているため後継として信頼性が高い
・Moment の後継であり開発継続性は高い
・IE11サポートに関するドキュメントが充実
・あまり人気がない
・使用経験者がいない
・学習コストが要る
js-joda - 独自実装のためIE9までサポートしている ・人気がない
・使用経験者がいない
java.time, Joda-Tome or Noda Time に慣れた人にはメリットだが、おそらくチーム的に不向き
・学習コストがいる

Luxon に決定 🎉

f:id:sekilberg:20210514111452j:plain
IE11で各種日付ライブラリを検証する

本命の Dayjs は、IE11ではタイムゾーン('Asia/Tokyo’)を指定した日時が意図した結果のになりませんでした。

date-fns (date-fns-tz)とLuxon はdate-fnsが標準時の表記(JST)、Luxon が IANA Time Zone 表記('Asia/Tokyo’)といった違いが出たものの日時は意図した時間が出力されました。 あとは好みや使い勝手といったところになってきますが Nuxt プロジェクトやPHPer との相性(Carbonの使用感との差)といった点で date-fns は脱落。最後に残ったのは Luxon でした。もともと Luxon は Moment.js のコントリビューターが作っているということもあり、IE11サポートのドキュメントも充実していてやはり安心感が違います。

polyfill

さて、IE11は UTC以外の特定のタイムゾーンをサポートしていません。IE11でタイムゾーンをサポートするためには polyfill が必要になります。

Option value ‘Asia/Tokyo’ for 'timeZone' is outside of valid range. Expected: ['UTC’]

https://stackoverflow.com/questions/54364061/ie-11-throwing-timezone-is-outside-of-valid-range-when-setting-timezone-to

IE11でタイムゾーンを扱う際の polyifll として date-time-format-timezone があります。しかし minified でも 2.64MBあり、そのままバンドルに含めると moment-timezone.jsよりもファイルサイズが増えてしまうため注意が必要です。さらにリポジトリアーカイブされており今後更新はされないため最新の polyfill を使うようにします。

最新のはこちら formatjs.io

すべて CDNから取得する場合は以下になります。polyfill.io は userAgent を見て polyfill が必要であるかを判断してファイルを返してくれるため、モダンブラウザで不要なファイルのロードをせずに済みます。

// nuxt.config.js
head: {
  script: [
    {
      src: ‘https://polyfill.io/v3/polyfill.min.js?features=Intl.~locale.ja,Intl.Locale,Intl.getCanonicalLocales,Intl.PluralRules.~locale.ja,Intl.NumberFormat,Intl.NumberFormat.~locale.ja,Intl.DateTimeFormat,Intl.DateTimeFormat.~locale.ja,Intl.NumberFormat.~locale.ja’ ,
      defer: true
    },
  ],
}

しかし、試してみたところ Intl.DateTimeFormat.~locale.ja のところで正しくロードできませんでした。 import する場合は下記のようになるかと思います。(そのほか必要な polyfill は適宜追加してください。 全てCDNにするか、全てimport にするかにしないと運用がたいへん。。)

// plugins/polyfill-datetimeformat.js
import { shouldPolyfill } from "@formatjs/intl-datetimeformat/should-polyfill";
(async function polyfill() {
  if (shouldPolyfill()) {
    try {
      const dataPolyfills = [
        import("@formatjs/intl-getcanonicallocales/polyfill"),
        import("@formatjs/intl-locale/polyfill"),
        import("@formatjs/intl-numberformat/polyfill"),
        import("@formatjs/intl-numberformat/locale-data/ja"),
        import("@formatjs/intl-pluralrules/polyfill"),
        import("@formatjs/intl-pluralrules/locale-data/ja"),
        import("@formatjs/intl-datetimeformat/polyfill"),
        import("@formatjs/intl-datetimeformat/locale-data/ja"),
        import("@formatjs/intl-datetimeformat/add-all-tz"),
      ];
      await Promise.all(dataPolyfills);
    } catch (e) {
      console.error(e);
    }
  }
})();

まとめ

IE11とタイムゾーンのサポートまでしているところはあまりないのではないでしょうか。タイムゾーンは日本で住んでいるとあまり意識することがありませんが、アプリケーションの世界では必ず必要になる概念であり、非常に学びの多いミッションでした。

代替ライブラリの選定にあたり、date-fns (date-fns-tz), Dayjs, Luxon, (js-joda) について多くの記事を調べましたが、IE11とタイムゾーンに言及した情報というのは見た限りはなかったと思います。この記事が有益な情報となれば幸いです。