Azure SDK for Goでの認証方式

「[Azure SDK for Go documentation](https://docs.microsoft.com/ja-jp/azure/developer/go/)」サイトの「[Authentication methods in the Azure SDK for Go](https://docs.microsoft.com/ja-jp/azure/developer/go/azure-sdk-authorization)」ページを読み進めました。

本セクションでは、[Azure SDK for Go](https://github.com/Azure/azure-sdk-for-go)を使ってAzureで認証するための形式と方式が紹介されています。

ここでは、対象ページの内容をベースに...というか結果的にGoogle翻訳による日本語翻訳状態となり、私なりの言い回しを加えています。ちなみに、"type"は"形式"に、"method"は"方式"に、日本語訳しています。

## 利用可能な認証の形式と方式

Azure SDK for Goは複数の資格情報セットと認証形式を提供し、認証形式は複数の認証方式（認証情報をSDKに取り込む操作）で呼び出せます。

提供されている認証形式は、次の通りです。

**証明書ベース形式**

- Azure Active Directory（以降、Azure AD）ユーザーまたはサービスプリンシパル用に構成されたX509証明書を使ってクライアント認証を行います。詳細については「[Get started with certificate-based authentication in Azure Active Directory](https://docs.microsoft.com/en-us/azure/active-directory/authentication/active-directory-certificate-based-authentication-get-started)」を参照してください。

**クライアント資格情報形式**

- アプリケーションに構成済みのサービスプリンシパルを組み込んで認証します。詳細については「[Create a service principal with Azure CLI](https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli?view=azure-cli-latest)」を参照してください。

**AzureリソースのマネージドID形式**

- アプリケーションは、Azure ADが自動的にAzureサービスに提供したマネージドIDを使ってAzure AD認証をサポートするAzureサービスを認証します。詳細は「[Managed identities for Azure resources](https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview)」を参照してください。

**デバイストークン形式**

- 多要素認証を有効にしたユーザーのデバイスにトークンを渡し、WebブラウザーでMicrosoftサインインにアクセスしてAzure ADアカウントで認証します。詳細は「[Use device token authentication](https://docs.microsoft.com/ja-jp/azure/developer/go/azure-sdk-authorization#use-device-token-authentication)」を参照してください。

**ユーザー名/パスワード形式**

- ユーザー名とパスワードで認証します。多要素認証が無効状態でのAzure ADサインインのため、セキュリティ面で不安があります。

【重要】クライアント資格情報形式以外の認証形式を使用する場合、アプリケーションはAzure ADに登録されている必要があります。詳細は「[Integrating applications with Azure Active Directory](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app)」を参照してください。

【注意】特別な要件がない限り、ユーザー名/パスワード形式は避けてください。ユーザーベースのサインインが必要な場合はデバイストークン形式で対応してください。

これらの認証形式は、さまざまな認証方式で利用できます。

**環境ベース方式**

- シェルの環境変数から資格情報を読み取ります。

**ファイルベース方式**

- サービスプリンシパルの資格情報などをファイルから読み込みます。

**クライアントベース方式**

- コード内のオブジェクトを使用し、プログラムの実行中に資格情報を提供する必要があります。

**デバイストークン方式**

- ユーザーはトークンを使用してWebブラウザーからインタラクティブにサインインする必要があります。

すべての認証機能と認証方式は、github.com/Azure/go-autorest/autorest/azure/authパッケージで利用できます。

【注意】特別な要件がない限り、クライアントベース方式は避けてください。認証情報をハードコード化する傾向にあり、認証要件が変更された場合のSDKリリースで機能しなくなる可能性があります。

## 環境ベース方式を使用する

アプリケーションを実行する前にシェルの環境変数を構成し、実行時にこれらの環境変数を読み取り、Azureで認証します。

環境ベース方式は、デバイストークン形式を除くすべての認証形式をサポートしており、次の順序で評価されます。

- クライアント資格情報形式
- 証明書ベース形式
- ユーザー名/パスワード形式
- AzureリソースのマネージドID形式

認証形式に未設定の値があるか拒否された場合、SDKは自動的に次の認証形式を試行し、形式がなくなるとエラーを返します。

次の表は、環境ベース形式でサポートされる認証形式ごとに設定する必要がある環境変数の詳細を示しています。

クライアント資格情報形式

    AZURE_TENANT_ID
        サービスプリンシパルが属するActive DirectoryテナントのID。
    AZURE_CLIENT_ID
        サービスプリンシパルの名前またはID。
    AZURE_CLIENT_SECRET
        サービスプリンシパルに関連付けられているシークレット。

証明書ベース形式

    AZURE_TENANT_ID
        証明書が登録されているActive DirectoryテナントのID。
    AZURE_CLIENT_ID
        証明書に関連付けられているアプリケーションクライアントID。
    AZURE_CERTIFICATE_PATH
        クライアント証明書ファイルへのパス。
    AZURE_CERTIFICATE_PASSWORD
        クライアント証明書のパスワード。

ユーザー名/パスワード形式

    AZURE_TENANT_ID
        ユーザーが属するActive DirectoryテナントのID。
    AZURE_CLIENT_ID
        アプリケーションクライアントID。
    AZURE_USERNAME
        サインインに使用するユーザー名。
    AZURE_PASSWORD
        サインインに使用するパスワード。

AzureリソースのマネージドID形式

    マネージドID形式に資格情報は必要ありません。
    アプリケーションは、マネージドIDを使用するように構成
    されたAzureリソースで実行されている必要があります。
    詳細については「Managed identities for Azure resources(※1)」を
    参照してください。

※1 https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview

既定のAzureパブリッククラウド以外のクラウドまたは管理エンドポイントに接続するには、次の環境変数を設定します。例えば、Azure Stack、別の地域のクラウド、または従来のデプロイモデルを使用している場合です。

    AZURE_ENVIRONMENT
        接続するクラウド環境の名前。
    AZURE_AD_RESOURCE
        接続時に使用するActive DirectoryリソースID。
        管理エンドポイントへのURIとして使用します。

Goコードでは、[NewAuthorizerFromEnvironment](https://godoc.org/github.com/Azure/go-autorest/autorest/azure/auth#NewAuthorizerFromEnvironment)関数を呼び出してオーソライザーオブジェクトを取得します。このオブジェクトは、クライアントのAuthorizerプロパティで設定され、Azureへのアクセスを許可します。

```Go
import "github.com/Azure/go-autorest/autorest/azure/auth"
authorizer, err := auth.NewAuthorizerFromEnvironment()
```

### Azure Stackでの認証

Azure Stackで認証するには、次の環境変数を設定する必要があります。

    AZURE_AD_ENDPOINT
        Active Directoryエンドポイント。
    AZURE_AD_RESOURCE
        Active DirectoryリソースID。

これらの環境変数は、Azure Stackメタデータ情報から取得できます。メタデータを取得するには、Azure Stack環境でWebブラウザーを開き、次のURLを使用します：(ResourceManagerURL)/metadata/endpoints?api-version=1.0

ResourceManagerURLは、Azure Stackデプロイメントのリージョン名、マシン名、および外部の完全修飾ドメイン名（FQDN）によって異なります。

    開発キット
        https://management.local.azurestack.external/
    統合システム
        https://management.(region).ext-(machine-name).(FQDN)

Azure StackでAzure SDK for Goを使用する方法の詳細については「[Use API version profiles with Go in Azure Stack](https://docs.microsoft.com/en-us/azure-stack/user/azure-stack-version-profiles-go?view=azs-2002)」を参照してください。

## ファイルベース方式を使用する

ファイルベース方式では、[Azure CLI](https://docs.microsoft.com/en-us/cli/azure/?view=azure-cli-latest)によって生成されたファイル形式を使用します。--sdk-authパラメータを使用して新しいサービスプリンシパルを作成するときに、このファイルを簡単に作成できます。CLIはstdoutに出力するため、出力をファイルにリダイレクトします。

```
az ad sp create-for-rbac --sdk-auth > azure.auth
```

AZURE_AUTH_LOCATION環境変数を、許可ファイルが配置されている場所に設定します。この環境変数はアプリケーションによって読み取られ、その中の資格情報が解析されます。実行時に認証ファイルを選択する必要がある場合は、[os.Setenv](https://golang.org/pkg/os/#Setenv)関数を使用してプログラムの環境を操作します。

認証情報を読み込むには、[NewAuthorizerFromFile](https://godoc.org/github.com/Azure/go-autorest/autorest/azure/auth#NewAuthorizerFromFile)関数を呼び出します。環境ベース方式とは異なり、ファイルベース方式にはリソースエンドポイントが必要です。

```Go
import "github.com/Azure/go-autorest/autorest/azure/auth"
authorizer, err := NewAuthorizerFromFile(azure.PublicCloud.ResourceManagerEndpoint)
```

サービスプリンシパルの使用とアクセス許可の管理の詳細については「[Create a service principal with Azure CLI](https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli?view=azure-cli-latest)」を参照してください。

## デバイストークン方式を使用する

ユーザーにインタラクティブにサインインさせる場合は、デバイストークン方式が最適です。ユーザーにトークンを渡してMicrosoftサインインサイトに貼り付け、Azure Active Directory（AAD）アカウントで認証します。この認証方式は、標準のユーザー名/パスワード方式とは異なり、多要素認証が有効になっているアカウントをサポートします。

[NewDeviceFlowConfig](https://godoc.org/github.com/Azure/go-autorest/autorest/azure/auth#NewDeviceFlowConfig)関数を使用して[DeviceFlowConfig](https://godoc.org/github.com/Azure/go-autorest/autorest/azure/auth#DeviceFlowConfig)オーソライザーを作成します。結果のオブジェクトで[Authorizer](https://godoc.org/github.com/Azure/go-autorest/autorest/azure/auth#DeviceFlowConfig.Authorizer)を呼び出して、認証プロセスを開始します。デバイスフロー認証は、認証フロー全体が完了するまでプログラムの実行をブロックします。

```Go
import "github.com/Azure/go-autorest/autorest/azure/auth"
deviceConfig := auth.NewDeviceFlowConfig(applicationID, tenantID)
authorizer, err := deviceConfig.Authorizer()
```

## 認証クライアントを使用する

特定の形式の認証が必要で、プログラムがユーザーからの認証情報を読み込んで処理を進める場合は、[auth.AuthorizerConfig](https://docs.microsoft.com/ja-jp/azure/developer/go/azure-sdk-authorization)インターフェースに準拠する任意のクライアントを使用できます。次の場合は、このインターフェースを実装する型を使用します。

- インタラクティブなプログラムを書く
- 専用の構成ファイルを使用する
- 用意されている認証形式では対応できない要件である

【警告】Azure資格情報をアプリケーションにハードコードしないでください。アプリケーションのバイナリーにシークレットを入れると、アプリケーションが実行されているかどうかにかかわらず、攻撃者がシークレットを簡単に抽出できます。これにより、資格情報が承認されているすべてのAzureリソースが危険にさらされます。

次の表に、AuthorizerConfigインターフェースに準拠するSDKの形式を示します。

    証明書ベース形式
        ClientCertificateConfig(※1)
    クライアント資格情報形式
        ClientCredentialsConfig(※2)
    AzureリソースのマネージドID形式
        MSIConfig(※3)
    ユーザー名/パスワード形式
        UsernamePasswordConfig(※4)

※1 https://godoc.org/github.com/Azure/go-autorest/autorest/azure/auth#ClientCertificateConfig
※2 https://godoc.org/github.com/Azure/go-autorest/autorest/azure/auth#ClientCredentialsConfig
※3 https://godoc.org/github.com/Azure/go-autorest/autorest/azure/auth#MSIConfig
※4 https://godoc.org/github.com/Azure/go-autorest/autorest/azure/auth#UsernamePasswordConfig

関連付けられたNew関数を使用してオーセンティケーターを作成し、結果のオブジェクトに対してAuthorizeを呼び出して認証します。たとえば、証明書ベース形式を使用するには次のようになります：

```Go
import "github.com/Azure/go-autorest/autorest/azure/auth"
certificateAuthorizer := auth.NewClientCertificateConfig(certificatePath, certificatePassword, clientID, tenantID)
authorizerToken, err := certificateAuthorizer.Authorize()
```