Slide 1

Slide 1 text

Microsoft Graph API Library for Go 2019-10-28 Takeshi Yaegashi Go Conference 2019 Autumn

Slide 2

Slide 2 text

自己紹介 八重樫 剛史 Takeshi Yaegashi ● 株式会社バンダイナムコスタジオ所属 ● Linux・Unix・OSS・低レベルなことが好きなエンジニア ● ホームページ・ブログ https://l0w.dev ● Go のお仕事 ○ Raspberry Pi を使った IoT 案件 ○ スマホゲームアプリのサーバ ● Go のお話 ○ golang.tokyo #25「golang binary hacks」 ○ golang.tokyo #26「Raspberry Pi + Go で IoT した話」

Slide 3

Slide 3 text

本日のお話 msgraph.go ● https://github.com/yaegashi/msgraph.go ● Microsoft Graph の紹介 ● msgraph.go の使用方法とアプリケーション、デモ (動画) ● Go 言語用クライアントライブラリの状況 ● msgraph.go の実装と工夫した点 ● 今後の計画

Slide 4

Slide 4 text

Microsoft Graph の紹介

Slide 5

Slide 5 text

Microsoft Graph API とは ● Microsoft のクラウドサービス (Office 365 など) を扱う統合 API https://docs.microsoft.com/ja-jp/graph/overview ● 次のようなリソースを操作するアプリを作成できる ○ ユーザー・グループ・デバイス・ライセンス (Azure Active Directory) ○ メール・連絡先・予定表・チャット (Outlook, Teams) ○ ストレージ・ファイル・サイト (OneDrive, SharePoint) ● Office 365 を導入している会社や個人にとって利用価値が高い API

Slide 6

Slide 6 text

Microsoft Graph API プログラミング ● 共通のエンドポイントを使用する REST API セット ○ API Endpoint (v1.0): https://graph.microsoft.com/v1.0 ○ API Reference: https://docs.microsoft.com/ja-jp/graph/api/overview ● 各言語・処理系用のクライアントライブラリ (SDK) https://microsoftgraph.github.io/msgraph-sdk-design/ ○ .NET(C#), Java, JavaScript, Objective C, PHP, Ruby, Python, … ○ 2019年10月現在、公式のGo言語用ライブラリはまだない

Slide 7

Slide 7 text

Go 言語用のクライアントライブラリの状況 ● GitHub をリポジトリ検索してみると… ○ https://github.com/search?l=Go&q=msgraph&type=Repositories ○ go-msgraph, msgraph-go, msgoraph, … 未完のプロジェクトが多数 ● msgraph.go = 今回紹介するライブラリ ○ https://github.com/yaegashi/msgraph.go ○ 2019年7月に開発開始 ○ msgraph.go という名前は既存のライブラリとの衝突を避けた結果

Slide 8

Slide 8 text

msgraph.go 使用法とアプリの例

Slide 9

Slide 9 text

msgraph.go 使用法:Graph Client の作成 import "github.com/yaegashi/msgraph.go/auth" import msgraph "github.com/yaegashi/msgraph.go/v1.0" // Create HTTP client with Azure AD OAuth2 device authorization grant m := auth.NewTokenManager() t, err := m.DeviceAuthorizationGrant(tenantID, clientID, scope, nil) if err != nil { /*...*/ } httpClient := t.Client(context.Background()) // Create MS Graph client graphClient := msgraph.NewClient(httpClient) ● 最初に Graph Client を作成する ● Azure Active Directory に対して OAuth2 認証を行う http.Client が必要 https://github.com/yaegashi/msgraph.go/tree/master/auth

Slide 10

Slide 10 text

msgraph.go 使用法:REST API 発行 // Get current user’s information // "GET https://graph.microsoft.com/v1.0/me" -> *msgraph.User user, err := graphClient.Me().Request().Get() if err != nil { /*...*/ } // Get current user's OneDrive root folder items // "GET https://graph.microsoft.com/v1.0/me/drive/root/children" -> []msgraph.DriveItem items, err := graphClient.Me().Drive().Root().Children().Request().Get() if err != nil { /*...*/ } // Create new group // "POST https://graph.microsoft.com/v1.0/groups" -> *msgraph.Group newGroup := &msgraph.Group{ /*...*/ } createdGroup, err := graphClient.Groups().Request().Add(newGroup) if err != nil { /*...*/ } ● メソッド呼び出しの連結で REST API の HTTP リクエストが出せる レスポンスの JSON に対応するモデルの struct が返される

