Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Microsoft Graph API Library for Go

Microsoft Graph API Library for Go

Go Conference Tokyo 2019 Autumn
https://gocon.jp/sessions/microsoft_graph_api_library_for_go/

msgraph.go demo - SharePoint Online + Microsoft Flow + GitLab CI
https://www.youtube.com/watch?v=DwKk405XyF4

msgraph.go
https://github.com/yaegashi/msgraph.go

YAEGASHI Takeshi

October 28, 2019
Tweet

More Decks by YAEGASHI Takeshi

Other Decks in Technology

Transcript

  1. 自己紹介 八重樫 剛史 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 した話」
  2. 本日のお話 msgraph.go • https://github.com/yaegashi/msgraph.go • Microsoft Graph の紹介 • msgraph.go

    の使用方法とアプリケーション、デモ (動画) • Go 言語用クライアントライブラリの状況 • msgraph.go の実装と工夫した点 • 今後の計画
  3. 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
  4. 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言語用ライブラリはまだない
  5. 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 という名前は既存のライブラリとの衝突を避けた結果
  6. 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
  7. 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 が返される
  8. 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 定義が利用可能
  9. msgraph.go 使用法:IDE による補完の活用 • REST API 仕様が Go 言語化されており IDE

    による補完が活用できる • ただし Visual Studio Code は知恵熱を出して沈黙することがあり たまに Restart Language Server する必要がある
  10. msgraph.go アプリケーションの例:SharePoint ファイル共有アクセス • SharePoint (OneDrive) ファイル共有のファイルを編集 • Microsoft Flow

    で CI ジョブ開始 msgraph.go でファイルをダウンロード • ファイル共有上の Excel ブックの中身を直接編集する API もある
  11. 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]" } }
  12. クライアントライブラリの実装戦略 = コード生成 • 膨大な MS Graph の機能をカバーするにはコード生成が必須 • OData

    v4 の REST API の定義 (XML) から自動生成する • https://graph.microsoft.com/v1.0/$metadata <EntityType Name="user" BaseType="microsoft.graph.directoryObject" OpenType="true"> <Property Name="userPrincipalName" Type="Edm.String" /> <Property Name="displayName" Type="Edm.String" /> <Property Name="passwordProfile" Type="microsoft.graph.passwordProfile" /> ... </EntityType> <ComplexType Name="passwordProfile"> <Property Name="password" Type="Edm.String" /> <Property Name="forceChangePasswordNextSignIn" Type="Edm.Boolean" /> <Property Name="forceChangePasswordNextSignInWithMfa" Type="Edm.Boolean" /> </ComplexType>
  13. 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 による実装
  14. なぜ 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# よくわからない
  15. 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
  16. msgraph.go の生成ファイル 種類 生成ファイル名 v1.0 beta 定数 <EnumType> 〜Enum.go 188

    528 モデル <EntityType> <ComplexType> 〜Model.go 638 1684 リクエスト 〜Request.go 247 645 アクション <Action> 〜Action.go 59 134 合計 1132 2991 • 型名・メソッド名・ファイル名は C# (.NET) 版ライブラリに倣っている • 生成ファイルの数が多すぎ?のため godoc.org で正しく表示できない
  17. 生成コードの例:モデル 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埋め込み
  18. 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" }
  19. 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
  20. msgraph.go 開発の進捗と今後の計画 • これまでの進捗 ◦ Go 言語で簡単な Microsft Graph アプリが作成できる段階

    • 今後の計画 ◦ 未対応機能実装:<Function>、バッチリクエスト、長時間操作、etc. ◦ 開発インフラ整備:ユニットテスト、CI/CD ◦ ドキュメント:godoc.org 使えん問題解決、Graph API ドキュメント ◦ ライブラリ API の安定化
  21. 公式コードジェネレータとの関わりについて • Microsoft Graph SDKs - Requirements and Design https://microsoftgraph.github.io/msgraph-sdk-design/

    • 公式 MSGraph SDK Code Generator を Go 言語に対応させたい ◦ 今後のライブラリの保守を考えると、公式コードジェネレータに Go に対応して もらったほうが望ましいと思われる ◦ msgraph.go のコード生成の経験 (jsonx とか) が生かせるはず