PowerShellでAzureのカスタムロールの作成と適用

##　概要
前回はAzure FunctionsとManagedIdentityを使って、
BlobStorageにデータを格納できた。

ただ、権限がOwner権限だったため必要最低限の権限に絞るようにしたい。
ので、試しにやってみた。

## やったこととか目次

1. カスタムロールの作成
1. コードの修正
2. Functionsへの適用
3. ハマったこと
3. 資料 

## カスタムロールの作成

[PowerShellでのカスタムロールの作成の仕方][]を参考につらつら書く
今回の目的は以下なのでそれが叶うように[ココ][カスタムロール内で使うAction,DataActionの定義]を参考に設定ファイルを作成する

 - blobコンテナへの書き込み(上書き含む)


[ポータルでのカスタムロール作成方法][]が公開されていたのでカスタムロールの作成はポータルからでもできる模様
(ただし2020/03/15現在preview機能)

```json-doc
{
    "Name": "Custom_blobStorageWriter",
    "Id": "5d722adf-39aa-43ea-990f-1ccc4d7bd40e", //作成する時(New-AzRoleDefinition実行時)は空文字
    "IsCustom": true,
    "Description": "Update&Write blobContainer",
    "Actions": [
        "Microsoft.Storage/storageAccounts/read",
        "Microsoft.Storage/storageAccounts/blobServices/containers/delete",
        "Microsoft.Storage/storageAccounts/blobServices/containers/write",
        "Microsoft.Storage/storageAccounts/listKeys/action" //Set-AzCurrentStorageAccountに必要(内部的にアクセスキーを取得している)
    ],
    "NotActions": [],
    "DataActions": [
        "Microsoft.Storage/storageAccounts/blobServices/containers/blobs/delete",
        "Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write"
    ],
    "NotDataActions": [],
    "AssignableScopes": [
        "/subscriptions/[隠してる]" //SubscriptionIDを入れる
    ]
}
```

## コードの修正
コード内でblobコンテナ名を取得しており、
read権限を不要にするため、処理を変更

```powershell
using namespace System.Net

# Input bindings are passed in via param block.
param($Request, $TriggerMetadata)

# Write to the Azure Functions log stream.
Write-Host "PowerShell HTTP trigger function processed a request."

# Interact with query parameters or the body of the request.

(get-date) > .\date.txt

Disconnect-AzAccount
Connect-AzAccount -Identity

(Get-AzSubscription)[0]| Select-AzSubscription 

## そのうち環境変数とかにする
$storageName = "tklogstorage"
$ResourceGroupName = "discordBot"
$containerName = "logs"

Set-AzCurrentStorageAccount -ResourceGroupName $ResourceGroupName -StorageAccountName $storageName
Set-AzStorageBlobContent -File .\date.txt -Container $containerName -Force

## Get-AzStorageAccount/Get-AzStorageContainerの処理にread権限が必要なため変更
# $storageAccount Get-AzStorageAccount | ?{$_.StorageAccountName -eq $storageName}  
# $storageAccount | Get-AzStorageContainer  | ?{$_.name -eq "logs"} |Set-AzStorageBlobContent -force -File .\date.txt

# Associate values to output bindings by calling 'Push-OutputBinding'.
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
    StatusCode = [HttpStatusCode]::OK
    Body = "end"
})

```

##  Functionsへの適用
[PowerShellでのアクセス権の付与の仕方][]を参考にFunctionに対してロールを適用する

適用先としてObjectIDが必要なのでPowerShellなりPortalから確認する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407754/90614ae3-2b54-1ddc-d953-176e5447b90e.png)


```powershell
New-AzRoleAssignment -ObjectId "3ba1b792-94ed-466e-8d75-a9560b89de31" ##上で確認したやつ
                     -RoleDefinitionName "Custom_blobStorageWriter"   ##カスタムロールの作成で作ったJsonのNameフィールド
```
参考リンクではSubscriptionの指定がしてるが、
カスタムロール内で指定していれば不要な模様

## ハマったこと

カスタムロールのJsonは結構ハマった。
どの権限が必要か手探りでやったため、Functionsを都度実行して試したが、
Functionsはインスタンスを再起動しないと過去の設定をキャッシュしているようで変更が反映されなかった。

ただ、エラーログには必要な権限が表示されるので、
手順がわかってしまえばそこまで難しくないかなと。

## 資料

[RBACの概要](https://docs.microsoft.com/ja-jp/azure/role-based-access-control/overview)
[PowerShellでのカスタムロールの作成の仕方][]
[PowerShellでのアクセス権の付与の仕方][]
[カスタムロール内で使うAction,DataActionの定義]

<!-- ### リンク -->

[PowerShellでのカスタムロールの作成の仕方]:https://docs.microsoft.com/ja-jp/azure/role-based-access-control/tutorial-custom-role-powershell
[ポータルでのカスタムロール作成方法]:https://docs.microsoft.com/ja-jp/azure/role-based-access-control/custom-roles-portal
[PowerShellでのアクセス権の付与の仕方]:https://docs.microsoft.com/ja-jp/azure/role-based-access-control/role-assignments-powershell
[カスタムロール内で使うAction,DataActionの定義]:https://docs.microsoft.com/ja-jp/azure/role-based-access-control/resource-provider-operations