コーポレートエンジニアリング部の id:sora_hです *1。今回は 3 ヵ月ほど前に実施した、Google Workspace テナントのプライマリドメイン変更について、記録を兼ねて説明します。
クックパッドは 2009 年頃 *2より Google Workspace *3を利用しています。当社の対外的なメールアドレスは cookpad.com ですが、Google ではプライマリドメインとして cookpad.jp が設定されています。各ユーザーには cookpad.com のアドレスを別名 (エイリアス) として登録されていて、メールアドレスとしては cookpad.com を利用、ただ Google へログインする時だけ cookpad.jp を利用する運用になっていました。想像が出来ると思いますが、これが様々な面で不便・混乱を発生させていました。どうしてこうなった…*4。
この負債を解決すべく、2022/8 頃から緩やかに準備を始め、2023/3 上旬に全ユーザーのドメインとプライマリドメインを cookpad.com に変更しました。本稿では変更に踏み切った理由から下準備、当日~事後の作業について解説します。そこそこ長く様々なタスクがあったため乱雑な記事となっていますが、何かの役に立てば幸いです。
- 変更のモチベーション
- Google Workspace におけるドメインとは
- 目標: 影響を最小に抑える
- プロジェクトの流れ
- 事前準備: 各種サービス (SaaS) の影響確認
- 事前準備: 内製システムの準備
- 事前準備: メール受信ダウンタイムの影響を最小化する
- 事前準備: 作業用データの準備
- 作業当日: プライマリドメイン変更作業
- 事後作業
- 社内アナウンスについて
- 振り返り
- Acknowledgements
変更のモチベーション
これは多岐にわたるため、代表的なものを箇条書きで説明します:
- ユーザーから見てメールアドレスやアカウント名が cookpad.com と cookpad.jp の 2 種類を持つことになり混乱する
- 対外的なメールアドレスは cookpad.com であるべきだが cookpad.jp を利用してしまう
- 逆に Google アカウントは cookpad.jp なのに cookpad.com を入力してエラーになってしまう
- クックパッドは Azure AD を併用していて *5、そちらは cookpad.com であるため、同様に混乱する
- Google ログインから Azure AD の SAML に切り替えた場合 SAML 上は cookpad.jp を名乗らせる必要がある (もしくは後述のように頑張って変更作業を行う)。
- Slack が当初 Google ログインによって cookpad.jp の利用であったため *6、Slack Connect の招待を cookpad.com のアドレスへ送信されると Slack アプリ上でそれを受諾することができない、などなど各種アプリでの不都合
- cookpad.com (メールアドレス, Azure AD) と cookpad.jp (Google) の意味に違いがあるため、社内システム各所の実装で読み替えなどの考慮が必要
- 各位の認識とその実装がまちまちで不具合が…
- Google Workspace のプライマリドメインを変更できなくなる条件を満たしてしまうサービスを利用できない (Chrome OS の MDM など)
ただし、本稿が非常に長いことから分かるように、丁寧な調査と作業を行わなければ様々な問題が発生してしまうため、腰がたいへん重いものでした。業務で Chrome OS を一部で利用していることから Chrome OS の MDM を検討するのが再検討のキッカケとして大きな要因でした。
Google Workspace におけるドメインとは
前提として、Google Workspace におけるドメインについて軽く解説します。
Google Workspace 配下のユーザーはテナントに登録されているドメインを利用します。各 Google Workspace テナントは複数のドメインが登録でき、それを配下のユーザーに設定します。
登録されているドメインの 1 つをプライマリドメインに指定し、デフォルトかつテナントを示すドメインとして各所で利用されます。その上で、プライマリドメイン以外にセカンダリドメインも設定してユーザーごとに使い分けることが可能になっています。
エイリアス
Google Workspace ユーザー/グループにはエイリアスを設定できます。エイリアスとして(異なるユーザー名・ドメインを持つ)別のメールアドレスを追加し、そのメールアドレスでもメールを送受信できるようになります *7。
そして、ユーザー・グループ単位に設定するエイリアスとは別にドメインエイリアスも利用できます。ドメインエイリアスはその名の通りドメイン全体に対して他のドメインを別名として登録するもので、ユーザー・グループにエイリアスとして登録せずとも、エイリアスが存在するドメインでアドレスが存在していれば、そのドメインエイリアスでもメールの送受信が可能になります。
ドメインエイリアスはプライマリドメインを含むテナントのドメインに対して追加するものです。そのためドメインエイリアスはユーザーの(プライマリの)メールアドレスとして直接割り当てることが不可能になっています。
Cookpad における Google Workspace ドメイン設定
本プロジェクト以前の Google Workspace のドメインは、ざっくり以下のようになっていました。
- cookpad.jp (プライマリドメイン)
- cookpad.com (ドメインエイリアス)
- {その他個別のエイリアスで利用する前提の細々としたドメイン} *8
冒頭で書いたように、cookpad.jp がプライマリドメイン・全ユーザー/グループのドメインに設定されています。cookpad.com をメールアドレスとして利用するため、cookpad.com は cookpad.jp に対するドメインエイリアスになっていました。
本プロジェクトでは cookpad.com をプライマリドメインに変更することが最終目的です。察しの良い方は気付くと思いますが、変更先のドメインがドメインエイリアスとして既に設定されていることで、まあまあ苦労します。
プライマリドメインまで変更するかどうか
ユーザーが利用する = ユーザーの Google アカウントとなるドメインを変更するだけであればプライマリドメインの変更は必須ではありません。ただ、Google Cloud Platform の組織名など各所で混乱を残してしまうこと、変更しない理由もないこと、Google の OAuth2/OIDC の hd オプションの挙動がイマイチになる *9。ことから今回はユーザーのドメインに加え、プライマリドメインまで変更を行いました。
プライマリドメインについては上記ヘルプに記載されているように「変更できない」条件が存在します。そのうちの大きな物が Chrome Enterprise や Chrome OS 端末をエンロールしているという点で、これはモチベーションの 1 つとなっていたため、後戻り出来なくなる前に済ませたかったため踏み切りました。
目標: 影響を最小に抑える
ユーザー・グループのドメインを変更するだけなら Google Workspace のドキュメント通りに作業するだけなので簡単ですが、それだけで済むはずがありません。本プロジェクトには各種サービス断など影響を最小限に抑えることが大きな目標としてありました。これは下記が含まれます:
- メール:受信が出来ない時間を短く抑える。出来ない場合でもその影響を最小にする
- ログイン連携の継続: Google アカウントでログインしている各種サービスへのアクセスを損わないようにする。ログインしたら新規ユーザーになってしまう、といったトラブルを回避する
- 混乱を避ける:各種アナウンスをきっちり行いユーザーの混乱を避ける。特に強制ログアウトが発生した場合に備える
特に Google の OAuth2/OIDC を利用してログインを行っている各種 SaaS への影響が心配でした。真っ当に実装していれば sub クレームを利用してユーザー検索を行う実装になるはず *10です。
ただ、OIDC や OAuth2 + userinfo API で得た email を元にユーザーを検索している不届きなサービスは確実に存在します (しました)。万が一業務でそのようなサービスが利用されていた場合 (いました)、業務に影響が生じてしまうため、それらについては事前に対策を行う必要があります。
プロジェクトの流れ
本プロジェクトは下記の手順で進行しました。冒頭に記載した通り 2022/8 ~ 2023/2 頃まで緩やかに準備、2023/3 上旬に一気に片付けるようなスケジュールです。
- 事前準備: 各種サービス (SaaS)、社内(内製)システムへの影響を確認、必要な作業についてアナウンスを準備
- 事前準備: 検証環境 (Google Workspace テナントなど) を用意して各種挙動のチェック、ユーザー・グループ情報変更に利用するスクリプトの準備
- 各自作業: 事前にアナウンスした各種サービスで必要な対応を各自で実施
- 直前作業: 各種サービスで必要な対応を実施
- 本番作業: 本番 Google Workspace テナントの変更作業
- 事後作業: 各種サービスで必要な対応を実施
- 事前準備: 各種サービス (SaaS) の影響確認
事前準備: 各種サービス (SaaS) の影響確認
というわけで、本プロジェクトでまず最初に行ったのは各種サービスでの影響・必要なアクションを確認することです。プロジェクトの大半の期間は地道に順次この点検を行っていた気がします。
Google Admin から利用履歴のある OAuth2 Client のリストを取得できるため、取得した上で業務で利用している・されていそうな *11サービスのリストを作成しました。およそ 30 サービスがリストアップされ、順次サポートに聞く、検証環境でちょっとアカウントリネームしてみて動作を試してみる…というのを地道に行います。
すると、やはり下記のようにさまざまなパターンで対応を求められることが分かってきました。
- 何も対応する必要はない (ログインしなおせばメールアドレスの変更が自動で反映される)
- 事前に各自でメールアドレスを変更しておく必要がある
- 事前に管理者が手動でメールアドレスを 1 ユーザーずつ変更して回る必要がある
- 事前に管理者が新しいドメインを allowlist に追加したり所有権の検証を済ませておく必要がある
- 管理者からドメイン変更を伝えたらまとめてサポートに変更してもらえる
- 管理者で新旧が分かる csv をサポートに提出したら変更してもらえる
- 管理者でユーザーを一度削除して再招待しなければいけない
- ログイン自体はリネーム後でも継続して行えるが、メールアドレス変更は手動で各自が行う必要がある
はい、真面目に OIDC 仕様通りにログインを実装してないところがあまりにも多すぎて本当に困ります。OIDC プロバイダから得られるメールアドレスを信用してそれでしかマッチングをしないのはあまりにも雑実装すぎます *12。
今回のプライマリドメイン変更では新規にドメインを取得してそれを変更するわけではなく、10 年ほど平行して両ドメインともメールアドレスとして使ってきた *13関係で、人によっては cookpad.jp → cookpad.com に管理者やサポートでリネームしようとしたらコンフリクトしてしまった! という事例がかなり発生しやすい状況です *14。これについても問合せを行い、下記のようなパターンが分かってきました。
そもそも企業が利用することを前提としているサービスでもドメインのリネームやユーザー名のリネームがある旨をサポートに伝えてもなかなか理解してもらえないことが多くて結構困ってしまうところです。ドメインだけじゃなくてユーザー名もわりと変わることがあるので…。SAML ならともかく OAuth2/OIDC を利用してるなら sub claim を適切に利用してほしい (重要な事なので何度でも書きます)。
まず、事前に各自で作業が必要なサービスについては事前にリストアップ・作業内容を Wiki に記載して全社アナウンスで各自の点検を依頼します。各自で作業が必要ないサービスでも、変更作業中は新規ログインができない可能性があり、それについては全て手元の端末でログインができているか確認するように記述しました。
当日に複雑な対応をしなければならなかったいくつかのサービスについては、後述する変更作業の節で解説します。
なお、Google Workspace コアサービス以外の Google のサービスについては GCP を含めて現在まで大きな問題は報告されていません。こちらの事前調査もサポートを通して行いたかったところ、コアサービスでないことから Google Workspace のサポートからは返答を貰えず各サービスのサポートへ誘導され、各サービスのサポートからは Google Workspace のサポートへ誘導されました。そのため、一部の非コアサービスで重要な Google Analytics や Google Cloud Platform については検証環境で権限などが維持されることを確認して済ませました。
※ 大きな問題はありませんでしたが、筆者のアカウントでは Google カレンダーが一切読み込まれない (Web だと白紙になる) という事象が発生しました。サポート曰く 24 時間は propagationにかかるらしかったので、おとなしく待ったら自然に解消してゆきました。
事前準備: 内製システムの準備
社内で内製しているシステムはほとんど *17が Hako で ECS にデプロイされていて、またユーザー認証はだいたい omniauth-google_oauth2 gem を利用しています。プライマリドメイン変更時の追従をスムーズに行うため、大半のパターンである Hako + Rails + omniauth-google_oauth2 について対応を検討しました。
まず、omniauth-google_oauth2 gem では hd オプションに Google Workspace のドメインを指定することで omniauth strategy レベルでログイン可能なドメインを制限できます (hosted domain, hd claim の検証)。omniauth-google_oauth2 の hd オプション自体は複数のドメインを指定可能ですが、hd オプションは Google の OAuth2 認可エンドポイントへも引き継がれていて、こちらは複数の指定を受け付けません。hd オプションを利用するとアカウント選択画面で表示するアカウントを絞ったり、1つに絞れたら省略したり、また新規ログインの際もドメイン名が補完されるためユーザー体験上有益です。この利点を失いたくはありませんでした *18。また、hd オプション以外でもドメインを検証している箇所もちらほら確認できました。
プライマリドメインの変更作業は週末、日本時間の土曜朝に行いました。何も手を打たないのであれば各自で週明けに cookpad.jp を cookpad.com に書き換えてデプロイしたり、DB 上のレコードを書き換えてもらうというところですが、社内システムに週明けに各自で変更をデプロイするまで、新規ログインできずに週末中の業務が停止する事態は避けたいものです。
検討した結果、AWS Systems Manager Parameter Store に現在の Google Workspace プライマリドメインを示す値を保存しました (作業前は cookpad.jp)。これを環境変数として ECS タスクに事前に入れてデプロイ、その環境変数が存在すれば hd オプションを含めプライマリドメインを示す値として利用するようにエンジニア全員に依頼をかけました。プライマリドメイン変更後、Parameter Store 上の更新して各 ECS サービスのタスクを再起動すればプライマリドメイン変更の反映が完了するという仕掛けです。
これに加えて、DB などに保存されている Google アカウント名があれば cookpad.jp → cookpad.com にしてもらう必要があります *19。アナウンスから作業直後の移行期間中はどちらが来てもいいように cookpad.jp を .com に読み替えてくれ、といった基本的な事も含めて確認をお願いしました。
プライマリドメイン変更作業後は用意した Parameter Store の値を更新し、ECS タスクを再起動することで反映させます。当社はほとんど Fargate の利用がなく EC2 をコンテナインスタンスとして利用しているので、社内向けサービス用の ECS クラスタに対応する Auto scaling group の instance refresh を実行しました。
多数の ECS サービスに force new update を行うとクラスタ全体が乱れて必要以上のコンテナインスタンス数にになる、集積率が一時的に下がる、コンテナインスタンスの起動の待ちが逐次発生して時間がかかる、といったデメリットがあるため、instance refresh でコンテナインスタンスを全て入れ替えてタスクの再起動に替えるのがおすすめです。
事前準備: メール受信ダウンタイムの影響を最小化する
次はメール受信についてです。前述したように、変更前の Google Workspace テナントは下記のようなドメイン構成になっていました:
- cookpad.jp (プライマリドメイン)
- cookpad.com (ドメインエイリアス)
ドメインエイリアスを利用しているので、ユーザーを cookpad.jp ドメインで作成するともれなく cookpad.com のメールアドレスがエイリアスとして付いてくる状態です。
そして変更作業後は、下記を満たしている必要があります。
- 既存ユーザー・グループのドメインが cookpad.com に切り替わっている
- 既存ユーザー・グループは引き続き cookpad.jp ドメインでもメールを受け取ることができる
これを達成するためには、2パターンの案がありました:
- A案: 下記構成に変更する
- cookpad.com (プライマリドメイン)
- cookpad.jp (ドメインエイリアス)
- cookpad.com (プライマリドメイン)
- B案: 下記構成にした上で、全ユーザー・グループにエイリアスを個別に追加する
- cookpad.com (プライマリドメイン)
- cookpad.jp (セカンダリドメイン)
長期的には、新規ユーザーは cookpad.jp のドメインでメールを受信する必要がないため、周辺サービス含めて変更が完了したタイミングで cookpad.jp ドメインでのメールアドレス付与を停止したいと考えていました。その場合 A 案だといつまでも引きずり、新規利用を完全に止めることができません。したがって今回は B 案を採用しました。
ただし、A 案 B 案どちらにも問題があり、Google Workspace はドメインエイリアスをユーザー・グループに直接割り当て可能な「ドメイン」に変更する操作が存在しません。どちらの場合も、一度ドメインエイリアスを削除、ドメインとして再追加して所有権の検証をやり直さなければいけません。また、削除→追加は即座に行えず、削除完了をしばらく待つ必要があります。
また、A 案だと cookpad.com へ変更し終えた後に cookpad.jp を削除、その上でエイリアスとして再追加する手順が必要なため作業時間が伸びてしまうのも問題と考えました。
ドメインエイリアスを削除すると当然ながらエイリアスによって発生していたメールアドレスは存在しなくなります。したがって、変更先かつメールアドレスとしてはプライマリである cookpad.com ドメインでメールを一定時間受信できないダウンタイムが発生します。削除完了~ドメイン再追加~エイリアス再追加がどれくらいの時間になるかは予測ができません *20。このダウンタイムについてどうするかを考えました。
人間同士のメール送受信であればあまり問題にはなりませんが、このダウンタイム中は Google の MTA がメールを受信した際、送信元のサーバにメールボックスが存在しない hard bounce (5.2.1 NoSuchUser) が返ることになります。送信元が supression list を持つようなシステムからのメールをダウンタイム中に受信して bounce した際、その対応として自動で supression list に入って以後のメールが送信されなくなる可能性があります。
Supression list に入っていることが自分で確認できないサービスは多く、サポートに確認しなければいけないサービスが多数存在します。それを各位で思い出してもらってサポートに問い合わせなければならない…という状況にするのは避けたいものです。出来ることなら soft bounce にしてリトライを促したいと考えました。
検討した結果、作業日前にダウンタイムが発生する cookpad.com の MX レコードの TTL を短くして、ダウンタイムが発生する前に一時的にデプロイした Postfix サーバーへ向けることにしました。以下のような設定で cookpad.com, cookpad.jp 宛のメールについては 4.3.2 の soft bounce になり、送信者にリトライを促せます。
# main.cf maillog_file = /dev/stdout debug_peer_level = 1 compatibility_level = 2 myhostname = inboundmx.googrename.cookpad.com mydomain = cookpad.com myorigin = googrename.cookpad.com mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain, cookpad.jp local_recipient_maps = # 4xx unknown_local_recipient_reject_code = 450 smtpd_recipient_restrictions = reject_unauth_destination, defer inet_interfaces = all smtp_tls_security_level = may smtpd_tls_security_level = may smtpd_tls_auth_only = yes smtpd_tls_key_file = /etc/postfix/cert/key.pem smtpd_tls_cert_file = /etc/postfix/cert/cert.pem smtpd_tls_CAfile = /etc/postfix/cert/chain.pem smtpd_tls_loglevel = 1 smtpd_tls_received_header = yes # tls cipher list や mandatory protocols は省略; Mozilla SSL Configuration Generator などを利用するのがオススメ https://ssl-config.mozilla.org/#server=postfix&version=3.4.8&config=intermediate&openssl=1.1.1k&guideline=5.7
これを利用すればメールを受信したことにせずデータを保存することもないので、完全ステートレスで運用可能です。検証環境で動作確認をしたところ、問題なくメール受信をリトライさせて遅延して受信できました。
これは当社の標準的なプラットフォームである Amazon ECS へ Hako を利用して作業数日前にデプロイしました。StartTLS がある都合、NLB の TLS 終端機能は利用できないため ECS タスクに TLS 証明書を渡す必要があります。TLS 証明書は当社の場合 ECS 上のシステムでは sorah/acmesmithを利用して発行・コンテナ起動時に S3 から取得するのが一般的なため、その仕組みを利用しました。また、この設計で受信するだけであれば外部にメールを送信することはないため、AWS の OP25B 解除なども行っていません。
なお、代案としては MX レコードの削除や MX レコード上で工夫することでリトライさせられないか検討しましたが、 RFC 5321 § 5.1. や実際の挙動をいくつか確認する限りでも確実にリトライさせられるものではないと判断し、Postfix の設定に至っています。
これでメールに関する準備も終わりました。
事前準備: 作業用データの準備
作業数日前に、テナント内のユーザーリストを元に実作業で利用する各種データを作成しました。このため、実作業一週間前に IT ヘルプデスクや HR チームと連携の元、テナント内の新規ユーザー作成を一時的に保留・新規作成を止めてもらうようにお願いしています。
作業で利用するデータは一部 SaaS のサポートへ提出するリネーム対応表、また Google Admin へインポートする CSV などがありました。dry-run を兼ねる、また terraform plan file のように反映内容を明らかにするため、可能であれば事前にデータを自動作成できるようにして確認しながら作業する意図で行っています。
作業当日: プライマリドメイン変更作業
日本時間の土曜朝から作業を開始、ざっくり下記の手順で進行しました。以下に解説します。
- 直前作業: 一部社内サービスをメンテに入れたり、MXレコードを前述の Postfix に入れ替える
- ドメインエイリアス cookpad.com の削除 (ここでメール受信のダウンタイムが始まる)
- cookpad.com をドメインとして再追加
- 全ユーザー・グループのドメインを cookpad.com に変更
- 全ユーザー・グループのエイリアスに cookpad.jp を追加
- メール受信が可能であることを確認して MX レコードの復旧
- 社内サービス向けの Parameter Store 上の値を変更して一斉反映
- プライマリドメインを cookpad.com へ変更
- 各種 SaaS へ変更を反映
これらの手順は事前に作業手順書を用意してログを記入しながら進行しました。また、作業開始前に Google のユーザーリストなどを一通りダウンロードしてバックアップしておきます。
直前作業: MXレコードの切り替え
まずはメール受信のダウンタイムに備えて MX レコードを前述の Postfix へ変更します。作業週の早いうちに予め TTL を短縮しておき迅速な反映を狙いましたが、しっかり問題なく切り換えが行われました。
SMTP の各種確認では swaks が便利でよく利用しています。事前に OP25B が解除された IP アドレスを持つマシンやサーバを用意して対応する SPF レコードも作成しておき、swaks でメールを送信して動作チェックを進めました。
swaks --from 'sorah@[REDACTED]' --to 'sorah@cookpad.com' --tls-optional-strict --tls-verify
ドメインエイリアスとしての cookpad.com を削除
次は cookpad.com を Google Workspace のドメインエイリアスから削除します。最初に書いたように削除しなければ通常のドメインとして再追加ができないため行いますが、ここからメール送受信のダウンタイムが発生します。
ドメインエイリアス削除実行後は即座に消えるわけではなくしばらく時間がかかります。(記憶が正しければ) ドメイン一覧からは即座に消失しますが、ユーザー詳細ページを確認するとユーザーから順次エイリアスが削除されていく様子が確認できます。
こちらも swaks で状況を確認できます。MX レコードに指定される SMTP サーバへメールを直送すると、NoSuchUser エラーが返ってくることを確認しました。
swaks --from 'sorah@[REDACTED]' --to 'sorah@cookpad.com' --server aspmx.l.google.com:25 --tls-optional-strict --tls-verify
セカンダリドメインとして cookpad.com を再追加
当社の環境ではおよそ 1 時間をかけてドメインエイリアスの削除が完全に完了しました。辞書順でエイリアスがユーザーから削除されていっているようだったので、辞書順で最後のユーザーからも消えたことを確認してから再追加を実行します。
ドメインが一度削除されている都合、ドメイン所有権の再確認が必要です。こちらは DNS レコードを用いて速やかに完了させました。
全ユーザー・グループのドメインを cookpad.com に変更
ドメインをテナントに再追加しただけでは、エイリアスではないため各所で利用され始めることはありません。今回の目的はプライマリドメインに加え全ユーザー・グループが cookpad.com を主たるアドレスとして利用する状況を作ることなので、次はその変更作業を行います。
今回の作業では、ユーザーは Google Admin でエキスポートした CSV の New Primary Email 属性を埋めて CSV インポートすることで行いました。旧 Primary Email はエイリアスとして自動で残るため、この対応で問題なく変更を行うことができます。 ただし既存のエイリアスを除くため、実際には全て API で実施するのが無難です。この点については後述します。
グループは Google Admin API を利用して一括更新を行いました。
作業チームのアカウントについては後回しにして手動で実行しました。リネームによって過去には再ログインが必要になったりした記憶がありますが、2023/3 に確認した限りでは Android や iOS *21以外で再ログインを求められませんでした。強制ログアウトによって全ての端末でログイン不可能になるなど (人はパスワードを忘れるので) 大きなトラブルは回避できるため、これは嬉しい挙動でした。
MXレコードの復旧
cookpad.com ドメインで再度メールが受信できるようになったことを確認して、MXレコードを元に戻します。不測の事態に備え、このタイミングでは TTL は短いまま維持しておきます。
メールの受信はレコードを変更せずともドメインエイリアス削除時の実行例と同様に swaks で確認可能です。
プライマリドメインの変更
ここまで問題なく来たら後はテナントのプライマリドメインを変更するだけです。
ただし、プライマリドメイン変更不可の条件に引っ掛かりすぐに変更することはできませんでした。 https://support.google.com/a/answer/7009324?hl=enに記載されているように様々な条件があるのですが、変更時のエラーでは何がダメかは教えてもらえません。
プライマリドメイン変更を行うか、行わないかはユーザーに(ほぼ)影響する話ではないため、ユーザー・グループの primary email address のドメインが変更されていれば問題はありません。ただ先述の通り完遂はさせたい、というところで対応を検討しました。
予定されていた作業時間中の反映は諦めましたが、幸いにしてチャットサポートに問い合わせたところ迅速に回答してもらえました *22。事前に目視して問題ないと思っていた Chrome Enterprise の試用ライセンス *23が実はアクティブで引っ掛かっていました。プライマリドメイン変更のために hold を依頼して、その日の深夜に改めて変更を完了しました。
障害: メールエイリアスの考慮不足
作業が一息ついたところで考慮不足が発覚しました。ユーザー・グループのprimary email については cookpad.jp から .com へ変更されましたが、secondary email - つまり個別に付与しているエイリアスについて cookpad.com への変更が必要だったところ考慮から漏れていました。この状態だと cookpad.com の secondary email address へメールが着信した際に NoSuchUser で hard bounce が返ってしまいます。
急ぎ MX レコードを再度 Postfix へ戻し、スクリプトを書いて復旧作業へ取り掛かりました。これについては既存のエイリアスで cookpad.jp ドメインのみ存在するアドレスを抽出し、cookpad.com ドメインのエイリアスとして追加しました。
Email の変更は旧名の alias が自動生成されるから CSV で良いのでは? となってインポート用 CSV の生成部のコードレビューまでしたところ、お互いで完全に存在を忘れる大きめなミスとなってしまいました。この点のリカバリについては後述します。
事後作業
Google Workspace テナント自体の作業はこれで完了ですが、ここからは事後に行った作業について解説します。
各種SaaSへの反映・確認作業
各種 SaaS の管理者側作業が下記の通り存在しました。
- 管理コンソールからユーザー情報を更新する
- サポート側リネーム完了を待つ (もしくは Google 側の完了を伝えて実施してもらう。いずれにせよ日程は事前に相談しておく)
- サポートに Google 側のリネームが完了した旨伝達する
管理コンソールからユーザー情報を更新する場合、一括で出来ない例がほとんどでした。複数人で分担してひたすらメールアドレスの更新を実施しました。
それ以外のいくつかの SaaS では事前に合意していた時間までにリネームが完了していない、または新ドメインである cookpad.com のアドレスに既にアカウントが存在してリネームできなかった (コンフリクト) といったトラブルがありました。
本稿では対応が長引いた SaaS を中心に代表例を解説します。なお、もし本稿をプライマリドメイン変更のために参照している方がいれば、サービス側の実装や状況は変化する可能性があるため、本稿の内容は参考程度に留めて都度問合せや検証は行うようにしてください。
Asana
Asana はテナント(組織) ごとに複数のドメインを登録可能ですが、cookpad.jp と cookpad.com がそれぞれ独立した組織で存在している状態でした。
社内横断的に動いている一部のチームが 2 つの組織を頻繁に切り替えなければならないというフィードバックがあったのも受け、こちらについては準備も兼ねて、Asana については 2023/1 頃に準備を始めました。Asana 側に組織の移行ガイドが用意されていたため、これに従って組織を 1 つにマージ *24しました。
https://asana.com/guide/help/organizations/data-migration
ユーザーのマージについては、ユーザーに cookpad.jp, cookpad.com 両方のメールアドレスを登録して検証を通してもらうことで自動で成されるようでした。マージが必要なユーザーは個別に連絡をして対応を依頼しました。
Figma
Figma は Google ログインについてメールアドレスをベースに実装されているようです。幸いにしてサポートが CSV を元にした一括のリネームを行ってもらえました。また、サポートに依頼するドメイン追加の手順が必要だったため、これは事前に済ませてあります。
また、土日での作業については合意が得られなかったため、金曜のうちにリネームを実施してもらいました。この対応として、事前のアナウンスで業務で重要な場合は Figma のログイン状態を確認して、ログインできていなければログインをするように周知しました。
実施した結果、コンフリクトが生じているユーザーがいましたが、それ以外は無事に完了しました。コンフリクトしたユーザーについては Figma サポートに空かどうか確認してもらい、空であれば削除してリネームを続行してもらうことができたので、そのように依頼しました。
Zoom
Zoom に関しても同様の対応で CSV を元にリネームとなりました。ドメイン追加・検証を事前に行う点も同様です。
こちらは事前に CSV を送付し作業日程まで合意していたところ、事前に内容を精査してもらえず、作業時間になってコンフリクトが発生したため全体の作業を中断したと報告されてしまいました。それに加え、事前に作成した全 Google ユーザーの新旧対照 CSV を送っていたのですが、実在する Zoom ユーザーに絞ってほしいとのリクエストがありました。事前に送っているのだから事前にチェックしておいてほしい………。
コンフリクトについては Google ログインではなくそれ以外の手段 (メールアドレス+パスワード) でサインアップ・ログインしてしまった場合に発生します。このような問題が生じてしまうのも複数のドメインがある故と言えます。仮にユーザー本人が誤りに気付いてログインし直したとしても、作成されてしまったアカウントとユーザーはそのまま残置されるため、コンフリクトへ繋がるという訳でした。
次に、残念ながらもともと休日に実施している関係でサポートから追加のレスが返ってくることはなく、大変困ったことになりました。 その場で検証を行ったところ、なかなか厄介なことが分かりました。特にコンフリクトがなければ Google ログイン後にメールアドレスを更新するか聞かれ、更新すれば Zoom ユーザーはリネームに問題なく追従できます。
しかし、コンフリクトがある場合の挙動が非常に困りました。まず、 cookpad.com アドレスで Zoom ユーザーが既に存在する場合は容赦なくそちらへログインする事になり、下記の選択肢が提示されます:
- メールアドレスを変更する
- ドメインに対応するアカウントへ参加する
- 無視して続行する
https://support.zoom.us/hc/en-us/articles/4405656980109-Advanced-Associated-Domain-configurations (実施当時よりユーザーが目にする画面の例が掲載されていてドキュメントが拡充されている!)
これらの選択肢はアカウントに追加したドメインごとにカスタマイズ可能です。本プロジェクトの目標として「影響を最小限に抑える」を掲げているため、業務を支障なく継続できる必要があります。従って、これまで利用していた cookpad.jp の Zoom ユーザーへ復帰できるよう整える必要が生じました。
検証の末、(3) 無視して続行する → 無料プラン (Basic) のアカウントを削除、という手順を辿り cookpad.com 名義の(1ユーザーしかいない)アカウントとユーザーを削除することで cookpad.jp ユーザーへログイン、リネームへ追従できることが判明しました。
(2) のオプション (consolidation) については実施されると IT で管理するメインの Zoom アカウントへ参加し、cookpad.jp と cookpad.com 名義で重複するユーザーが存在してしまう上、自力での復帰が不可能になるため無効化しました。(1) のオプションのみ提示するカスタマイズも可能ですが、cookpad.jp の Zoom ユーザーが既に存在してそのメールアドレスには変更できない上、cookpad.com は誤って作成されたユーザーそのもので不可能なため見送りました。
アカウント削除の操作はクリック数も多くやや不安だったため、日英両方でスクリーンショットも添えた作業手順のアナウンスページを追加で周知しました。
調査の結果パスワードログイン → Google ログインへ切り替える際の確認画面も存在する事が判明し、フロー含めてやや複雑な文章になりましたが、その分丁寧に作成したため混乱なく乗り越えられました。週明けから IT ヘルプデスクに対応してもらったトラブルシュートで、Google/Zoom のクッキーを全削除しないと cookpad.com へ更新されない例などいくつか追加でケースが見つかりましたが、概ね問題なかったようです。
設定変更までに誤ってアカウントが consolidate されてしまったパターンなど、メインの Zoom アカウントに cookpad.jp, cookpad.com 両ユーザーが存在してしまうケースが発生しましたが、これについては Zoom サポートに週明けにバルクでのリネームと合わせてマージ対応をお願いできました。
Slack
Slack に関しても Google ログインで運用を開始したため、現状は SAML ログインですが cookpad.jp から cookpad.com に変更する必要があります *25。今回サポートに聞いたところ SCIM を利用するのが早いかも、という提案を貰いました。
スクリプトレスで済めば & このタイミングで SCIM 導入ができれば嬉しいということで SCIM を導入する方向で決めましたが、検証から導入までまあまあ時間がかかってしまい、実は Slack について完了したのはつい先日の事です。その上で導入直後に SCIM v2 のリリースがされており、タイミングが悪かったですね…。
Azure AD から SCIM を行っていて、cookpad.jp で最初にマッチングさせ cookpad.com に変更を行いました。Slack は user name から display name に方針を切り替えてだいぶ経ちますが、user name は API 上の各所に残っていて、SCIM も例外ではありません。SCIM のドキュメントにも記載されているように文字種・文字長制限を回避して指定する必要があります。
SCIM 化にあたって問題だったのはこの userName を重複せずに設定することです。Display name はユーザーが自由に設定できるようにしたいため SCIM では渡さないことにしたため、新規にプロビジョンされたユーザーは userName を目にします。したがって、ここは機械的な値に設定できません。Azure AD テンプレートのデフォルトである email のローカルパートを採用することにしましたが、single/multi channel guest の userName とも衝突してはならないという所で何件か衝突が発生しました。これについては個別にエラーを確認して guest 側を別名に変更するという措置を行いました。
メールダウンタイムの事後報告
週明けまでに復旧できていないと困る SaaS 類の対応まで一段落したところで、メールダウンタイムの事後報告と、メールエイリアス障害の事後対応を行います。
まずはダウンタイム中に着信したメールログを集計してユーザー・グループごとに着信した envelope from のリストを作成しました。CloudWatch Logs Insights で Postfix のログを下記クエリで抽出します:
fields @timestamp, @message, @logStream, @log
| filter @message like /NOQUEUE/
| parse @message /RCPT from (?<remote_mta>.+?)\[(?<remote_ip>.+?)\]: (?<response_code>[0-9. ]+?) <(?<recipient_email>.+?)>: (?<response_message>.+?);/
| parse @message /; from=<(?<from_email>.*?)> to=<(?<to_email>.+?)> proto=(?<proto>.+?) helo=<(?<helo>.+?)>/
| filter from_email not like /bounces.google.com/
| stats count(*) as cnt by from_email, to_email
| sort to_email asc, cnt desc
| limit 10000
これで得られる from_email は envelope from であるため、Google Sheets にインポートして各種配信サービスの動的に作成される envelope from を正規化、エイリアスを primary email address に変換、再集計のち CSV で出力しました。
障害自体は wiki で周知の上、このデータを添えて障害の対象だったユーザー・それ以外で文面を分けてメールで個別にお知らせを送信しました。送信したデータがどれくらい役に立つかは分かりませんが、少なくとも障害がなかった場合についてはリトライで後から到着すべきメールが来ているかどうかは判断できるということで実施しています。
また、エイリアスが削除されたことにより Gmail の Send mail as 設定も自動で剥奪されることを確認したため、再設定についても案内しました。
DKIM の再設定
これもメール関連で盲点の1つでしたが、ドメインエイリアスを削除した時点で DKIM の設定も消失します。実施後しばらくしてセキュリティチームのメンバーから DKIM 忘れてない? と言われて慌てて設定しました *26。再セットアップにより鍵長も現代的になったのでお得だったと思うことにします。
社内アナウンスについて
さて長々と書いてまいりましたが、最後に作業中および作業前後に実施した社内へのアナウンスについて言及しようと思います。今回はアカウントのリネームによって社内システムや SaaS にアクセス不可能になるリスクや、事前事後に各自の作業が存り、また既に書いているようにその他不測の事態が発生する可能性があったため、比較的丁寧にアナウンスを執筆しました。
Slack での社内アナウンスはもちろん、事後 Zoom や Figma などリネーム・マージの積み残しが発生したため、常に状況が分かるページを更新し続けていました。
今回、リネーム後にいくつかトラブルがあったり、想定スケジュール通りに SaaS 含めリネームが完了しないといった計画外の出来事がありましたが、実は日本・グローバル通してほぼ問い合わせがありませんでした。丁寧なドキュメントや簡潔なアナウンスが混乱を防ぎセルフサービスで解決も出来るということを改めて実感できるプロジェクトとなりました。
振り返り
さて、以上が Google Workspace プライマリドメイン変更プロジェクトの解説となります。まとめと振り返りしては下記でしょうか。
- Google Workspace 外のサービスへの影響を調査するのがとにかく大変
- Relying Party 各位には OIDC の適切な実装をお願いしたい。ドメイン以外でもメールアドレスは普通に変わりうるもの。
- 最近 The False Identifier Anti-patternといういい記事が Microsoft Entra チームから出ていたのでオススメです。
- SAML ログインに対応するのは必須ではない *27として、Google ログインなどを強制するオプションは欲しい。それはそれとしてサポートコストが掛かるのは分かるが SSO を有償オプションにしないでほしい。
- 作業日程を JST 土曜朝にしたが、金曜深夜にするべきだった
- 各種サービスのサポートが米国西海岸時間 (PT) で稼動しているため
- そもそも本件をまったく理解してもらえない *28、対応が複雑、といった理由で英語話者へエスカレされることも想定し、日本国外で開発されているサービスへの問合せは日本語サポートがあろうとも全て英語で行っていたのもある。もちろん日本語サポートが無い場合も多数だった。
- 当社で社内システムメンテ時に考慮すべきタイムゾーンは UK 時間と日本時間。いずれにも被っていない PT、かつ平日に実施すればスムーズにサポートに作業を行ってもらえたり、リアルタイムに連携ができたと思われる
- また、土曜作業で水曜に Google Workspace を含めた IdP のフリーズを宣言したが、サポートとの TZ 差による RTT を考慮して月曜にはフリーズしておくべきだった
- プライマリドメインの変更可・不可は事前に確認しておくべきだった
- 正確には途中で(諸事情で)タスクがこぼれてしまった… そしてこれについてはサポートに問い合わせるしかないのが大変なところ
- ほとんどのメールについてロストを簡単な仕掛けで防げたのは良かった
- ただしエイリアスを見落としてメールのエイリアスのみ障害を起こしてしまった
- 日本・グローバルチーム両方で実施後、週明けからのトラブルやユーザー問合せはほぼ無しを達成できて良かった
- 丁寧なドキュメント・簡潔なアナウンスが助けたと思われる
- 英日両方でドキュメントを用意したり、スクリーンショットまで英日で分けるのは作業負荷としては割と大変ではある
- また、変更によって強制ログアウトが発生しないのが良かった。モバイルでも iOS/iPadOS では Google 製アプリは何もなく、Android でもパスワードのみでメールアドレスまで求められることがなかった
総作業時間としてはプロジェクト終盤に集中していたとはいえ、2022/8 ~ 2023/3、Slack などを含めれば 2023/6 までと長期間にわたり本当に大変だったので仮ドメイン名で運用を開始するのは本当におすすめしません *29。
Acknowledgements
本プロジェクトは筆者 (sorah) だけでは手が到底足りなかったため、株式会社I-Styleの板垣 崇司さま, 菅井 祐太朗 (id:hokkai7go) さま, 中田 健史さまに事前調査やスクリプトの作成・検証のご協力をいただきました。
また下記の記事を先行事例として参考にさせていただきました。やれば出来るんだ…! というところで踏み切るキッカケにもなりました。
また、こちらは同様の懸念で別テナントへの引っ越しを行った事例だそうです。本稿のように頑張れば同じアカウントを維持してリネームすることもできますが、興味深い事例として紹介します。
みなさまがこの記事を役に立てないことを願いつつ終わりたいと思いますが、何かの役に立てば幸いです。
*1:技術部 SRE グループが主務です。一応…
*2:テナント自体は 2007 年から、業務に本格的に使われたのは 2009 年から、らしいですが詳細は不明です
*3:当時は Google Apps
*4:これも導入時期と同様に経緯は完全に損われていて不明、利用していないドメインで「一旦」設定してみて、そのまま本番利用されちゃったパターンと想像しています
*5:Intune の存在、SAML機能の柔軟性など諸々で併用になっていますが、本プロジェクトでやっとアドレスが統一され混乱を防げるようになったので Google Workspace は Azure AD からのフェデレーションに切り替えたい…!
*6:Slack がまさに Enterprise Grid で SAML に変更になった時、cookpad.jp を SAML で Azure AD に名乗らせていた例
*7:人の名前は姓名いずれも変わったり、ビジネスネームが異なったり、衝突したりするため、ユーザー名に命名規則を設けるのは非常におすすめしません。ひどい例では、イレギュラーがあるのにユーザー名の命名規則を鵜呑みにしてメールアドレスの推測を行うような実装も発生してしまいます。当社では記号の制約はありますが、任意のユーザー名を入社時にリクエストすることが出来るようになっています
*8:昔は hostmaster@ でメールを受けて SSL 証明書発行の承認とかをしていたので、そういうやつのために色々追加されていました
*9:後述しますが、Google Workspace や Cloud Identity のドメインを元にアカウント選択画面の表示をフィルタしたりスキップ、また新規ログイン時にフォームにドメインをあらかじめ表示する機能。組織のプライマリドメイン != ユーザーのドメイン時の挙動が不定
*10:Google も sub claim を利用しろ、email は適さないゾと ドキュメントで明記しています。OIDC 仕様上でも sub クレーム以外での照合は non-conformant です https://openid.net/specs/openid-connect-core-1_0.html#ClaimStability。
*11:シャドーITっぽいというよりかは、子会社で利用していて本体で関知していないサービス等がそこそこ
*12:そういえば最近 https://www.descope.com/blog/post/noauthとかありましたね。Google の場合は email_verified claim も見ていればいいけど、見ていないところも実はあったりしたんだろうか?
*13:変更元の cookpad.jp は意図せず使われてきてしまった、と言うのが正しいんですが
*14:たとえば Google ログインを強制できず、パスワードでサインアップやアカウント招待を受諾してしまうとそうなってしまう
*15:Google ログインできない場合でもパスワードリセットの手順でなんとかなったりする事が多かった
*16:ドメイン所有権の検証があるサービスだとお願いできたり、一度テナントに .jp, .com 両方のユーザーを入れてからだったり
*17:日本側の場合。UK オフィスが中心となっているグローバル事業は ALB + Azure AD OIDC だったりします
*18:もちろん、一時的に hd に両方指定してもらって後で戻すというのもアリですが、後で戻してもらうことは必須ではないため、戻してもらえなかったところだけ不便なままという状況が予想できます
*19:もちろん認証は sub claim を利用して認証が行われるのが望ましいですが、各種フォームなどメールアドレスから引くことも当然あるため
*20:事前に検証用の Google Workspace 上で同じ数のユーザーを作成してみれば分かるかもしれませんが、アテにならない上に費用が無駄にかかってしまう…
*21:純正メール・カレンダーで利用する iOS 自体に登録されているアカウント情報。Google 製アプリでは不要だった
*22:チャットサポートはログが残らない上その場で解決まで至らないイメージが強かったのですが、Google Workspace の英語サポートは割とその期待は上回った気がします
*23:リセラーからトライアル目的で渡されたものと記憶していますがこれも詳細が不明…
*24:実際にはマージではなく、統合先の組織にデータがコピーされる実装のようです
*25:かなり前に Enterprise Grid プランに移行しているので現在は Azure AD から SAML ログイン、cookpad.jp を名乗らせています。Enterprise Grid 移行時にリネームを検討したところ当時は不可能だった覚え
*26:DMARC の reject ポリシー有効化のためにレポートを監視していたようです
*27:しかし SAML が嫌なら任意の OIDC クライアントを設定させてほしい…
*28:実際説明に苦労したサービスはたくさんあった
*29:関係ないですが Active Directory (Windows Server) のドメインもちゃんとしたドメインを使うのが良いです。public TLD のサブドメインかなにかを設定した上で(それもKerberos Realmになるのでユーザーに分かりやすいドメインの下が良いと思います)、UPN suffix をメールアドレスに合わせましょう。