2020年5月4日月曜日

Azure SDK for Goでの認証方式

Azure SDK for Go documentation」サイトの「Authentication methods in the Azure SDK for Go」ページを読み進めました。

本セクションでは、Azure SDK for Goを使ってAzureで認証するための形式と方式が紹介されています。

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

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


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

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

証明書ベース形式


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

  • アプリケーションに構成済みのサービスプリンシパルを組み込んで認証します。詳細については「Create a service principal with Azure CLI」を参照してください。

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

  • アプリケーションは、Azure ADが自動的にAzureサービスに提供したマネージドIDを使ってAzure AD認証をサポートするAzureサービスを認証します。詳細は「Managed identities for Azure resources」を参照してください。

デバイストークン形式

  • 多要素認証を有効にしたユーザーのデバイスにトークンを渡し、WebブラウザーでMicrosoftサインインにアクセスしてAzure ADアカウントで認証します。詳細は「Use device token authentication」を参照してください。

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

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

【重要】クライアント資格情報形式以外の認証形式を使用する場合、アプリケーションはAzure ADに登録されている必要があります。詳細は「Integrating applications with Azure Active Directory」を参照してください。

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

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

環境ベース方式

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

ファイルベース方式

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

クライアントベース方式

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

デバイストークン方式

  • ユーザーはトークンを使用して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」を
        参照してください。

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

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

Goコードでは、NewAuthorizerFromEnvironment関数を呼び出してオーソライザーオブジェクトを取得します。このオブジェクトは、クライアントのAuthorizerプロパティで設定され、Azureへのアクセスを許可します。

        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」を参照してください。

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


ファイルベース方式では、Azure CLIによって生成されたファイル形式を使用します。--sdk-authパラメータを使用して新しいサービスプリンシパルを作成するときに、このファイルを簡単に作成できます。CLIはstdoutに出力するため、出力をファイルにリダイレクトします。

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

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

認証情報を読み込むには、NewAuthorizerFromFile関数を呼び出します。環境ベース方式とは異なり、ファイルベース方式にはリソースエンドポイントが必要です。

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

サービスプリンシパルの使用とアクセス許可の管理の詳細については「Create a service principal with Azure CLI」を参照してください。

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


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

NewDeviceFlowConfig関数を使用してDeviceFlowConfigオーソライザーを作成します。結果のオブジェクトでAuthorizerを呼び出して、認証プロセスを開始します。デバイスフロー認証は、認証フロー全体が完了するまでプログラムの実行をブロックします。

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

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


特定の形式の認証が必要で、プログラムがユーザーからの認証情報を読み込んで処理を進める場合は、auth.AuthorizerConfigインターフェースに準拠する任意のクライアントを使用できます。次の場合は、このインターフェースを実装する型を使用します。

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

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

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

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

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

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

2020年5月1日金曜日

Goで月末日の時は増加減した月の月末日を返す

GoのtimeパッケージのAddDate()関数ですが、例えば10月31日に1ヶ月を足すと11月31日となりDateの正規化によって12月1日になります。

package main

import (
        "fmt"
        "time"
)

func main() {
        t := time.Date(2019, 10, 31, 0, 0, 0, 0, time.Local)
        fmt.Println(t)
        fmt.Println(t.AddDate(0, 1, 0), "(Add 1 month)")
}

実行結果

2019-10-31 00:00:00 +0000 UTC
2019-12-01 00:00:00 +0000 UTC (Add 1 month)

そこで、月末日の時は増減した月の月末日、すなわち、10月31日に1ヶ月を足すと11月30日となる関数「AddMonth()」を考えてみました。(注意:横スクロールしてください)
package main

import (
        "fmt"
        "time"
)

// AddMonth returns the time corresponding to adding the
// given number of months to t.
// For example, AddMonth(t, 2) applied to January 1, 2011
// (= t) returns March 1, 2011.
//
// AddMonth does not normalize its result in the same way
// that Date does, so, for example, adding one month to
// October 31 yields November 30.
func AddMonth(t time.Time, months int) time.Time {
        lastMonthDay := func(t time.Time) int {
                return time.Date(t.Year(), t.Month()+1, 1, 0, 0, 0, 0, t.Location()).AddDate(0, 0, -1).Day()
        }

        // Creating 1st Date from t and adding months because AddDate() normalizes t.
        am := time.Date(t.Year(), t.Month(), 1, 0, 0, 0, 0, t.Location()).AddDate(0, months, 0)
        ad := lastMonthDay(am)

        if ld := lastMonthDay(t); t.Day() == ld || t.Day() > ad {
                return time.Date(am.Year(), am.Month(), ad, am.Hour(), am.Minute(), am.Second(), am.Nanosecond(), am.Location())
        }

        return t.AddDate(0, months, 0)
}

