Azure Lighthouseを使ってみた

# きっかけ
先月Microsoft Inspire　2019に参加させていただく機会があり、
MSPサービスとして盛り上がっていたAzure Lighthouseについて検証を行ったのでその備忘録として記載します。
# Azure Lighthouseとは
公式HPに以下の3本柱が記載されています。
 1. クラウド管理の自動化とスケーリング
 2. より高度な可視性とガバナンスを実現
 3. 顧客への新しいアプローチ方法により、市場を拡大する

、、、あまりよくわからない、、、
一言でいうならば、
**「サブスクリプションの管理権限を異なるAzure AD(以下AAD)に紐づく環境に委任できるサービス」**
これによって、顧客所有のサブスクリプションをプロバイダが管理できるようになる！といったメリットがあります。
早速検証内容にいきます。細かい注意点や仕様は適宜はさんでいきます。
# 検証内容
## 前提
1. プロバイダ用サブスクリプション(委任先)とカスタマー用サブスクリプション（委任元）が用意できていること。(AADは別)
2. プロバイダユーザは、"ユーザ管理者権限"を持っていること。カスタマーユーザは"所有者権限"を持っていること。

## プロバイダ用サブスクリプション側の作業
1. プロバイダ用サブスクリプション環境にログインする。
2. 委任先となるAADユーザ/AADグループを作成する。
委任先は、以下の3つを選択できるが、管理上「AADグループ」をお勧めする。

- **AADグループ**
- Service Principle
- Managed Identity

## カスタマー用サブスクリプション側の作業
1. カスタマー用サブスクリプション環境にAzure CLIでログインする。
※ここでAzure CLIでログインした理由は、のちに権限委任のARMテンプレートを展開することになるが、Azure CLIが個人的にやりやすかったためです。というよりもPortalからやろうとするとなぜか展開先のリソースグループが要求されうまくいかなかった。。

2. 操作対象のサブスクリプションを指定

```
$ az account set --subscription　<サブスクリプションID>
```

3. Microsoft.ManagedServicesが登録済として表示されていることを確認する。

```
$ az provider show –namespace "Microsoft.ManagedServices" –-output table
```

※登録済み時の結果

```
    Namespace                  RegistrationState
    -------------------------  -------------------
    Microsoft.ManagedServices  Registered
```

※登録されていない場合は、以下URLを参照して登録する。
https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-manager-supported-services
4.　権限委任のためのARMテンプレート(ParameterFile含む)を作成する。
※委任する元のスコープは以下を選択できる。ものによってARMテンプレートが異なるので注意が必要。
今回は①のサブスクリプションで作成した。現在は未対応であるが、リソース単体での委任もリリース予定のよう。

