Azure環境のTerraform管理をはじめる

過去に何回かAzure環境(私の用途だとAzureADだけど)をTerraform管理するため、構築してきたけど 毎回やり方を忘れて数時間無駄にするのでメモ。

概要

  1. TerraformでAzure環境をゴニョゴニョするために「Azure サービスプリンシパル」なるものを作る。
  2. AWSで言う「プログラムによるアクセス」のIAMユーザーを作るのと同義な気がする。しらんけど。
  3. stateファイルを管理するために「Azure Storage」も用意する。
  4. 1で作った「Azureサービスプリンシパル」に権限を与える。
  5. tfファイルの作成
  6. tfファイルでリソース作成してみる

1. Azureサービスプリンシパルを作る

  1. Azureポータルにログイン。
  2. Cloud Shellを開く
    • f:id:undersooon:20200910095247p:plain
  3. Bashを選択して、下記コマンドを実行。(サブスクリプションIDの確認)
    • az account list --query "[].{name:name, subscriptionId:id, tenantId:tenantId}"
    • 複数表示されたら、下記で使用するサブスクリプションIDを指定する。
      • az account set --subscription="<<上記のsubscriptionIdの値>>"
  4. 確認したサブスクリプションIDを変数に入れとく。
    • SUBSCRIPTION_ID=<<上記のsubscriptionIdの値>>
  5. サービスプリンシパル名の定義。(任意の値です。わかりやすくTerraformとかにするといいかも)
    • 例: SUBSCRIPTION_NAME="Terraform"
  6. 下記コマンドで、サービスプリンシパルを作成。
    • az ad sp create-for-rbac --role="Contributor" --scopes="/subscriptions/${SUBSCRIPTION_ID}" --name "${SUBSCRIPTION_NAME}"
      • 表示される値はすべてあとで使うのでメモしておく。 ※特にpasswordはあとで確認不可なので必ずメモする。

2. stateファイル管理用のAzure Storage」も用意

  1. ストレージアカウントの構成スクリプトをそのまま実行する。
    • storage_account_name, container_name, access_key はあとで必要になるので必ずメモしておく。

(念の為、上記URLのスクリプト内容を転記)

#!/bin/bash

RESOURCE_GROUP_NAME=tstate
STORAGE_ACCOUNT_NAME=tstate$RANDOM
CONTAINER_NAME=tstate

# Create resource group
az group create --name $RESOURCE_GROUP_NAME --location eastus

# Create storage account
az storage account create --resource-group $RESOURCE_GROUP_NAME --name $STORAGE_ACCOUNT_NAME --sku Standard_LRS --encryption-services blob

# Get storage account key
ACCOUNT_KEY=$(az storage account keys list --resource-group $RESOURCE_GROUP_NAME --account-name $STORAGE_ACCOUNT_NAME --query [0].value -o tsv)

# Create blob container
az storage container create --name $CONTAINER_NAME --account-name $STORAGE_ACCOUNT_NAME --account-key $ACCOUNT_KEY

echo "storage_account_name: $STORAGE_ACCOUNT_NAME"
echo "container_name: $CONTAINER_NAME"
echo "access_key: $ACCOUNT_KEY"

3. 「Azureサービスプリンシパル」に権限を与える

  1. Azureポータルの「Azure Active Directory」 - 「アプリの登録」から作成したサービスプリンシパル名のアプリを探して開く。
  2. APIのアクセス許可」から必要な権限を付与する。
    • ご参考までに:当方は、AzureADユーザー、グループ管理、エンタープライズアプリケーション(SSO用アプリ)しか用が無かったので下記権限にしてます。
      • f:id:undersooon:20200910100503p:plain
  3. 「管理者の同意」を与える。
    • 同画面の真ん中らへんに下記ボタンがあるはずなので忘れずに実行。※わかりづらいUIなのでよくさがしてください。
      • f:id:undersooon:20200910100712p:plain
  4. 「Azure Active Directory」 - 「ロールと管理者」から、必要なロールを与える。
    • グローバル管理者が一番手っ取り早いですが、ユースケースで判断してください。(たとえば、ユーザー管理、グループ管理したいだけなら「ユーザー管理者」ロールで十分)

4. tfファイルの作成

上記までで、TerraformによるAzure環境の管理ができるようになったので下記のようなtfファイルを作って管理する。

main.tf(azureadプロバイダを使う宣言と、stateファイルの保管場所の指定)

provider "azuread" {
  version = "0.7"
}