func main() {
        cnt := 14

        fmt.Println("First Days")
        ft := time.Date(2020, 2, 1, 0, 0, 0, 0, time.Local)
        for i := -cnt; i <= -1; i++ {
                fmt.Println(AddMonth(ft, i), "(Add", i, "month)")
        }
        fmt.Println(ft)
        for i := 1; i <= cnt; i++ {
                fmt.Println(AddMonth(ft, i), "(Add", i, "month)")
        }

        fmt.Println()

        fmt.Println("Last Days")
        lt := time.Date(2020, 2, 29, 0, 0, 0, 0, time.Local)
        for i := -cnt; i <= -1; i++ {
                fmt.Println(AddMonth(lt, i), "(Add", i, "month)")
        }
        fmt.Println(lt)
        for i := 1; i <= cnt; i++ {
                fmt.Println(AddMonth(lt, i), "(Add", i, "month)")
        }
}

実行結果

First Days
2018-12-01 00:00:00 +0000 UTC (Add -14 month)
2019-01-01 00:00:00 +0000 UTC (Add -13 month)
2019-02-01 00:00:00 +0000 UTC (Add -12 month)
2019-03-01 00:00:00 +0000 UTC (Add -11 month)
2019-04-01 00:00:00 +0000 UTC (Add -10 month)
2019-05-01 00:00:00 +0000 UTC (Add -9 month)
2019-06-01 00:00:00 +0000 UTC (Add -8 month)
2019-07-01 00:00:00 +0000 UTC (Add -7 month)
2019-08-01 00:00:00 +0000 UTC (Add -6 month)
2019-09-01 00:00:00 +0000 UTC (Add -5 month)
2019-10-01 00:00:00 +0000 UTC (Add -4 month)
2019-11-01 00:00:00 +0000 UTC (Add -3 month)
2019-12-01 00:00:00 +0000 UTC (Add -2 month)
2020-01-01 00:00:00 +0000 UTC (Add -1 month)
2020-02-01 00:00:00 +0000 UTC
2020-03-01 00:00:00 +0000 UTC (Add 1 month)
2020-04-01 00:00:00 +0000 UTC (Add 2 month)
2020-05-01 00:00:00 +0000 UTC (Add 3 month)
2020-06-01 00:00:00 +0000 UTC (Add 4 month)
2020-07-01 00:00:00 +0000 UTC (Add 5 month)
2020-08-01 00:00:00 +0000 UTC (Add 6 month)
2020-09-01 00:00:00 +0000 UTC (Add 7 month)
2020-10-01 00:00:00 +0000 UTC (Add 8 month)
2020-11-01 00:00:00 +0000 UTC (Add 9 month)
2020-12-01 00:00:00 +0000 UTC (Add 10 month)
2021-01-01 00:00:00 +0000 UTC (Add 11 month)
2021-02-01 00:00:00 +0000 UTC (Add 12 month)
2021-03-01 00:00:00 +0000 UTC (Add 13 month)
2021-04-01 00:00:00 +0000 UTC (Add 14 month)

