Azure Arc対応サーバーでマネージドIDを利用する

#　はじめに
[Azure Arc](https://azure.microsoft.com/ja-jp/services/azure-arc/)とは、オンプレミスや他社クラウド上のサーバーをAzureサービスに統合し一元管理するためのサービスです。
いくつか提供されている機能があるのですが、その中から「マネージドIDを利用してAzureリソースに対し認証を行う」というものを試してみました。

# 環境
今回はOCI上の仮想マシンをAzureに接続してみます。
OSはUbuntu、バージョンは20.04 Minimal、ビルドは2021.12.03-0のものを利用します。

# Azure Arcの準備
[公式のドキュメント](https://docs.microsoft.com/ja-jp/azure/azure-arc/servers/learn/quick-enable-hybrid-vm)を参照しながらやっていきます。

Azure Arcを利用するためにAzureリソースプロバイダーの登録が必要となります。
Cloud ShellかAzure CLIが利用可能な端末から、以下のコマンドを実行します。

```bash
$ az account set --subscription "<利用するサブスクリプション名>"
$ az provider register --namespace 'Microsoft.HybridCompute'
Registering is still on-going. You can monitor using 'az provider show -n Microsoft.HybridCompute'
$ az provider register --namespace 'Microsoft.GuestConfiguration'
Registering is still on-going. You can monitor using 'az provider show -n Microsoft.GuestConfiguration'
```

実行後、登録が完了したかを確認します。

```bash
$ az provider list -o table| grep Microsoft.HybridCompute
Microsoft.HybridCompute                  RegistrationRequired  Registered
$ az provider list -o table| grep Microsoft.GuestConfiguration
Microsoft.GuestConfiguration             RegistrationRequired  Registered
```
両方とも上記のように「Registered」となっていればOKです。

# Azure Arcエージェント インストールスクリプトの生成
まずはサーバが配置されるリソースグループを準備します。
今回は「AzureArc」という空のリソースグループを作成しました。
![スクリーンショット 2022-01-08 1.00.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274613/ee05b74a-7569-797f-e5d5-667d6481be92.png)
リソースグループの「＋作成」ボタンをクリックし、「Azure Arc」で検索、「サーバー - Azure Arc」を選択します。
![スクリーンショット 2022-01-08 1.03.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274613/498653b5-3e98-d359-0dde-6fb35659b218.png)
「作成」をクリック
![スクリーンショット 2022-01-08 1.05.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274613/ac33ae6b-3394-aa14-1334-ff14f6ba0706.png)
今回はサーバー1台のみを接続するため、「単一サーバーの追加」の「スクリプトの生成」をクリックします。
![スクリーンショット 2022-01-08 1.07.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274613/b526dcf7-ad4b-828e-22ed-59537c412ba9.png)

ここからフローに沿ってインストール用スクリプトを生成していきます。
![スクリーンショット 2022-01-08 1.08.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274613/34838a8d-3f43-c60a-cd46-dac7b7ab340c.png)
上記画面に記載のあるように、Azureに対しデータを送信するため、該当サーバーにはAzure宛のアウトバウンド通信が必要となります。
私は試せてないですが、プロキシサーバー経由やExpressRouteやVPN経由での接続もできるようなので、そこまで厳しい要件でもないかと思います。

次のページでは、サブスクリプション・リソースグループ・リージョン・OS種別を選択します。
今回のサーバーは直接インターネット向けのアウトバウンドを許可しているため、ネットワーク接続の項目は「パブリック エンドポイント」を選択します。
![スクリーンショット 2022-01-08 1.14.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274613/d0a68d65-5b2f-40e3-84f2-0c85fbe8f3f8.png)

タグの設定はお好みで…。デフォルトで4つのタグ名が入力されていますが、特に必須というわけではないようです。
![スクリーンショット 2022-01-08 1.16.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274613/39c44793-6de8-4326-bfda-46ce31db67bd.png)

最後のページにエージェントインストール用のスクリプトが表示されます。
ダウンロード、もしくは表示内容をコピーしてインストール対象のサーバ上へ転送します。
![スクリーンショット 2022-01-08 1.18.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274613/b9d8aea4-eaa8-0639-d515-c04604d41256.png)

# サーバーにAzure Arcエージェントを導入する
前項で作成したスクリプトを、インストール対象のサーバ上で実行します。

```bash
$ sudo bash OnboardingScript.sh
--2022-01-07 16:27:30--  https://aka.ms/azcmagent
〜略〜
INFO[0001] All endpoints are available... continue onboarding 
To sign in, use a web browser to open the page https://microsoft.com/devicelogin and enter the code XXXXXXXXX to authenticate.
```
上記のメッセージが表示されたら、お手元の端末のブラウザで「https://microsoft.com/devicelogin」を開き、表示されているコードを入力し登録を進めます。
![スクリーンショット 2022-01-08 1.30.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274613/7a680de6-542c-ab60-16a7-946321c8e404.png)

その後、以下のメッセージが表示されたらインストール終了です。

```bash
INFO[0156] Successfully Onboarded Resource to Azure      VM Id=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
オンボードされたサーバーを表示するには、https://portal.azure.com/#blade/HubsExtension/BrowseResource/resourceType/Microsoft.HybridCompute%2Fmachines に移動します
```
Azureポータルを見ると、サーバーのリソースが追加されています。（ちゃんとOCI上のサーバーだと認識されていますね）
![スクリーンショット 2022-01-08 1.34.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274613/1f34f1d0-b375-70b7-6f82-16d2dee106a7.png)

# マネージドIDの利用準備
Azure Arc対応サーバーでマネージドIDを利用するには、ユーザーが「himds」グループに所属している必要があります。以下のコマンドでグループに追加します。

```bash
$ sudo gpasswd -a $USER himds
```
また、多くのAzure SDKでは環境変数の有無でマネージドIDの利用可否を判断しています。以下のように

- IDENTITY_ENDPOINT
- IMDS_ENDPOINT

の2つの環境変数を追加しておきます。

```bash
echo "export IDENTITY_ENDPOINT=http://localhost:40342/metadata/identity/oauth2/token" >> .bashrc 
echo "export IMDS_ENDPOINT=http://localhost:40342" >> .bashrc
```
グループ設定と環境変数の読み込みのために、一度ログアウトして再度ログインします。

# マネージドIDの利用テスト
今回はBlobストレージへのファイルアップロードでマネージドIDを試してみます。
まずはストレージアカウントを作成し、
![スクリーンショット 2022-01-08 11.27.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274613/0a8de490-29bd-979a-1f57-b133b69aafe9.png)
左ペインの「アクセス制御(IAM)」を開き、上部の「追加」→「ロールの割り当ての追加」を選択、
![スクリーンショット 2022-01-08 11.29.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274613/ec4a194f-0a19-1d9d-2b4d-fa1596ad527c.png)
「ストレージ BLOB データ共同作成者」を選択し次へ、
![スクリーンショット 2022-01-08 11.31.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274613/1b5ed74a-dea0-85d5-8956-68f4023085a8.png)
アクセスの割り当て先で「マネージドID」を選択し、「メンバーを選択する」から今回の対象サーバーを選択します。
![スクリーンショット 2022-01-08 11.32.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274613/9b72adeb-9486-eaad-6628-4e932b6262d5.png)
レビュー画面で問題なければ追加を行い、以下のようにIAMの一覧に追加されていればOKです。
![スクリーンショット 2022-01-08 11.36.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274613/865547c4-d1c5-9d16-ba85-8f3cd1c56673.png)

アップロード先のコンテナーも作成しておきます。「arcupload」という名前で作成しました。
![スクリーンショット 2022-01-08 11.38.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274613/cc387b99-fe92-a935-a6bd-6d0e30658af3.png)

続いては対象サーバー上の作業です。
以下のようなアップロード用のテストファイルを準備し、

```test.txt
upload from arc-test
```
それをアップロードするためのコードをPythonで準備しました。

```upload_blob.py 
from azure.identity import DefaultAzureCredential
from azure.storage.blob import BlobServiceClient
token_credential = DefaultAzureCredential()

blob_service_client = BlobServiceClient(
    account_url="https://<ストレージアカウント名>.blob.core.windows.net",
    credential=token_credential
)

blob_client = blob_service_client.get_blob_client(container='arcupload', blob='test.txt')

with open("test.txt", "rb") as data:
    blob_client.upload_blob(data)
```
必要なAzure SDKをインストールします。

```bash
$ sudo apt install python3-pip
$ sudo pip3 install azure-identity azure-storage-blob
```
準備が整ったら、以下のように実行します。

```bash
$ python3 upload_blob.py
```
エラーなく完了すればOKです。

ポータルからBlobを見てみると、
![スクリーンショット 2022-01-08 11.42.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274613/84c1c420-8b65-a63c-cb33-8440d568177f.png)
ちゃんとアップロードできています！

# おわりに
上記のとおり、コードにも環境変数にも固有の認証情報は持たせずにBlobのアップロードが実現できます。
Azure外のサーバーであってもマネージドIDの仕組みで認証可能というのは便利だと思います。