terraform {
  backend "azurerm" {
    resource_group_name  = "tstate(手順2でリソースグループ名を変えてた場合はその名前にする)"
    storage_account_name = "<<手順2のstorage_account_name>>"
    container_name       = "<<手順2のcontainer_name>>"
  }
}

※MSのサイトではbackendにkeyも指定しているが、それは危険なのでterraform initするときに指定するようにする。(後述)

enterpriseApp.tf(エンタープライズアプリケーションの管理)

resource "azuread_application" "appName" {
  name     = "appName"
  homepage = "https://account.activedirectory.windowsazure.com:444/applications/default.aspx?metadata=customappsso|ISV9.1|primary|z"

  app_role {
    allowed_member_types = [
      "User"
    ]
    description  = "User"
    display_name = "User"
    is_enabled   = true
  }

  app_role {
    allowed_member_types = [
      "User",
    ]
    description  = "msiam_access"
    display_name = "msiam_access"
    is_enabled   = true
  }
}

resource "azuread_service_principal" "appName" {
  depends_on                   = ["azuread_application.appName"]
  app_role_assignment_required = "true"
  application_id               = "${azuread_application.appName.application_id}"
  tags = [
    "8adf8e6e-67b2-4cf2-a259-e3dc5476c621",
    "WindowsAzureActiveDirectoryCustomSingleSignOnApplication",
    "WindowsAzureActiveDirectoryGalleryApplicationNonPrimaryV1",
    "WindowsAzureActiveDirectoryIntegratedApp",
  ]
}

※1 azuread_service_principalについて補足1
エンタープライズアプリケーションの種類はtags欄で決まる模様。上記は「ギャラリー以外のアプリケーション」を作成する例。
※2 azuread_service_principalについて補足2
depends_onを設定しないとazuread_applicationとの整合性がとれなくなってつむ。

azureuser.tf(ユーザーやグループを管理するtf)

# AzureADからObject IDを取得
data "azuread_user" "user1" {
  user_principal_name = "user1@hogehoge.com"
}