Last Days
2018-12-31 00:00:00 +0000 UTC (Add -14 month)
2019-01-31 00:00:00 +0000 UTC (Add -13 month)
2019-02-28 00:00:00 +0000 UTC (Add -12 month)
2019-03-31 00:00:00 +0000 UTC (Add -11 month)
2019-04-30 00:00:00 +0000 UTC (Add -10 month)
2019-05-31 00:00:00 +0000 UTC (Add -9 month)
2019-06-30 00:00:00 +0000 UTC (Add -8 month)
2019-07-31 00:00:00 +0000 UTC (Add -7 month)
2019-08-31 00:00:00 +0000 UTC (Add -6 month)
2019-09-30 00:00:00 +0000 UTC (Add -5 month)
2019-10-31 00:00:00 +0000 UTC (Add -4 month)
2019-11-30 00:00:00 +0000 UTC (Add -3 month)
2019-12-31 00:00:00 +0000 UTC (Add -2 month)
2020-01-31 00:00:00 +0000 UTC (Add -1 month)
2020-02-29 00:00:00 +0000 UTC
2020-03-31 00:00:00 +0000 UTC (Add 1 month)
2020-04-30 00:00:00 +0000 UTC (Add 2 month)
2020-05-31 00:00:00 +0000 UTC (Add 3 month)
2020-06-30 00:00:00 +0000 UTC (Add 4 month)
2020-07-31 00:00:00 +0000 UTC (Add 5 month)
2020-08-31 00:00:00 +0000 UTC (Add 6 month)
2020-09-30 00:00:00 +0000 UTC (Add 7 month)
2020-10-31 00:00:00 +0000 UTC (Add 8 month)
2020-11-30 00:00:00 +0000 UTC (Add 9 month)
2020-12-31 00:00:00 +0000 UTC (Add 10 month)
2021-01-31 00:00:00 +0000 UTC (Add 11 month)
2021-02-28 00:00:00 +0000 UTC (Add 12 month)
2021-03-31 00:00:00 +0000 UTC (Add 13 month)
2021-04-30 00:00:00 +0000 UTC (Add 14 month)

月末日に関しては、12ヶ月の月末日の並びから

        ...,31|31,28&29,31,30,31,30,31,31,30,31,30,31|31,...

30日が連続することがないことを考慮して、以下のケースで動作確認しました。(基:基準日の月末日)

        -1 基 +1
        -- -- --
        31,28,31
        31,29,31
        31,30,31
        28,31,30
        29,31,30
        30,31,30
        30,31,31
        31,31,28
        31,31,29
        31,31,30

例)基準日が2019年2月28日で前後2ヶ月の月末日を出力するmain()関数内のコード。

        tl := time.Date(2019, 2, 28, 0, 0, 0, 0, time.Local)
        fmt.Println(AddMonth(tl, -2), "(Add -2 month)")
        fmt.Println(AddMonth(tl, -1), "(Add -1 month)")
        fmt.Println(tl)
        fmt.Println(AddMonth(tl, 1), "(Add 1 month)")
        fmt.Println(AddMonth(tl, 2), "(Add 2 month)")

2020.05.02 11月30日の時に-1ヶ月すると10月31日ではなく10月30日になっていた不具合を修正しました。

2020.05.03 2020年3月31日の時に-1ヶ月すると2月29日ではなく3月1日になっていた不具合を修正しました。

2020年4月29日水曜日

GoでSubversionからパッケージをgo getして実行する(自マシン内完結型)

社内や個人でSubversionを使ってGoコードを管理しているGopherには朗報!?Go 1.14から、goコマンドはmoduleモードでSubversionリポジトリーをサポートしました。

しかしながら、具体的な手順がなかなか見つかりませんでした。そこで「自マシン内のSubversionサーバーに登録されたGoの外部パッケージを、自マシン内で取得して実行する」ことを色々と目標に試してみました。実際に動作した時は心の中でガッツポーツ!q@w@p

Subversionサーバーの構築

自マシンに「Subversion」と「Apache HTTP Server」をインストールします。

Apache HTTP Serverには、Subversionと連動してHTTP/HTTPS通信でアクセスできる仕組みが用意されています。

今回は、諸事情によりno_ssl版のためHTTP通信でアクセスした場合の内容となっています。openssl版&HTTPS通信であればスマートに進められるはずです。

ちなみに、Subversionからの外部パッケージの取得には、svnコマンドが使用されます。

本筋ではないため、具体的なインストールやセットアップについては割愛します。

Subversionリポジトリーの作成

svnadmin createコマンドで新規リポジトリーを作成します。

リポジトリー内に、branches/、tags/、trunk/、の定番ディレクトリーを作成します。

ここでは以下のパス構成を想定しています。

svn://127.0.0.1/go/trunk/src/

本筋ではないため、具体的な手順は割愛します。

GOPROXYとGOSUMDBの無効化

今回は、諸事情により外部へのインターネット接続が制限されているため、moduleに関する2つの環境変数の値を無効化します。

GOPROXYとGOSUMDBの初期値を確認します。

$ go env GOPROXY
https://proxy.golang.org,direct

$ go env GOSUMDB
sum.golang.org

GOPROXYとGOSUMDBに無効値を設定します。