| | オンボードの対象|TemplateFile|ParameterFile|
|:--:|:--------------|:----------------------|:----------------------|
|1| Subscription|[delegatedResourceManagement.json](https://github.com/Azure/Azure-Lighthouse-samples/blob/master/Azure-Delegated-Resource-Management/templates/delegated-resource-management/delegatedResourceManagement.json)|[delegatedResourceManagement.parameters.json](https://github.com/Azure/Azure-Lighthouse-samples/blob/master/Azure-Delegated-Resource-Management/templates/delegated-resource-management/delegatedResourceManagement.parameters.json)|
|2| Resource group| [rgDelegatedResourceManagement.json](https://github.com/Azure/Azure-Lighthouse-samples/blob/master/Azure-Delegated-Resource-Management/templates/rg-delegated-resource-management/rgDelegatedResourceManagement.json)|[rgDelegatedResourceManagement.parameters.json](https://github.com/Azure/Azure-Lighthouse-samples/blob/master/Azure-Delegated-Resource-Management/templates/rg-delegated-resource-management/rgDelegatedResourceManagement.parameters.json)|
|3|サブスクリプション内の複数のリソース グループ|[multipleRgDelegatedResourceManagement.json](https://github.com/Azure/Azure-Lighthouse-samples/blob/master/Azure-Delegated-Resource-Management/templates/rg-delegated-resource-management/multipleRgDelegatedResourceManagement.json)|[multipleRgDelegatedResourceManagement.parameters.json](https://github.com/Azure/Azure-Lighthouse-samples/blob/master/Azure-Delegated-Resource-Management/templates/rg-delegated-resource-management/multipleRgDelegatedResourceManagement.parameters.json)|
|4| サブスクリプション (Azure Marketplace に公開されたオファーの使用時) |[marketplaceDelegatedResourceManagement.json](https://github.com/Azure/Azure-Lighthouse-samples/blob/master/Azure-Delegated-Resource-Management/templates/marketplace-delegated-resource-management/marketplaceDelegatedResourceManagement.json)|[marketplaceDelegatedResourceManagement.parameters.json](https://github.com/Azure/Azure-Lighthouse-samples/blob/master/Azure-Delegated-Resource-Management/templates/marketplace-delegated-resource-management/marketplaceDelegatedResourceManagement.parameters.json)|



今回私が作成したARMテンプレートを記載しておきます。
- TemplateFile

```
{
    "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "mspName": {
            "type": "string",
            "metadata": {
                "description": "Specify the Managed Service Provider name"
            }
        },
        "mspOfferDescription": {
            "type": "string",
            "metadata": {
                "description": "Name of the Managed Service Provider offering"
            }
        },
        "managedByTenantId": {
            "type": "string",
            "metadata": {
                "description": "Specify the tenant id of the Managed Service Provider"
            }
        },
        "authorizations": {
            "type": "array",
            "metadata": {
                "description": "Specify an array of objects, containing tuples of Azure Active Directory principalId, a Azure roleDefinitionId, and an optional principalIdDisplayName. The roleDefinition specified is granted to the principalId in the provider's Active Directory and the principalIdDisplayName is visible to customers."
            }
        }              
    },
    "variables": {
        "mspRegistrationName": "[guid(parameters('mspName'))]",
        "mspAssignmentName": "[guid(parameters('mspName'))]"
    },
    "resources": [
        {
            "type": "Microsoft.ManagedServices/registrationDefinitions",
            "apiVersion": "2019-06-01",
            "name": "[variables('mspRegistrationName')]",
            "properties": {
                "registrationDefinitionName": "[parameters('mspName')]",
                "description": "[parameters('mspOfferDescription')]",
                "managedByTenantId": "[parameters('managedByTenantId')]",
                "authorizations": "[parameters('authorizations')]"
            }
        },
        {
            "type": "Microsoft.ManagedServices/registrationAssignments",
            "apiVersion": "2019-06-01",
            "name": "[variables('mspAssignmentName')]",
            "dependsOn": [
                "[resourceId('Microsoft.ManagedServices/registrationDefinitions/', variables('mspRegistrationName'))]"
            ],
            "properties": {
                "registrationDefinitionId": "[resourceId('Microsoft.ManagedServices/registrationDefinitions/', variables('mspRegistrationName'))]"
            }
        }
    ],
    "outputs": {
        "mspName": {
            "type": "string",
            "value": "[concat('Managed by', ' ', parameters('mspName'))]"
        },
        "authorizations": {
            "type": "array",
            "value": "[parameters('authorizations')]"
        }
    }
}
```


- ParameterFile

※"managedByTenantId"はプロバイダ(委任先)のテナントID
※"principalId"は、プロバイダ(委任先)のAADグループのObjectID
※今回はContributorの権限(b24988ac-6180-42a0-ab88-20f7382dd24c)を委任する設定とした。

```
{
    "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentParameters.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "mspName": {
            "value": "test-provider"
        },
        "mspOfferDescription": {
            "value": "test management"
        },
        "managedByTenantId": {
            "value": "********-****-****-****-************"
        },
        "authorizations": {
            "value": [
                {
                    "principalId": "********-****-****-****-************",
                    "principalIdDisplayName": "Tier 1 Support",
                    "roleDefinitionId": "b24988ac-6180-42a0-ab88-20f7382dd24c"
                }
            ]
        }
    }
}
```

5. 作成したARMテンプレートを展開する。

```
$ az deployment create --location <Region> --template-file <テンプレートのファイルのパス> --parameters <テンプレートのパラメータのパス> --verbose
```

## 確認作業
1. カスタマー側からの確認
2. 
「Home」>「Service providers」>「Service provider offers」に遷移し、委任先のテナントが表示されていることを確認する。
2. プロバイダ側からの確認
「Home」>「My customer」>「Customers」に遷移し、委任元のカスタマー環境のサブスクリプションが登録されていることを確認する。


以上が基本的な設定となります。
上記設定をすることで、Azure Portal内の各サービス画面から委任されているサブスクリプションを選択可能となり、あたかも自分のAADに紐づいているサブスクリプションのように操作ができるようになる。
なぜか一覧に出てこない場合は、以下のような手順を行ってみてください。
「Home」>「Monitor」>「Alert」などに遷移し、同画面の「Don't see a subscription? Open Directory + Subscription settings」を押下する。
※右ブレードにてカスタマーの”ディレクトリ”と”サブスクリプション”のボックスにチェックを入れることによって、他のサービスでも選択可能となる(バグ？)。


# その他
* 以下の権限委任について以下の制限があります。
>ロールの割り当てでは、ロールベースのアクセス制御 (RBAC) の組み込みロールを使用する必要があります。 現在、組み込みロールはすべて、Azure の委任されたリソース管理でサポートされています。ただし、所有者、ユーザー アクセス管理者、および DataActions アクセス許可を持つ組み込みロールは除きます。 また、カスタムロールと従来のサブスクリプション管理者ロールはサポートされていません。

* 複数の組み込みロールの割り当て方法
ParameterFileを以下のような記述にします。

```
{
・・・
	"authorizations": {
        "value": [
        {
    　       "principalId": "********-****-****-****-************",
            "principalIdDisplayName": "Tier 1 Support",
            "roleDefinitionId": "b24988ac-6180-42a0-ab88-20f7382dd24c"
        },
        {
            "principalId": "********-****-****-****-************",
            "principalIdDisplayName": "Tier 2 Support",
            "roleDefinitionId": "fb1c8493-542b-48eb-b624-b4c8fea62acd"
	
・・・
}
```

# さいごに
ネットにも情報がなく私自身も手探りで検証しました。何かご意見ご指摘あれば気軽にお声掛けください！