Datadogで使用量情報をAdmin権限以外でも見れるようにする

Datadogを使用していた際にメンバーの「どれくらい使用しているかわからないんだよね〜」というつぶやきを見かけました。使用量がわからないと思わぬ課金が発生していてもすぐ気づけ無い等の問題があるためDatadogのカスタムロールを用いてUsageの見れる権限を作成して対応しました。

本記事ではDatadogno使用量(Plan & Usage)を見れるロールを作ることを題材にDatadogのカスタムロールの作成方法を紹介します。また自分の利用方法では複数のDatadog Organizationがあり、いちいち手作業でカスタムロールを作成するのは大変だったのでPythonでカスタムロールの作成をスクリプト化し、自動化をしました。こちらのスクリプトについても紹介します。

今回使用する「カスタムロール」機能はEnterprise版の機能になりますのでご注意ください。

カスタムロールの作成と変更は、オプトイン Enterprise 機能です。ご使用のアカウントでこの機能を有効にしたい場合は、Datadog のサポートチームにお問い合わせください。*1

Datadogの権限について

Datadogの権限については以下のページにまとまっています。デフォルトで存在する権限は「Datadog 管理者ロール」「Datadog 標準ロール」「Datadog 読み取り専用ロール」の3つです。これらの権限をメンバーに付与することで権限管理をできますが、より柔軟に権限を振りたい場合には「カスタムロール」を用いて権限を作る必要があります。

docs.datadoghq.com

「管理者」しかPlan & Usageページに表示される「使用状況レポート」にアクセスできず、メンバーがDatadogの使用量を意識しにくいという課題がありました。

docs.datadoghq.com

ここでカスタムロールを作成してメンバー誰でもPlan & Usageページを見れるようにしてハッピーになろうぜ、というのが今回の記事になります。

カスタムロール

datadogの提供するアクセス許可を組み合わせてオリジナルのアクセス権限を作成することができます。アクセス許可の種類については以下のページにまとまっています。

docs.datadoghq.com

カスタムロールの作り方

カスタムロールの作成は以下のページを参考に作成しました。

docs.datadoghq.com

カスタムロールの有効化

カスタムロールはEnterprise版のオプトイン機能になります。 事前にカスタムロールの機能を有効化するために問い合わせページやサポートの方にカスタムロールを有効化したい旨を伝え有効化してもらいましょう。

手動のロールの作成

  1. Datadog Roles ページに移動
  2. ページ右上隅 New Role を選択
  3. ロールに名前をつける
    • 今回は「BillingReadRole」という名前にしました
  4. 権限の編集
    • 名前の下に付与される権限一覧が表示されます
      • デフォルトでReadに関する権限がいくつか付与される
    • 追加でBillingとUsageを見るための権限にチェック
      • Billing Read
      • Usage Read
  5. 保存

これで無事にカスタムロールが作成できました🙌

ロール作成の自動化 with Python

何個かDatadogのOrganizationを持っていると同一のロールをすべてのOrganizationで作りたいなどの要件が出てきます。 そんなときには何かしらの自動化手段を考えたいものです。

DatadogのRoleを管理する際には「terraformを用いて管理する案」や「API経由で作成する案」があります。今回はPythonAPI経由で作成に挑戦しましたのでそちらを共有します。

1. 操作するアカウントのAPIキーを取得する

PythonからDatadogを操作するには API Key と Application Key が必要になります。

以下の手順でそれぞれ取得し、どこかにメモします。これらの情報が流出してしまうと自由にDatadogを操作できてしまうため管理には気をつけてください。

  1. Organization Setting を開く
  2. ACCESS -> API Keys からキーを作成し保存
  3. ACCESS -> Application Keys からキーを作成し保存
2. Python実行用の環境作成

Pythonで操作するにあたり、Datadog社の公開している datadog-api-client-python を利用していきます。

  1. ライブラリのインストール
    pip install datadog-api-client
  2. アクセス情報を環境変数にセット
    • デフォルトでこのライブラリは DD_API_KEYDD_APP_KEY に書かれたAPI Key とApplication Keyを用いてDatadogにアクセスします
      1. で保存したキーを環境変数に保存しましょう
    • また時折 DD_SITE なる環境変数を求められることがありました。こちらもセットしておきましょう
export DD_API_KEY=<取得したAPIキー>export DD_APP_KEY=<取得したAPPキー>export DD_SITE=datadoghq.com
3. 付与する権限のIDを調べる

APIリファレンス > ロール: List roles のサンプルコードを用いて手動で作成した BillingReadRoleにはどのような権限がついているか確認していきます。Python実行用の環境作成でセットした認証情報をもとにDatadogにログインされます。list_role を実行することで ROLE_DATA_ATTRIBUTES_NAME のロール名についているPermissionを見ることができます。

サンプルがそのままだと動かなかったので少しだけ修正しています。

# from os import environ
from datadog_api_client.v2 import ApiClient, Configuration
from datadog_api_client.v2.api.roles_api import RolesApi

# there is a valid "role" in the system
ROLE_DATA_ATTRIBUTES_NAME = "<BillingReadRole 作成したロール名>"

configuration = Configuration()
with ApiClient(configuration) as api_client:
    api_instance = RolesApi(api_client)
    response = api_instance.list_roles(
        filter=ROLE_DATA_ATTRIBUTES_NAME,
    )

    print(response)