$ go env -w GOPROXY=direct
$ go env -w GOSUMDB=off

GOPATH上への移動

以降、GOPATH上で作業します。GOPATHは以下のコマンドで確認できます。

$ go env GOPATH

外部パッケージをSubversionに登録

外部パッケージとして、Add()関数を持つcalcパッケージを用意します。

calc/ディレクトリーを作成します。

$ mkdir calc

calc/ディレクトリー内に移動します。

$ cd calc

modの初期化を行います。

$ go mod init

作成されたgo.modファイルのmodule行をURLパスに修正します。

修正前:

module calc

go 1.14

修正後:

module 127.0.0.1/svn/go/trunk/src/calc.svn

go 1.14

calc.goを作成します。

$ vim calc.go

package calc

func Add(x, y int) int {
return x + y
}

calc/ディレクトリーをSubversionにチェックインします。
# 私はsvnコマンドではなく、Eclipseでチェックインしています m(__)m

svn://127.0.0.1/go/trunk/src/
|
+--calc/
   |
   +--calc.go
   +--go.mod

メイン パッケージの作成

test/ディレクトリーを作成します。

$ mkdir test

test/ディレクトリー内に移動します。

$ cd test

modの初期化を行います。

$ go mod init

main.goファイルを作成します。

$ vim main.go

package main

import (
"fmt"

calc "127.0.0.1/svn/go/trunk/src/calc.svn"
)

func main() {
fmt.Println(calc.Add(1, 2))
}

外部パッケージURLのホストが自マシンの場合、IPアドレス(ここでは127.0.0.1)で指定します。localhostで指定すると「import path does not begin with hostname」エラーになります。

通常でしたら、ここでmain.goファイルを実行します。

$ go run main.go

この時、import句の"127.0.0.1/svn/go/trunk/src/calc.svn"にHTTPS通信でアクセスして自動で外部パッケージが取得されます。

https://127.0.0.1/svn/go/trunk/src/calc.svn?go-get=1

しかし、今回はHTTP通信のためエラーとなります。そのため、go getコマンドを実行して手動で外部パッケージを取得します。

通常、go getするURLにはHTTPS通信でアクセスします。

$ go get 127.0.0.1/svn/go/trunk/src/calc.svn

今回はHTTP通信のため、-insecure オプションを付けてgo getします。

$ go get -insecure 127.0.0.1/svn/go/trunk/src/calc.svn

main.goファイルを実行すると、外部パッケージ「calc」のAdd(1, 2)が実行されて、結果の3が標準出力されます!

$ go run main.go
3

メイン パッケージのモジュール情報

go.sumファイルが作成されます。

$ vim -R go.sum

127.0.0.1/svn/go/trunk/src/calc.svn v0.0.0-YYYYMMDD... h1:...=
127.0.0.1/svn/go/trunk/src/calc.svn v0.0.0-YYYYMMDD.../go.mod h1:...=

go.modファイルに外部パッケージが追加されます。

$ vim -R go.mod

module test

go 1.14

require 127.0.0.1/svn/go/trunk/src/calc.svn v0.0.0-YYYYMMDD... // indirect

気づいた点など

go getではデフォルトでHTTPS通信が行われています。
→Subversionと連動させるApache HTTP Serverはopenssl版を使いましょう。

Subversionの外部パッケージURLの最後には「.svn」が必要です。
→GihHub経由に慣れていると、なかなか気付けない。

import句にて、Subversion経由の外部パッケージには別名を付けて使用します。
→本ページでは"127.0.0.1/svn/go/trunk/src/calc.svn"にcalcと別名付けています。

関連するGoのソースコード
→使われているsvnコマンドの引数とかがわかります。

2020年4月26日日曜日

Azure SDK for Goを使う上での開発者向けツール

Azure SDK for Go documentation」サイトの「Tools for developers using the Azure SDK for Go」ページを読み進めました。

本セクションでは、Azure SDK for Goを使用する上でGoコードを効率的に記述したりAzureサービスとシームレスに連携したりする開発者向けツールが紹介されています。

ここでは、対象ページの内容をベースとして、私なりの解説を加えてみます。

Azure CLI

AzureにはAPIを操作する方法として、WebブラウザーでログインしてのGUI操作、Azure SDKを使ってのコード操作の他に、Azure CLIによるコマンドライン操作が用意されています。