Slide 11

Slide 11 text

msgraph.go 使用法:REST API 対応コード REST API msgraph.go 説明 GET /users users, err := cli.Users().Request().Get() 全ユーザー取得 POST /users u := &msgraph.User{/*...*/} user, err := cli.Users().Request().Add(u) ユーザー作成 GET /users/XXX user, err := cli.Users().ID("XXX").Request().Get() ユーザー取得 PATCH /users/XXX u := &msgraph.User{/*...*/} err := cli.Users().ID("XXX").Request().Update(u) ユーザー更新 DELETE /users/XXX err := cli.Users().ID("XXX").Request().Delete() ユーザー削除 ● 各リソースコレクションの操作メソッドとモデル struct 定義が利用可能

Slide 12

Slide 12 text

msgraph.go 使用法:IDE による補完の活用 ● REST API 仕様が Go 言語化されており IDE による補完が活用できる ● ただし Visual Studio Code は知恵熱を出して沈黙することがあり たまに Restart Language Server する必要がある

Slide 13

Slide 13 text

msgraph.go アプリケーションの例:SharePoint ファイル共有アクセス ● SharePoint (OneDrive) ファイル共有のファイルを編集 ● Microsoft Flow で CI ジョブ開始 msgraph.go でファイルをダウンロード ● ファイル共有上の Excel ブックの中身を直接編集する API もある

Slide 14

Slide 14 text

msgraph.go アプリケーションの例:msgraph-sshpubkey ● https://github.com/yaegashi/msgraph.go/tree/master/cmd/msgraph-sshpubkey ● SSH 公開鍵を User の extensions で管理できる (オープン拡張機能) ● sshd_config の AuthorizedKeysCommand で実行してユーザー認証 ● サイズ 5.6MB の実行ファイルで導入が容易 AuthorizedKeysCommand /usr/bin/msgraph-sshpubkey -config /etc/msgraph-sshpubkey.json -login %u AuthorizedKeysCommandUser root $ cat /etc/msgraph-sshpubkey.json { "tenant_id": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX", "client_id": "YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY", "client_secret": "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ", "login_map": { "yaegashi": "[email protected]" } }

Slide 15

Slide 15 text

msgraph.go の実装

Slide 16

Slide 16 text

クライアントライブラリの実装戦略 = コード生成 ● 膨大な MS Graph の機能をカバーするにはコード生成が必須 ● OData v4 の REST API の定義 (XML) から自動生成する ● https://graph.microsoft.com/v1.0/$metadata ...

Slide 17

Slide 17 text

2 種類のコードジェネレータの存在 ● MSGraph SDK Code Generator https://github.com/microsoftgraph/MSGraph-SDK-Code-Generator ○ Microsoft 公式 MS Graph SDK コードジェネレータ ○ C# および .NET Framework による実装 (開発に Windows が必要) ○ C# (.NET Core), Java, JavaScript, Objective-C, Python ● msgraph.go コードジェネレータ https://github.com/yaegashi/msgraph.go/gen ○ Pure Go による実装

Slide 18

Slide 18 text

なぜ MSGraph SDK Code Generator があるのに msgraph.go を? ● 実は MSGraph SDK Code Generator の存在を知らなかった ○ C# (.NET) 用のライブラリを参考に msgraph.go を作り始めて しばらく経ってから気づいた ○ 現在の msgraph.go は MSGraph SDK Code Generator を パクったリスペクトしたコード生成を行う ● MSGraph SDK Code Generator はクロスプラットフォームでない ○ 新しい言語の対応を追加するには Windows の開発環境が必要 ○ C# よくわからない

Slide 19

Slide 19 text

msgraph.go のコード生成 ● go generate ./gen ○ metadata XML のダウンロードとコード生成を行う ○ v1.0 と beta の 2 つの API バージョンのコードを生成する ○ text/template によりテンプレートファイルからコードを生成する ○ 生成したファイルに goimports を実行して整形・import 解決 package gen //go:generate go run msgraph-download.go -pretty -baseURL https://graph.microsoft.com/v1.0 -out metadata-v1.0.xml //go:generate go run msgraph-download.go -pretty -baseURL https://graph.microsoft.com/beta -out metadata-beta.xml //go:generate go run msgraph-generate.go -baseURL https://graph.microsoft.com/v1.0 -in metadata-v1.0.xml -out ../v1.0 //go:generate go run msgraph-generate.go -baseURL https://graph.microsoft.com/beta -in metadata-beta.xml -out ../beta