# グループ作成
resource "azuread_group" "group1" {
  name = "group1"

# AzureADのグループにメンバー追加
resource "azuread_group_member" "group1" {
  group_object_id  = azuread_group.group1.id
  member_object_id = data.azuread_user.user1.id
}

5. TerraformでAzureリソースを作成してみる

手順4のtfファイルが存在するディレクトリで下記を実行。

export ARM_SUBSCRIPTION_ID="<<手順1のsubscriptionId>>"
export ARM_CLIENT_ID="<<手順1のappId>>"
export ARM_CLIENT_SECRET="<<手順1のpassword>>"
export ARM_TENANT_ID="<<手順1のtennant>>"

terraform init -backend-config="key=<<手順2のaccess_key>>"

無事、successとなったら

terraform plan で作成されるリソースの確認。 terraform applyでリソース作成して終了!

GitHub ActionsやCircle CI等でCIしたいときは上記値を環境変数とかに埋め込めばできます。

参考にさせていただいたURL

docs.microsoft.com

docs.microsoft.com

qiita.com

TerraformでAzureAD App作成に失敗するとき

雑メモ。 TerraformからAzureAD アプリケーションを作成しようとすると、下記のエラーが。。

Error: graphrbac.ApplicationsClient#Create: Failure responding to request: StatusCode=400 -- Original Error: autorest/azure: Service returned an error. Status=400 Code="Unknown" Message="Unknown service error"

権限も、下記のような感じで問題ないはず。。 f:id:undersooon:20200728101827p:plain

と悩んでたら、「name」の箇所に記号が入ってたのが原因だった。 でも、GUIでは記号入れられるのになー??なんでだ??と思ってたら、下記みたいに「name」からデフォルトURLを作成するのね。。そりゃエラーになるわ。。

f:id:undersooon:20200728101336p:plain

というわけで、「homepage = "https://dummy/" 」とかってのを入れたら無事に作成できた。 (記号以外にも、空白や2バイト文字でも起きる模様)

f:id:undersooon:20200728101555p:plain

MacPCでPalo AltoのGlobal Protect用証明書をLet's Encryptで作成するメモ

いつも忘れて調査に時間がかかるのでメモ。 ※情報が正しくない恐れありです。いつか清書します。

参考にさせていただいたサイト

www.bitbodyguard.com

qiita.com

事前準備1

Global Protect用のドメインを取得 & TXTレコードが書き換えられる環境を用意しておく。

事前手順2

下記を事前にインストールしておく。

  • certbot
    • brew install certbot
  • openssl
    • brew install openssl
  • pan-python
    • pip install pan-python

証明書の用意

下記コマンドを実行。変数の箇所は各自の環境に合わせて書き換えてください。

DOMAIN=hogehoge.com #Global Protect用のドメイン
MAIL=admin@hogehoge.com #証明書失効について通知したりするメールアドレス

certbot certonly --manual \
-d ${DOMAIN} -m ${MAIL} --agree-tos --manual-public-ip-logging-ok \
--preferred-challenges dns-01 \
--server https://acme-v02.api.letsencrypt.org/directory

下記のような感じで登録するテキストレコードが表示するので、それを登録し、ちょっと時間を置いてからEnterする。

Please deploy a DNS TXT record under the name
_acme-challenge.hogehoge.com with the following value:

xxxxxxxxxxxxxxxxxxxxxxx

Before continuing, verify the record is deployed.

証明書作成に成功したらpfx形式の証明書を生成する。

TEMP_PWD=$(openssl rand -hex 15)
sudo openssl pkcs12 -export -out letsencrypt_pkcs12.pfx -inkey /etc/letsencrypt/live/${DOMAIN}/privkey.pem -in /etc/letsencrypt/live/${DOMAIN}/cert.pem -certfile /etc/letsencrypt/live/${DOMAIN}/chain.pem -passout pass:$TEMP_PWD

Palo AltoのAPIキーを得る

Palo AltoのAPIキーを得る。下記変数の箇所は各環境に合わせてください。

#変数
PAN_MGMT=192.168.xx.xx #Palo AltoのIP
USERNAME=admin
PASSWORD=hogehoge
#APIキー発行
panxapi.py -h ${PAN_MGMT} -l ${USERNAME}:${PASSWORD} -k

成功するとこんな感じで表示

keygen: success
API key:  "xxxxx"

証明書をアップロード

下記のような感じでアップロードする。

# 変数
CERT_NAME=LetsEncryptWildcard #任意の証明書名
API_KEY="xxxxx" #上記で生成されたAPIキー

# アップロード
curl -k --form file=@letsencrypt_pkcs12.pfx "https://$PAN_MGMT/api/?type=import&category=certificate&certificate-name=$CERT_NAME&format=pkcs12&passphrase=$TEMP_PWD&key=$API_KEY" && echo " "

curl -k --form file=@letsencrypt_pkcs12.pfx "https://$PAN_MGMT/api/?type=import&category=private-key&certificate-name=$CERT_NAME&format=pkcs12&passphrase=$TEMP_PWD&key=$API_KEY" && echo " "

成功すると下記のような結果が表示される。

<response status="success"><result>Successfully imported LetsEncryptWildcard into candidate configuration</result></response>

あとはPalo AltoのGUIコンソールで「デバイス」-「証明書の管理」-「証明書」でアップロードした証明書が現れているので、Global Protectポータル等でアップロードした証明書を使えばOK。

Google Apps Script(GAS)をclasp&GitHub Actionsでお手軽CI管理する

本ページについて

コーポレートエンジニアとして生きていく以上、お友達にならないといけない(?)Google Apps Script。
使いこなすと、色々と便利なので大変役立つので業務で使っている方も多いと思います。

ですが、最大のデメリットとして、 Google Apps Scriptは標準機能だけではコード管理ができない」 ということがあげられると思います。
このページはGASをコード管理するためにステップバイステップで手順を記載したページになります。

対象読者

  • 個人でGASを使っているが、チームにもコードを共有して管理したくなった。でも手法がわからない。CIって何?って人向け。
    • 「CIは興味あるけど手が出せないよ...」という方に役立てば幸いです。
    • GitHubの操作方法については触れないので自学してください。

今回のページでどんな嬉しいことがおこるか

コード管理ができる

上記につきると思うのですが、具体的になにが嬉しいかというと

  • 問題のあるコードがリリースされてしまっても比較的かんたんに戻せる。
  • レビューしていないものはリリース禁止等のルールがGitHub側の機能でもたせることができるので、「誰かが知らないうちに更新して事故発生」案件が防げる。

といったことがあるかなと。そして、

GASのオーナーをGAS編集者と分離できる。

これは何かというと、共有のGASを作成した場合、よくあるケースとして「共有用Gsuiteアカウントを作成して、そのアカウントのID/PASSを共用してGASを編集する」というのがあると思います。

これは実は危険で、「誰が編集したかがわからない」とか、そもそもGAS以外にGmailとかも使えるので「共有用アカウントでGmail等から情報持ち出し&誰が持ち出したかがわからない」という問題がおきます。

繰り返しになりますが、これは非常に厄介。
しかもそのアカウントが「Webアプリケーションとして公開」(詳細は後述)が可能なユーザだったりすると、各種社内資料の閲覧権限をいじってしまい、Internetに公開されてしまうかもしれないという問題も。
これが、CI化することで

  • GAS編集はGitHub上で行う。
    • 編集者が誰かわかる。
  • GAS編集以外できない。
    • 情報の持ち出しようがない。

という嬉しいことがおきます。

使うもの

  1. clasp
    • claspとは?
      • googleが提供するGAS等を管理するフレームワーク
      • 詳細はググるとたくさん出てくるのでそちらを参照。
      • ざっくりいうと、GAS管理を簡単にする便利ツール。
  2. GitHub Actions
    • GitHub Actionsとは?
      • GitHub社謹製のCI製品。GitHubに標準で搭載されている。
      • 無料ではないが、契約プランによっては無料枠の範囲で使える。詳細はググってください。
  3. CIって?
    • 細かく語ると色々深いのでざっくりいうと「GitHubに反映すると本番にも自動反映する仕組み」(本当は違うが、こういう理解で十分かと。)
    • 参考URL: https://cloudbees.techmatrix.jp/devops/ci/

本ページで作成する構成

色々なケースに対応できるように下記要件で構成しようと思います。 管理対象のGASのケースに応じて下記要素の不要なところを適宜削ってもらえればと思います。

  • GASはWebアプリケーションとして公開する。
    • GASを外部アプリ(例えば、SlackのOutgoing Webhook(参考URL)) と連携できるGASにする。
  • いきなり編集内容のGASが反映されると改修ミスがあったときなどが怖いのでテスト環境(Sandbox)を用意。そちらに一旦、反映し問題が無いものを本番GASに反映されるようになする。

構成図でいうと、こう。

f:id:undersooon:20191225131257p:plain
構成図

構築手順

事前準備その1:必要アカウント、リポジトリの用意

まず、事前に下記アカウント、リポジトリを用意しておきます。2はお近くのコーポレートエンジニアにお願いするといいと思います。 1についてもコーポレートエンジニアに相談すると検証用のアカウントくれるかもしれません。

  1. Sandbox用のGmailアカウント(何でもいいのでフリーのGmailアカウントとかを取得するといいと思います。もちろんコードテスト用のみに使用し、悪用は厳禁です。)
  2. 本番GASを動かすGsuiteアカウント(個人アカウントでもいいですが、後々のこと、セキュリティのこと諸々を考えるとGAS専用アカウントとかを払い出すといいと思います。)
  3. GAS管理用のGitHubリポジトリを用意する。Privateリポジトリ推奨。

事前準備その2:認証Tokenの取得、管理対象GASの作成

claspで使用するための認証Tokenを取得します。
自分のPCでclaspを一時的にインストールしてtokenを取得しますが、tokenを得られたら自PCからはclaspを削除してもOKです。

  1. SandBoxアカウントで「Google Apps Script API」をオンにする。
  2. claspはNode.jsで動くので Node.js/npmをインストールします。
  3. claspをインストールします。
    • npm i @google/clasp -g
  4. tokenを取得するため、事前準備で用意したSandBoxアカウントでclasp loginする。
    • clasp login
      • ログインウィンドウが立ち上がるので認証情報を入力する。いろいろと権限も求められるがOKしておく。
      • ログインに成功するとtoken情報を生成した旨、そのパスを示すメッセージが表示されるのでそのtokenファイルをメモしておく。(後で使う)
        • Macの場合のパスは「 ~/.clasprc.jsonWindowsは試してないのでわかりません。。
  5. 適当なパスに空ディレクトリを作成して、そこにcdする。
  6. 管理対象のGASを作成する。
    • clasp create SAMPLE
      • WebAppとして公開する場合は、「webapp」、通常のGASとして作成する場合は「standalone」を選択するが、あとで変更可能なのでとりあえず「standalone」にしておく。
      • f:id:undersooon:20191225135652p:plain
    • ※作成されるとGASのURLが表示されるので、忘れずにメモしておくこと。
  7. カレントディレクトリに「.clasp.json」 が出来ているのでこのファイルの内容もメモしておく。(後で使う)
  8. 本番GASを動かすGsuiteアカウントでもtokenを取得するため、上記手順を行いtokenを取得、GASを作成する。

構築

以上までの準備が整いましたらいよいよ構築です。
GitHub Actions用のワークフローとして下記ymlをGitHub側にアップロード(push)するので事前に作成しておきます。

  1. 下記リポジトリにテンプレートを用意したのでgit clone等で取得する。
  2. 「事前準備その1」で用意したリポジトリに上記リポジトリの内容を配置する。
    • 手で配置してもいいですし、 この参考手順で配置してもいいと思います。
    • ちゃんと配置できていればこんな形になっているはず。
    • f:id:undersooon:20191225182404p:plain
  3. Tokenをベタ書きするのは怖いので、GitHub側の「Secrets」にToken情報をそれぞれ下記のように登録する。Token情報は「事前準備その2」で取得した、「.clasprc.json」から得る。
    • f:id:undersooon:20191225182830p:plain
    • 面倒&細かいことは気にしない!という人は、clasprc.jsonに「事前準備その2」で取得したTokenファイル「.clasprc.json」を上書いてください。
    • PRD_ACCESS_TOKEN
      • 本番側Tokenの「access_token」
    • PRD_ID_TOKEN
      • 本番側Tokenの「id_token」
    • PRD_CLIENT_ID
      • 本番側Tokenの「client_id」
    • PRD_REFRESH_TOKEN
      • 本番側Tokenの「refresh_token」
    • PRD_CLIENT_SECRET
      • 本番側Tokenの「clientSecret」
    • STG_ACCESS_TOKEN
      • Sandbox側Tokenの「access_token」
    • STG_ID_TOKEN
      • Sandbox側Tokenの「id_token」
    • STG_CLIENT_ID
      • Sandbox側Tokenの「client_id」
    • STG_REFRESH_TOKEN
      • Sandbox側Tokenの「refresh_token」
    • STG_CLIENT_SECRET
      • Sandbox側Tokenの「clientSecret」
  4. 「事前準備その2」で取得した、「.clasp.json」から、下記値を上記手順と同様に「Secrets」に登録する。
    • PRD_SCRIPT_ID
      • 本番側の「scriptId」
    • STG_SCRIPT_ID
      • Sandbox側の「scriptId」
  5. (オプション)「Webアプリケーションとして導入」をするなら、「appscript.json」に下記を追記する。
  6. 以上!

運用編

上記までが完了しましたら、GitHubでGASのコードが管理できるようになります。
具体的には

  1. scripts/配下に .js もしくは .ts拡張子のScriptを配置する。
  2. (今回のSAMPLEを使用する場合) masterリポジトリにmergeするとSandBox側のGASに設定内容が反映されるので確認する。
    • 例: Code.jsというファイルを配置して、アップロードすると、GAS側にもCode.gsという形で反映されます。
  3. (今回のSAMPLEを使用する場合) 2でコードが問題ないことが確認できたら、releaseリポジトリにmerge。本番側GASにマージされることを確認する。

参考までに:運用デモ
https://streamable.com/dfzyv

最後に

色々と初期設定は煩雑ですが、一回設定が終わればGitHubにpushするだけでGASに反映されるので便利です。
また、GitHubの機能を使ったレビュー機能が使えたり、GASのオーナー権限を絞ることができたりと色々と応用の幅があると思いますのでぜひぜひ試してみてくださいませ。

参考にさせて頂いたURL

qiita.com

qiita.com

github.com

AppleIDがAzureADによるフェデレーションログインに対応したので試してみた

この記事について

Apple社デバイス管理者にとって悲願(?)のApple IDがIdP(今のところAzureADだけ?)によるログインが可能になったので検証してみました。
結論から言うと、 「まだ社内展開は早いかな...。」 という所感を持ったのでそこについて触れていきます。

ちなみに、現状、フェデレーションログインによるメリットが享受できる企業としては下記になると考えています。(詳細は後述)

  1. 「会社設立したてでこれからApple IDを管理する」といった企業。
  2. Apple ID用のサブドメインを用意する」といった企業。

フェデレーションログインによる「メリット」

  1. ユーザー(社員)はAzureADによるID/PASSでログインできる。MFAもAzureADのものが使える。
  2. AppleIDを新規作成したときに「レビュー」と呼ばれる入力が不要になる。(ID毎にクレジットカード情報入力したり、住所入力したりとしないといけないので新入社員にとっては苦痛でしかない)

なんといってもメリットは1につきると思います。
2についても、新入社員はiPhone/iPadを支給されたらAzureADでログインする"だけ"で良くなるのでとても簡単になります。
...とここまではメリットしかなくて「最高だぜ!!!ヒャッハー!」なんですが、デメリットもあります。大きすぎるデメリットが。

フェデレーションログインによる「デメリット」

  1. 既存のApple IDはフェデレーションログインに移行できない。
  2. AppStoreでアプリ購入するときに、TouchID/FaceIDが使えなくなる。
  3. ユーザプロビジョニングが自動ではない

最大のデメリットは1ですね。
おそらく、会社展開の場合は、「会社使用のメールアドレス」にApple IDを紐付けていると思います。
そして、大多数の方はフェデレーションログインする際にメールアドレスのドメイン部でフェデレーション設定をしたいと思うはずです。
ところが...今回のフェデレーション設定をすると今回のケースのような場合、既存ユーザは別Apple ID作成を強制されます。しかも別ドメインに!

例: 会社のメールアドレスがtaro@hoge-apple.comであり、AppleIDもそのメールアドレスで作成した場合。

  1. 管理者がhoge-apple.comドメインをAzureADによるフェデレーション管理下に置く。(今回のリリース内容をやる)
  2. taro@hoge-apple.comはAppleから「60日以内にApple IDを別のものに変えなさい」とメールが届く。
  3. 別メールアドレスとして、例えばtaro+old@hoge-apple.comとして登録しようとする。
  4. 上記アドレスのドメイン部がフェデレーション管理下に置かれるので、エラーになってしまう。
  5. 泣く泣くicloud.comのIDなどにApple IDを変更せざるを得ない。
    • 課金済みのAppや、電話帳、iCloudストレージなども新Apple IDに移行されてしまう!
  6. taroは新たにtaro@hoge-apple.comとしてAzureADにログインして、"データも何もないまっさらな"Apple IDを使用する。

こんな事態になります。
つまり...

Apple IDを多量に展開済であればあるほど、フェデレーションログインへの移行は難しくなるわけです。。

じゃあ、どうしたらいいの?

現実解としては下記のようになるかなと考えます。
(ぜんぜん、現実的ではないがこれくらいしか打開策が思いつかない)

  1. 既存社員→今まで通り、ID/PASSによるApple IDを継続してもらう。
  2. 新入社員→Apple ID用の ドメイン を取得し、そのドメインを使用してフェデレーションログインをする。
    • 例: 上記例の場合、 taro@appleid.hoge-apple.com といったサブドメインを切るなどが現実的じゃないかと。

設定方法

さて、ここからが本題。
デメリットがとても大きいリリースですが、メリットもゼロじゃないのでいざ設定をしてみようと思います。

手順は公式サイトの下記を参考にやります。
support.apple.com

前提として下記が必要なので準備しておいてください。

  1. ABM(Apple Business Manager)の登録。(詳細は割愛します)
  2. Azure ADのグローバル管理者ユーザ
  3. Azure ADのグローバル管理者ユーザに「姓」「名」を登録しておく。

support.apple.com

前提:

  1. 事前にフェデレーション先Azure Portalにログインしておきます。
    • ※グローバル管理者権限のユーザでのログインが無難です。
  2. ABMにログインします。
  3. 「設定」を選択します。
    • f:id:undersooon:20191202113041p:plain
  4. 「アカウント」を選択します。
    • f:id:undersooon:20191202144800p:plain
  5. 「Federated Authentication」から「編集」を選択し、「接続」ボタンを押します。
    • f:id:undersooon:20191202113501p:plain
    • f:id:undersooon:20191202113530p:plain
  6. ポータルにサインインしろと言われ、許可設定を求められるので「承諾」します。(SAMLではなく、Directory APIを叩くんですね)
    • f:id:undersooon:20191202113732p:plain
    • f:id:undersooon:20191202113842p:plain
  7. ABMの画面に戻り、管理対象のドメイン名を入力して「続ける」を選択します。
    • f:id:undersooon:20191202113905p:plain
  8. また、Azureへのサインインが求められるので対応します。
    • f:id:undersooon:20191202114024p:plain
    • ちなみにこの段階でAzureAD側のグローバル管理者ロールのユーザに姓名が登録されていないとエラーになります。
    • f:id:undersooon:20191202114131p:plain
  9. 登録が成功すると、下記のようにユーザ名の競合のチェックが走ります。競合って?と思ったのですが「既に登録ドメインを使ったApple IDが作成されてないか」チェックするみたいです。
    • f:id:undersooon:20191202122923p:plain
    • ちなみに下記にも自動的に追加される模様
    • f:id:undersooon:20191202123049p:plain
  10. 「アクティビティ」に登録ドメインとバッティングしているApple IDの数が出るので対処します...と言いたいとこですが どのApple IDがバッティングしているかは教えてくれません (つらい...)
  11. というわけで、「設定」-「アカウント」-「Federated Authentication」 でフェデレーションを有効化します。
    • f:id:undersooon:20191202123752p:plain
    • f:id:undersooon:20191202123529p:plain
    • f:id:undersooon:20191202123834p:plain
  12. すると、フェデレーション登録済のユーザが居た場合、下記のようなメール(脅迫メール)が届くようになるので60日以内にユーザ側で移行作業をしてもらいます。
    • f:id:undersooon:20191202123943p:plain
    • ちなみにログインするとこうなります。
    • f:id:undersooon:20191202124653p:plain
  13. 以上

無理やり既存Apple IDをフェデレーションIDにマイグレーションできないかあがいてみた。

  1. ここで、「もともと使っていたApple IDを入力したらフェデレーションユーザにマイグレーションされるんじゃ...?」と淡い期待を込めてやってみますが、 できませんでした AzureAD認証に成功しても下記ウィンドウが再び表示されループします。
    • f:id:undersooon:20191202124653p:plain
  2. ABM側から社員によるID移行前に、既存のApple IDを指定して無理やりマイグレーションできないか試みましたが、これも失敗...。
    • f:id:undersooon:20191202124922p:plain
  3. いっそのことマイグレーションしないで放置してみる(フェデレーションログインとの混在を目指す)とも考えたのですがこれもNG...。
    • Apple ID移行しないとApple側が強制的にApple IDをテンポラリのものへと置き換えるそうです。
    • support.apple.com
      • Apple から最初の通知が届いてから 60 日以内に Apple ID を更新しなかった場合、Apple ID は @temporary.appleid.com を含む仮のユーザ名に変更されます。たとえば、john@example.edu changes は john-example.edu@temporary.appleid.com に変わります。

追記

このフェデレーションは 一度設定するとそのドメインは削除できません (2019.12.2時点) のでご注意ください。
ドメインの追加自体はできるのでまあいいのかもしれませんが、気にされる方はお気をつけを。
(指摘頂いた khakさんありがとうございます!!)

AWS Single Sign-On(AWS SSO)で3rdParty Identity Providerが使えるようになったので試してみた

何が嬉しいわけ??

元記事はこちらです。
feedproxy.google.com

ざっくりいうと、
AWS SSOの認証元として、3rdPartyのSSO製品でユーザ認証ができるようになった
というやつです。

今までは、下記方法によりAWS SSOのユーザ認証が可能でしたがそれぞれ頭を悩ますデメリットがありました。

  • AWS Directory Serviceでユーザ認証
    • デメリット:既に既存のADサーバで運用している場合、統合ができないのでこちらの方式が使用できない
  • AD Connectorで既存ADサーバ情報をAWS上に同期する
    • デメリット:既存ADサーバとVPN接続等で接続するなど何かしら頑張らなければいけない。その後AD Connectorによる接続も必要。
      • AD環境のネットワークアドレスと、VPC上のサブネットが重複していたりするとネットワーク再設計が必要だったり...も。

また、上記デメリットがあるゆえに、IAMでIdentity Providerを登録して運用している人も多いと思います。(私もそうでした)
ただ、これにもデメリットがあり

  • AWSをマルチアカウント運用している場合、それぞれのAWSアカウントでIdentity Provider設定が必要

というなかなか辛い状況もあります。(幸い、Terraform化できるのでコード化できてればそこまで苦労はないといえば無いですが面倒は面倒)

それが、今回のリリースにより 3rdPartyのIdentity Providerが使用できることによりAWS Directory ServiceもAD Connectorも必要なくなったので上記デメリットが払拭された形になります。

また、上記デメリットが払拭されるばかりか、メリットとして

  • SSO後の画面で一時的なAWS CLIクレデンシャルが発行できる

というメリットもあります。(これが地味にすごく便利!!!) 今までは こういった ツールに頼らざるを得なかったので、今回のリリースはもうメリットしかないわけです。
(厳密にいうと、少しだけデメリットはありますが)

というわけで今後、AWS環境とSSOを結ぶ際には今回の方式がデファクトスタンダードになると思われますので、設定してみます。

設定編

基本的には下記記事を実行しているだけなのですが、元記事では手順がざっくりしている箇所もあるのでステップバイステップで少し詳細に書いていきます。 feedproxy.google.com

設定編:前提

前提として、下記準備が必要です。

  1. 対象AWSアカウントのrootアカウントでログインできること。
    • AWS Orgnizationの機能を使っている場合は親AWSアカウントのrootアカウントが必要です。
  2. IdPを用意済であること(今回はAzureADで実装します)

設定編:実装

それでは、上記記事を参考に実装していきます。

  1. Azureにログインし「Azure Active Directory」-「エンタープライズ アプリケーション - すべてのアプリケーション」-「新しいアプリケーション」と選択します。URLでいうと これ です。
  2. 「ギャラリー以外のアプリケーション」を選択します。
  3. f:id:undersooon:20191202010536p:plain
  4. 名前はなんでもいいのですが、わかりやすく「AWS」としておきます。
    • f:id:undersooon:20191202010645p:plain
  5. 作成した設定値に対してシングルサインオンさせたいユーザを選択しておきます。
  6. f:id:undersooon:20191202013713p:plain
  7. シングルサインオン」を選択し、シングルサインオン方式として「SAML」を選択します。
    • f:id:undersooon:20191202010758p:plain
    • f:id:undersooon:20191202010825p:plain
  8. 中腹あたりにある「③SAML名証明書」のメニューの中から「フェデレーションメタデータXML」を選択してダウンロードしておきます。
    • f:id:undersooon:20191202011043p:plain
  9. シングルサインオンしたいAWSアカウントにログインします。
  10. シングルサインオンコンソール( これ ) を開きます。
    • 東京リージョンでは使えない、みたいなエラーが出たりしますがリージョンは特段どこでもいいのでバージニア北部(us-east-1) あたりを選んでおきます。
  11. 「設定」を選びます。
    • f:id:undersooon:20191202011813p:plain
  12. 「IDソース」から「変更」を選びます。
    • f:id:undersooon:20191202011902p:plain
  13. メタデータファイルのダウンロード」をしておく。
    • f:id:undersooon:20191202012335p:plain
  14. AzureADに戻り「メタデータファイルをアップロード」で上記メタデータをアップロードする。
    • f:id:undersooon:20191202013905p:plain
  15. 再びAWSコンソールに戻り、「外部IDプロバイダー」を選択し、先程AzureADからダウンロードしたメタデータXMLをアップロードし、「次:確認」を選択します。
    • f:id:undersooon:20191202012025p:plain
    • f:id:undersooon:20191202012424p:plain
  16. 画面上に指示に従い、更新。
    • f:id:undersooon:20191202012621p:plain
  17. 設定が終わると、「Return to Setting」というボタンがでるので押す。すると一画面前に戻るので「キャンセル」と押してシングルサインオンコンソールに戻る。(ここはUIがよくないですね...)
    • f:id:undersooon:20191202012713p:plain
  18. ここまでで、SSO設定は終わりだが、ユーザプロビジョニング/グループプロビジョニングができないと旨味が全くないのでプロビジョニング設定する。
  19. 「自動プロビジョニングを有効化」を選択する。
    • f:id:undersooon:20191202013025p:plain
  20. 下記のようにSCIMエンドポイントとアクセストークンが表示されるのでメモしておく。
    • ※アクセストークンは一回しか表示されないので必ず値を控えておくこと。
    • f:id:undersooon:20191202013149p:plain
  21. AzureADに戻り「プロビジョニング」を選択して、上記SCIMエンドポイントとアクセストークンを入力し、「テスト接続」をしてみて成功することを確認する。
    • f:id:undersooon:20191202013437p:plain
  22. マッピング」-「Synchronize Azure Active Directory Users to customappsso」を選択する。
    • f:id:undersooon:20191202014108p:plain
  23. 「mail nickname」となっているところを「object ID」に変更して「保存」する。
    • f:id:undersooon:20191202014238p:plain
    • f:id:undersooon:20191202014331p:plain
  24. デフォルトではプロビジョニング周期は40分だが、さっさとテストしたいので下記のようにして「保存」を選択してすぐにプロビジョニングを走らせる。
    • f:id:undersooon:20191202014500p:plain
  25. AWS SSOコンソールに戻り、「ユーザー」欄にプロビジョニングされていれば成功!
    • f:id:undersooon:20191202014625p:plain

運用編

  • AWS アカウント」からSSOさせたいAWSアカウントを選択して、上記プロビジョニング済ユーザを割り当てればOK。(画面の指示に従えば簡単に設定できるので詳細は割愛)
    • f:id:undersooon:20191202014815p:plain
  • (AWS SSOの機能で元々できていたことではありますが)SSO済のポータル(シングルサインオンコンソールにURLが書いてあります)にログインして、「command line or programmatic access」を選択するとAWS CLI用の一時クレデンシャルが取得できます。(Winodowsの場合のものも用意されていて地味にうれしいですね)
    • f:id:undersooon:20191202015141p:plain
    • f:id:undersooon:20191202015102p:plain
    • f:id:undersooon:20191202015437p:plain

最後に

設定自体はとても簡単で、導入後の運用も煩雑なところがなくデメリットが特にないように思えます。 今まで、最初に述べたデメリットのせいでAWS SSOが導入できていなかった方はこの機会に是非導入することをおすすめします。 快適ですよ。