Azure CLIは az コマンドで操作を行い、Windowsは実行バイナリーで、macOSとLinuxはPython 3スクリプトでインストールされます。またDockerやAzure Cloud shellでも実行可能です。

CLIのメリットは、コマンドライン上で他のコマンドと組み合わせて一連の処理をスクリプト化して実行できる柔軟性の良さが挙げられます。

個人的には、Goのマルチプラットフォーム向けに処理速度の良さも含めた実行バイナリーを提供できるメリットを生かして「Azure CLIこそGoで!」と思うのですが、如何でしょうか?(Google社のパブリッククラウド「Google Cloud Platform」のCLIツールであるgcloudコマンドにも同様に思うところ)

Visual Studio Code

Visual Studio Code(以下、vscode)は、Microsoft社が提供しているオープンソースのコードエディターで、エクステンション(いわゆるプラグイン)をインストールすることで機能拡張でき、オートコンプリート、実装テンプレート、リファクタリング、デバッグなどの機能が追加されます。


Goコードを効率的にコーディングするためのエクステンションとして「ms-vscode.Go」がMicrosoft社員にて開発&サポートされており、デバッガーとして「delve」が対応しています。


2015年11月のvscodeのベータ版の公開時にms-vscode.Goも紹介され、当時はGopherとして「Microsoft社がGoへの取り組みもしっかり行なっている!」と感動しました。


本セクションでは、Azure サービスと連携するためのエクステンションがまとめられた「Azure Extension Pack」も紹介されていますが、


リンク先のエクステンション提供サイト「Marketplace」では非公開(unpublished)になっているため、今後は個々のAzureサービス用のエクステンションをインストールして使用することになります。

Azure DevOps プロジェクトでのCI/CD

Azure上にデプロイしているGoアプリケーションを継続的インティグレーション/継続的デリバリー(CI/CD:Continuous Integration/Continuous Delivery)するには、Azure DevOps Project パイプラインを使用します。これにより、gitリポジトリー上のGoアプリケーションのソースコードを直接Azureにデプロイしてテストすることができます。


depによる依存関係管理

Azure SDK for Goは、パッケージ(ライブラリー)の依存関係管理にdepを使用しています。


depはGoでパッケージ依存管理を行うためのプロジェクトとしてスタートしました。現在のGo本体には、これらの成果を反映した「Go Modules」が実装されています。Go Moludesの採用によりdepの開発も収束しており、今後はAzure SDK for GoもGo Modules化が進むと思われます。

2020年3月29日日曜日

「autorest」および「go-autorest」とは?

Azure SDK for Go documentation」サイトの「Install the Azure SDK for Go」ページを読み進めています。

Include the Azure SDK for Go in your project」セクションにて、GoでAzure サービスを使うには Azure/azure-sdk-for-go とは別に Azure/go-autorest もインポートする必要があるとの記述がありましたので、autorestについて少し調べてみました。

ちなみに Azure/go-autorest は Azure/azure-sdk-for-go をgo getした時に一緒にダウンロードされます。

  • go get -u -d github.com/Azure/azure-sdk-for-go/...

AzureのREST API

AzureにはREST APIが用意されており、各プログラミング言語はAzure SDKで用意されているHTTPクライアントを通じてこのAPIにアクセスし、Azureとの連携を図ります。

AzureのREST API 仕様はOpen API 仕様 形式で書かれており、また、公開されています。


Azure SDKで用意されているHTTPクライアントは、この仕様書をautorestに読み込ませて自動作成されています。

Azure/autorest

autorestは、Microsoft社が開発している汎用(Azure専用ではない)オープンソースのツールで、Open API 仕様 形式を読み込んでRESTful Webサービスにアクセスするクライアント ライブラリーを生成します。

OpenAPI 3.0をサポートしており、PowerShall、C#、Python、Java、TypeScript、Ruby、そしてGoのHTTPクライアント ライブラリーを生成できます。

Azure/go-autorest

go-autorestは、autorestで作成されたAzure SDK for Goのクライアント ライブラリーに対して、ゴルーチンを使ってHTTPリクエストを並列処理できる機能を追加するパッケージで、

  • Azure Active Directory 認証 ライブラリー (autorest/adal)
  • 日付型を正確にパースするパッケージ (autorest/date)
  • 型アサーション(autorest/to)
  • モック (autorest/mock)
  • バリデーション (autorest/validation)
  • ロガー (logger)

