Google Apps Scriptでグループアドレスの作成・削除を行う【GAS】
Google Apps Scriptで地味な存在ながら非常に重要な機能を担ってるのが「Googleグループ」。単なるメーリングリストとしての機能だけではなく、Google Driveのアクセス権をまとめて付与する場合にも、このグループのアドレスで管理したりします。
そんなグループアドレスを作成するにはちょっと手間が必要です。
目次
今回使用するスプレッドシート
- グループ一括作成 - Google Spreadsheet
グループの作成で利用するメソッドは、Google Workspaceの管理者権限が必要です。よって通常のユーザ権限では実行ができないので要注意。今回のコードでは紹介していませんが、Enterprise Standard以上で使える動的グループについては、Admin SDKではなくCloud Identity APIを使って作成が出来るようです。
事前準備
グループの作成は1つのメソッドではなく、3つのメソッドを使って作成する必要があります。また、その際に利用するクラスは
スクリプトエディタを開き、左サイドバーのサービスの+をクリックして以下の追加を行います。
- Admin SDK APIを追加する
- GroupSettings APIを追加する
図:2つのサービスが必要です
ソースコード
グループを作成 => グループ設定を変更 => メンバーを追加という3ターンで1グループが作成できます。
グループの作成
1 2 3 4 5 6 7 8 9 10 |
//作成 try{ //グループの作成 var group = AdminDirectory.Groups.insert({ email: groupaddress, name : groupname, }); }catch(e){ } |
- AdminDirectory.Groups.insertで追加します
- emailがグループアドレスの指定場所
- nameがグループ名を指定する場所です
グループ設定変更
このグループ作成で一番配慮しなければいけないのが、グループのアクセス設定。一歩間違えると社内のメールが外部の第三者にだだ漏れという事件が嘗てありましたが、それが起こりかねません。また勝手に外部のメンバーがリクエストしてグループに入れるというのもマズイ。
また、内部の人間にむやみに権限を与えて、外部メンバーを追加できてしまうというのもまたマズイということでこれらのアクセスタイプ。これをよく考えてコードで設定する必要があります。
アクセスタイプについて
次のコードのoptionの中身がグループに対する様々なアクセス権を設定するものになります。主によく使うパターンは以下内容になります。
- whoCanViewMembership(メンバーを表示できるユーザ)
ALL_IN_DOMAIN_CAN_VIEW = 組織全体
ALL_MEMBERS_CAN_VIEW = グループメンバー - whoCanContactOwner(グループのオーナーに連絡出来るユーザ)
ANYONE_CAN_CONTACT = 外部含め誰でも
ALL_MEMBERS_CAN_CONTACT = グループメンバー - whoCanViewGroup(会話を閲覧できるユーザ)
これが一番重要な設定で誤った設定をすると第三者にグループメールの中身が世界中に漏洩することになります。
ALL_IN_DOMAIN_CAN_VIEW = 組織内なら誰でも
ALL_MEMBERS_CAN_VIEW = グループメンバー - whoCanPostMessage(投稿出来るユーザ)
こちらも通常はメンバー以外の投稿を認めない設定が良いでしょう
ANYONE_CAN_POST = 外部含め誰でも
ALL_MEMBERS_CAN_POST = グループメンバーALL_IN_DOMAIN_CAN_POST = ドメイン内のメンバーならだれでも - whoCanModerateMembers(メンバーの管理)
通常メンバーにメンバーの管理権限は与えません。
OWNERS_ONLY = オーナーのみ
OWNERS_AND_MANAGERS = オーナーとマネージャのみ - whoCanJoin(グループに参加できるユーザ)
CAN_REQUEST_TO_JOIN = 組織内全員がリクエスト出来る - allowExternalMembers(組織外のメンバーの許可)
false = 外部メンバー追加はさせない
true = 外部メンバーを追加を許可する
※但し、trueでなくとも管理コンソールからは追加できる。しかしGASからはtrueにしておかないと外部メンバーは追加できない
ソースコード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
//アクセスタイプを設定 var option = { whoCanViewMembership: 'ALL_IN_DOMAIN_CAN_VIEW', whoCanContactOwner: 'ANYONE_CAN_CONTACT', whoCanViewGroup: 'ALL_MEMBERS_CAN_VIEW', whoCanPostMessage: 'ANYONE_CAN_POST', archiveOnly: 'false', whoCanModerateMembers: 'OWNERS_AND_MANAGERS', whoCanJoin: 'CAN_REQUEST_TO_JOIN', allowExternalMembers: 'true' }; try{ //アクセスタイプ設定 var accessType = AdminGroupsSettings.Groups.patch(option, groupaddress); }catch(e){ } |
- optionにて、アクセスタイプを定義します
- 今回のオプションは社内で利用する場合に推奨されるパターンのオプションとなります。
- AdminGroupsSettings.Groups.patchにてアクセスタイプを反映させます
- groupaddressにはグループアドレスを入れます。
図:これがアクセスタイプ
メンバーの追加
AdminDirectoryを使う場合
1 2 3 4 5 6 7 8 9 |
//メールアドレスを取得 let member = {email: "hoge@tomato.com"}; try{ //グループにユーザーを追加 var res = AdminDirectory.Members.insert(member,groupaddress); }catch(e){ } |
- member変数でJSON形式でメンバーのアドレスを構築
- AdminDirectory.Members.insertにてメンバーを追加する
- groupaddressにてグループアドレスを指定する
Cloud Identity Groups APIを使う場合
2020年10月に追加されたCloud Identity Groups APIというものがあるのですが、こちらのAPIを使ってメンバーの追加や更新を行う場合は、対象者のグループ参加有効期限を設定可能です。GUI上や他のメソッドからは出来ない動作になります。このAPIはREST APIとなっているため、GASからはUrlfetchAppで叩いてリクエストしますが、Cloud Identity Premium / Enterprise Standard以上でなければ利用出来ません。
このAPIはGCP側のAPIとなるので、事前準備が必要です。以下の手順で構築します。
※但し、1時間後にexpireと指示してみましたが、削除されず・・・日数単位での指定が必要のようです。
※セットしてる最中は、対象者のロールの変更などは手動で出来ません。
APIを有効にする
Google Cloud Console側でAPIを有効化する必要性があります。
- GCPのプロジェクトを開く
- 左サイドバーからAPIとサービスにて、「APIとサービスの有効化」をクリックする
- Cloud Identityと検索すると出てくるので、クリックします。
- 有効化をクリックします。
- Admin SDK APIも検索して追加しておきます。
- 認証情報の作成は不要です
GASのスクリプトエディタ左側のサービスにて、Admin ADKも追加しておきましょう。
図:有効化をしておくだけでOK
図:サービスとしても追加
GASのプロジェクトを紐付けする
Google Apps ScriptとCloud Consoleのプロジェクトを紐付けする作業が必要です。以下の手順でプロジェクトの変更を行います。
- Cloud Console側のプロジェクトのホームを開き、「プロジェクト番号」を控えておく
- Google Apps Scriptのスクリプトエディタを開く
- サイドバーからプロジェクト設定を開く
- GCPプロジェクトの「プロジェクトを変更」をクリック
- GCPのプロジェクト番号に、1.の番号を入力して、プロジェクトを設定をクリック
- これで紐付けが完了しました。
図:プロジェクトの移動も必須の作業です
appscript.jsonの編集
appscript.jsonに以下のような感じで、oauthScopesを追加して起きます。appscript.jsonの表示は、サイドバーのプロジェクト設定より、「appsscript.json」マニフェスト ファイルをエディタで表示するにチェックを入れると表示されるようになります。GCPのAPIを使う為に必要です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
{ "timeZone": "Asia/Tokyo", "dependencies": { }, "exceptionLogging": "STACKDRIVER", "runtimeVersion": "V8", "oauthScopes": [ "https://www.googleapis.com/auth/userinfo.profile", "https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/script.external_request", "https://www.googleapis.com/auth/cloud-identity.groups", "https://www.googleapis.com/auth/admin.directory.user" ] } |
セットするソースコード
このコードは対象のグループに対して、期限付きでユーザを追加するコードです。すでに追加済のユーザに対しての変更は、こちらのメソッドを利用して更新します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
//GWS顧客IDを取得する function getCustomerId(){ var customer = AdminDirectory.Users.get(Session.getEffectiveUser().getEmail()) return customer.customerId } //グループのリソース名を取得する //groups/xxxxxxといったリソース名を取得するための関数 function getGroupName(groupman){ var url = "https://cloudidentity.googleapis.com/v1beta1/groups?parent=customers/ "+ getCustomerId(); var param = { method : "get", headers : { "Authorization": "Bearer " + ScriptApp.getOAuthToken() }, }; var pageToken ; do{ var page = JSON.parse(UrlFetchApp.fetch(url,param).getContentText()); if(page.groups && page.groups.length > 0){ for(var i = 0; i< page.groups.length;i++){ if(page.groups[i].groupKey.id === groupman){ return page.groups[i].name; } } } pageToken = page.nextPageToken }while(pageToken) } //有効期限をセットしたユーザをグループに追加する function makeGroupUserlimit() { //対象のグループアドレス let groupaddr = "ここに追加先のグループアドレスを入力" //グループ名を取得する let groupman = getGroupName(groupaddr) //作成エンドポイント let endpoint = 'https://cloudidentity.googleapis.com/v1beta1/'+groupman+'/memberships'; //OAuth Tokenを取得 let token = ScriptApp.getOAuthToken(); //リミット日付 const expire = 1; //指定日数後にExpireする const now = new Date(); //指定日数後の日時を算出(日本時間) let expiration = new Date(now.getTime() + (expire * 24 * 60 * 60 * 1000)); let expiretime = Utilities.formatDate(expiration, "JST", "yyyy-MM-dd'T'HH:mm:ss'Z'") //リクエストボディ let body = { "preferredMemberKey": { "id": "ここに対象のユーザのメールアドレスを入力" //対象ユーザメールアドレス }, "roles": [ { "expiryDetail": { "expireTime": expiretime }, "name": "MEMBER" } ] } //ヘッダ情報 let header = { Authorization: "Bearer " + token } //リクエストオプション let options = { headers: header, method: "POST", contentType: "application/json", payload: JSON.stringify(body), muteHttpExceptions: true } //URLリクエスト let response = UrlFetchApp.fetch(endpoint,options); //レスポンス内容を取得 let retcode = response.getResponseCode(); //作成実行の結果 if(retcode == 200){ let ret = response.getContentText(); console.log(ret) return ret; }else{ //失敗 console.log("失敗") return false; } } |
- getGroupName関数で、groups/xxxxという形式のグループのリソース名を取得しておきます。
- getCustomerId関数で、Google Workspaceの顧客IDを取得します(管理コンソール上でも表示されてる)
-
makeGroupUserlimit関数にて、グループリソース名をもってしてURLを構築し、対象ユーザに期限を設定して追加します。
- 利用するエンドポイントは、「https://cloudidentity.googleapis.com/v1beta1/groups/xxxx/memberships」という形式になります。
- リクエストボディにn日後のリミットとしてexpireTimeを指定し、このときの日付時刻はJSTで指定すること
- 成功するとレスポンスコードは200で返ってくる
管理コンソール上のグループにはこれでメンバーが新規追加されますが、表面上リミットを確認する為のUIは存在しません。成功すると以下のような内容がレスポンスとして取得可能です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
{ "done": true, "response": { "@type": "type.googleapis.com/google.apps.cloudidentity.groups.v1beta1.Membership", "name": "groups/xxxxx/memberships/1111111", "memberKey": { "id": "対象のユーザのメールアドレス" }, "roles": [ { "name": "MEMBER", "expiryDetail": { "expireTime": "2024-08-06T19:33:20Z" } } ], "preferredMemberKey": { "id": "対象のユーザのメールアドレス" } } } |
expireする日を確認するコード
expireする日を指定することは出来ましたが、管理コンソール上などで失効する日は確認することができません。よって、これはコードでのみ確認することが出来ます。以下のコードの中でグループアドレスと対象者メアドを指定することで、対象者にセットされてる失効日確認することが可能です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
//対象ユーザのexpireする日時を取得 function viewUserExpiration(){ //対象のグループアドレス let groupaddr = "ここにグループアドレスを指定する" //対象のユーザ let email_user = "ここに対象ユーザのメアドを指定する" //グループ名を取得する let groupman = getGroupName(groupaddr) //グループリソース const resource = 'https://cloudidentity.googleapis.com/v1beta1/'+groupman+'/memberships'; const param = { method : "get", headers : { "Authorization": "Bearer " + ScriptApp.getOAuthToken() }, }; //グループメンバーシップを取得 let pageToken ; let membership; do{ let page = JSON.parse(UrlFetchApp.fetch(resource,param).getContentText()); let tempret = page.memberships; if(tempret && tempret.length > 0){ for(let i = 0; i< tempret.length;i++){ let user = tempret[i]; //ユーザのメアドと一致するものを取得 if(user.preferredMemberKey.id == email_user){ membership = user.name; break; } } } pageToken = page.nextPageToken }while(pageToken) //対象ユーザの情報をリクエスト const expireurl = 'https://cloudidentity.googleapis.com/v1beta1/'+membership ; const param2 = { method : "GET", contentType : "application/json", headers : { "Authorization": "Bearer " + ScriptApp.getOAuthToken() }, muteHttpExceptions:true, }; //expireする日時を取得 const ret = UrlFetchApp.fetch(expireurl,param2); //レスポンスを取得 let result = ret.getContentText(); //レスポンスコードを取得 let rescode = ret.getResponseCode(); //ステータスコードで分岐 if(rescode == 200){ const user = JSON.parse(result); console.log('有効期限: '+ user.roles[0].expiryDetail.expireTime); }else{ console.log('エラー: ' + rescode); console.log('詳細: ' + result.split('title')[1]); } } |
グループの削除
作成済みのグループアドレスの削除は非常に簡単です。AdminDirectory.Groups.removeに対してメアドを渡して実行するだけです。
1 2 3 4 5 6 |
//グループアドレスの削除実行 try{ let ret = AdminDirectory.Groups.remove(mail); }catch(e){ console.log(e.message); } |
関連リンク
- Google Groupsのメンバー一覧を取得するGAS
- グループの詳細を更新する
- Admin SDK グループ設定サービス
- GASでAdmin SDKを利用する(Directory編)その2
- 【G Suite】APIからグループのアクセスタイプを含む詳細情報を取得する
- AdminDirectory Delete Google Group Aliases
- Cloud IdentityでGoogleグループからメンバーを追加・削除するGoogle Apps Scriptを書いた
- 動的グループを使用してメンバーを自動的に管理する
- 動的グループの作成と更新
- Use the Google Cloud Identity API for Google Groups
- Create membership expiration in Google Groups for Google Workspace
- グループ メンバーの有効期限の設定が可能に(ベータ版)
- Cloud Identity Groups API(ベータ版)を使用してプログラムでグループを管理する
- Method: groups.memberships.modifyMembershipRoles
- Time limited, auto-expiring group memberships for users on Google Cloud
- St3ph-fr/my-apps-script-utils
- 自作PythonラッパーでGoogleグループのメンバーシップをより便利に管理する