❯ python3 ./list_roles.py
{'data': [
  {'attributes':
    {
      'created_at': datetime.datetime(2022, 2, 18, 11, 51, 54, 42646, tzinfo=tzutc()),
      'modified_at': datetime.datetime(2022, 2, 18, 11, 51, 54, 89124, tzinfo=tzutc()),
      'name': 'BillingReadRole',
      'user_count': 1
    },
    'id': '01234567-hoge...',
    'relationships': {
      'permissions': {
        'data': [
          {'id': 'd90f6830-d3d8-11e9-a77a-b3404e5e9ee2', 'type': 'permissions'},
          {'id': '46a301df-ec5c-11ea-aa9f-970a9ae645e5', 'type': 'permissions'},
          ....

data として id が出ていますがこのままではなんのPermissionなのかわかりません... 別途Permissionの内容を見るAPIリファレンス > ロール: List Permissionを実行してみましょう。

from datadog_api_client.v2 import ApiClient, Configuration
from datadog_api_client.v2.api.roles_api import RolesApi

configuration = Configuration()
with ApiClient(configuration) as api_client:
    api_instance = RolesApi(api_client)
    response = api_instance.list_permissions()

    print(response)
❯ python3 ./list_permission.py 
{'data': [
    {
        'attributes': {
            'created': datetime.datetime(2018, 10, 19, 15, 35, 23, 734317, tzinfo=tzutc()),
            'description': 'Deprecated. Privileged Access (also '
                'known as Admin permission) has been '
                'replaced by more specific '
                'permissions: Access Management, Org '
                'Management, Billing Read/Write, '
                'Usage Read/Write.',
            'display_name': 'Privileged Access',
            'display_type': 'other',
            'group_name': 'General',
            'name': 'admin',
            'restricted': False
        },
        'id': '984a2bd4-d3b4-11e8-a1ff-a7f660d43029',
        'type': 'permissions'
    },
    {
        'attributes': {
            'created': datetime.datetime(2018, 10, 19, 15, 35, 23, 756736, tzinfo=tzutc()),
            'description': 'View and edit components in your '
                'Datadog organization that do not '
                'have explicitly defined permissions. '
                'This includes configuring events, '
                'facets (except logs), and saved '
                'views.',
            'display_name': 'Standard Access',
            'display_type': 'other',
            'group_name': 'General',
            'name': 'standard',
            'restricted': False
            },
        'id': '984d2f00-d3b4-11e8-a200-bb47109e9987',
        'type': 'permissions'
    },
    .... 省略
}

どうやら id と紐づく attributes が存在し、権限の名前や説明を設定しているようです。BillingReadRole についていた 46a301df-ec5c-11ea-aa9f-970a9ae645e5 のidを出力されたjsonから検索すると以下が見つかりました。

description: View your organization's subscription and payment method but not make edits.
display_name: Billing Read

カスタムロールを作成し、付与したい権限のIDを与えることで目的の権限を作成することができそうです。idについては github 上で調べたところ同じ値が数多く見つかり、Organization毎に異なるものでは無いようでした。

4. ロールの作成と権限の付与

APIリファレンス > ロール: Create role を用いてカスタムロールを作成していきます。リンク先のサンプルコードでは権限の何もついていないロールを作成していますが、やってみたところ権限付与もCreateRoleと同時に実行可能でした。

以下のサンプルでは「Billing Read」「Usage Read」の権限を付けた権限を「billing-read-role」の名前でカスタムロールを作成しています。実行後には作成したカスタムロールのidを表示しています。

from datadog_api_client.v2 import ApiClient, Configuration
from datadog_api_client.v2.api.roles_api import RolesApi
from datadog_api_client.v2.model.permissions_type import PermissionsType
from datadog_api_client.v2.model.relationship_to_permission_data import \
  RelationshipToPermissionData
from datadog_api_client.v2.model.relationship_to_permissions import \
  RelationshipToPermissions
from datadog_api_client.v2.model.role_create_attributes import \
  RoleCreateAttributes
from datadog_api_client.v2.model.role_create_data import RoleCreateData
from datadog_api_client.v2.model.role_create_request import RoleCreateRequest
from datadog_api_client.v2.model.role_relationships import RoleRelationships
from datadog_api_client.v2.model.roles_type import RolesType

createRoleBody = RoleCreateRequest(
  data=RoleCreateData(
    type=RolesType("roles"),
    attributes=RoleCreateAttributes(
      name="billing-read-role"
    ),
    relationships=RoleRelationships(
      users=None,
      permissions=RelationshipToPermissions(
        data=[
          RelationshipToPermissionData(
            # Billing Read
            id="46a301df-ec5c-11ea-aa9f-970a9ae645e5",
            type=PermissionsType("permissions")
          ),
          RelationshipToPermissionData(
            # Usage Read
            id="46a301e1-ec5c-11ea-aa9f-afa39f6f3e36",
            type=PermissionsType("permissions")
          ),
        ]
      )
    ),
  )
)

def main():
  configuration = Configuration()
  with ApiClient(configuration) as api_client:
    api_instance = RolesApi(api_client)
    try:
      response = api_instance.create_role(body=createRoleBody)
    except Exception as e:
      print(e)
      return
    print(response["data"]["id"])

if __name__ == '__main__':
  main()

実行することでRelationshipToPermissionDataとして記載した権限のついたカスタムロールを作成することができます。API KeyとAPP Keyを入れ替えることで各アカウントに同一のロールを作成することができます。

まとめ

作成したカスタムロールをユーザに付与することで適切に権限を管理することができます。 今回はPlan & Usage を管理者以外が見れないことを不便に感じてカスタムロールを作成しました。 この記事を読んだ方でこんな感じでカスタムロール使用しているよ〜、こんな感じでロールの管理しているよ〜などあればコメントでご紹介いただきたいです。

ここまで読んでくださりありがとうございました!