Slide 20

Slide 20 text

msgraph.go の生成ファイル 種類 生成ファイル名 v1.0 beta 定数 〜Enum.go 188 528 モデル 〜Model.go 638 1684 リクエスト 〜Request.go 247 645 アクション 〜Action.go 59 134 合計 1132 2991 ● 型名・メソッド名・ファイル名は C# (.NET) 版ライブラリに倣っている ● 生成ファイルの数が多すぎ?のため godoc.org で正しく表示できない

Slide 21

Slide 21 text

生成コードの例:モデル struct の定義 type User struct { DirectoryObject UserPrincipalName *string `json:"userPrincipalName,omitempty"` DisplayName *string `json:"displayName,omitempty"` PasswordProfile *PasswordProfile `json:"passwordProfile,omitempty"` /*...*/ } type PasswordProfile struct { Object Password *string `json:"password,omitempty"` ForceChangePasswordNextSignIn *bool `json:"forceChangePasswordNextSignIn,omitempty"` ForceChangePasswordNextSignInWithMFA *bool `json:"forceChangePasswordNextSignInWithMfa,omitempty"` } ● encoding/json の利用を前提としたフィールド名とタグがつけられる ● 基本型 (int, string, bool, etc.) や構造体はすべてポインタ型となる ● struct 埋め込みによりモデル継承、全モデルは Object struct をひとつ含む struct埋め込み

Slide 22

Slide 22 text

JSON に含まれる追加データ ● API が返す JSON には、モデル struct のフィールドで定義されていない "@odata.context" のような追加データが含まれることがよくある ● これらを単に encoding/json で Unmarshal すると失われてしまう GET https://graph.microsoft.com/v1.0/me/ { "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users/$entity", "businessPhones": [], "displayName": "八重樫 剛史", "givenName": "剛史", "jobTitle": null, "mail": "[email protected]", "mobilePhone": null, "officeLocation": null, "preferredLanguage": null, "surname": "八重樫", "userPrincipalName": "[email protected]", "id": "6764eb11-841c-444e-b770-0e0d8748ea0a" }

Slide 23

Slide 23 text

Object / AdditionalData / jsonx による追加データの対応 type Object struct { AdditionalData map[string]interface{} `json:"-" jsonx:"true"` } func (o *Object) SetAdditionalData(key string, val interface{}) {/*...*/} func (o *Object) GetAdditionalData(key string) (interface{}, bool) {/*...*/} user, err := graphClient.Me().Request().Get() if err != nil { /*...*/ } if context, ok := user.GetAdditionalData("@odata.context"); ok { fmt.Println(context) // -> https://graph.microsoft.com/v1.0/$metadata#users/$entity } ● Object の AdditionalData がいわゆる catch-all 動作で追加データを格納する ● encoding/json を改造・拡張した jsonx により実現 https://github.com/yaegashi/msgraph.go/tree/master/jsonx

Slide 24

Slide 24 text

まとめ

Slide 25

Slide 25 text

msgraph.go 開発の進捗と今後の計画 ● これまでの進捗 ○ Go 言語で簡単な Microsft Graph アプリが作成できる段階 ● 今後の計画 ○ 未対応機能実装:、バッチリクエスト、長時間操作、etc. ○ 開発インフラ整備:ユニットテスト、CI/CD ○ ドキュメント:godoc.org 使えん問題解決、Graph API ドキュメント ○ ライブラリ API の安定化

Slide 26

Slide 26 text

公式コードジェネレータとの関わりについて ● Microsoft Graph SDKs - Requirements and Design https://microsoftgraph.github.io/msgraph-sdk-design/ ● 公式 MSGraph SDK Code Generator を Go 言語に対応させたい ○ 今後のライブラリの保守を考えると、公式コードジェネレータに Go に対応して もらったほうが望ましいと思われる ○ msgraph.go のコード生成の経験 (jsonx とか) が生かせるはず

Slide 27

Slide 27 text

おわり msgraph.go ぜひ使ってみてください プルリクエストもお待ちしております!