なども含まれています。

例:autorest/adal(Active Directory Authentication Library

クライアント サービスでは、毎回ログイン画面からログインするのはわずらわしいため、リソースを操作するためのアプケーション IDである「サービス プリンシパル」を作成してアクセスします。


autorest/adal はサービス プリンシパルのトークンを扱うためのパッケージです。


今回で「Azure SDK for Go のインストール / Install the Azure SDK for Go」ページを読み終えたことになります。

P.S. これまで通りja-jpでアクセスしたのですが日本語ドキュメントが表示されなくなっていました... > Microsoftさん

2020年3月20日金曜日

「Azure SDK for Go」とは別の独自サービスパッケージ

Azure SDK for Go のドキュメント」サイトの「Azure SDK for Go のインストール」ページを読み進みています。

Azure SDK for Go を入手する」セクションにて、いくつかのAzure サービス用のパッケージは Azure/azure-sdk-for-go とは別に用意されているとの記述があり、それらは主にストレージ サービスとメッセージング サービスのパッケージです。

ストレージ サービス

File Storage(パッケージ:Azure/azure-storage-file-go

  • Azure上に構築されたSMB プロトコルのファイル共有システム。
  • 汎用 OS(Linux, macOS, Windows、など)でのファイル共有で使用。

Blob Storage(パッケージ:Azure/azure-storage-blob-go

  • ファイルをBLOBで扱うストレージ。
  • 大量データの蓄積や操作(アーカイブ、ランダム アクセス、データ解析、など)

Queue storage(パッケージ:Azure/azure-storage-queue-go

  • RESTでのテキストメッセージをキューイングする。
  • Service Busと比べてキューイング(格納)に重きが置かれている。

Table storage(パッケージ:なし)

  • 分散Key-Valueストア。

メッセージング サービス

Service Bus(パッケージ:Azure/azure-service-bus-go

  • TCP プロトコルのメッセージをキューイングしたりPub/Subで処理する。
  • Queue Storageと比べてメッセージングに重きが置かれている。

Event Hubs(パッケージ:Azure/azure-event-hubs-go

  • HTTPS/AMQP/Kafka プロトコルの大量のイベントを受け取って、Kafka プロトコルに対応したサービスに振り分ける。
  • ビッグ データ向け。

Event Grid(パッケージ:なし)

  • 対応したAzure サービスからのイベントを受け取って、対応したAzure サービスに振り分ける。

サービスのパッケージが分家する動きは、Azure SDK for Goがベータ版だった時からあり、最初はストレージでした。

2020年3月15日日曜日

「Azure Stack」とは?

Azure SDK for Go のドキュメント」サイトの「Azure SDK for Go のインストール」ページの「Azure SDK for Go を入手する」セクションにて、Azure SDK for GoはGo 1.8以上をサポートしているが、Azure Stack環境だとGo 1.9以上が必要だと書かれてあります。

Azure Stack」は初めて見聞きするサービス名なので少し調べました。

Azure Stackは、グローバル Azureを利用できない企業などがオンプレミス環境で利用できる様にしたAzureの拡張機能です。

自社内にMicrosoft 認定 ハードウェア パートナーから提供されたAzure Stackをセットアップした物理 サーバーを構えることで、オンプレミスで利用したりグローバル Azureと連携させたりできます。

Azure Stackには3つの製品ファミリーがあります。

Azure Stack Hub

  • 仮想マシン、Webアプリ&関数、コンテナーなどを実行するサーバー製品。
  • 運用はオンプレミスで、グローバル Azureとの連携も可能。

Azure Stack Edge

  • 主にAI/ML向けでFPGAが組み込まれた1Uラックマウント型サーバー製品。
  • 処理したデータはネットワーク経由でグローバル Azureに転送。

Azure Stack HCI

  • Azure HCIを採用したサーバー製品。
  • サービスは仮想マシンとして実行してグローバル Azureと連携する。

個人的には、自社でサーバー用 Azureがインストールされた物理 サーバーを購入して運用するソリューション サービスだと解釈しました。

【用語の補足】

  • グローバル Azure:パブリック クラウド版 Azureのこと
  • オンプレミス (on-premise):自社内にハードウェアやソフトウェアを構築して情報システムを運用する形態。
  • HCI (Hyper Converged Infrastructure):CPU処理、ストレージ、ネットワークを仮想化して統合した基盤