Amazon Connectのユーザ管理ログをAthenaで取得してみた- Amazon Connect アドベントカレンダー 2022

Amaozn Connectユーザの操作ログをノーコードでいい感じに出力してみました
2022.12.03

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、中川です。

Amazon Connect アドベントカレンダー 2022、3日目の記事です!
Amazon Connect アドベントカレンダー 2022はクラスメソッドとギークフィードさんの有志が募ってチャレンジしている企画になります。

今年の4月にAmazon Connectユーザーの作成やセキュリティプロファイルを更新したときの操作が、CloudTrailに出力されるようになるアップデートがありました。

アップデート以前はAmazon Connectインスタンスにログインすることでしか操作履歴を確認できず、出力する機能もなかったため、操作履歴を監査ログとして扱いたい場合に悩ましかったです。 本記事では監査ログとしてAmazon Connectユーザの操作履歴が求められるケースを想定して、Athenaでログを取得をしてみます。

やってみた

前提

ログの対象とするユーザ操作関連のAPIは以下とします。

  • CreateUser
  • DeleteUser
  • UpdateUserIdentityInfo
  • UpdateUserSecurityProfiles
  • UpdateUserRoutingProfile
  • UpdateUserPhoneConfig
  • UpdateUserHierarchyStructure
  • UpdateUserHierarchyGroupName
  • UpdateUserHierarchy

また、事前にAthenaでは下記ドキュメントを参考にCloudTrailのテーブルを作成していることとします。

Creating the table for CloudTrail logs in Athena using partition projection

そのままログを取得してみる

まずはログのフォーマットをCloudTrail上から確認します。

以下はCreateUserの抜粋です。実行ユーザの情報は userIdentity.principalId から取得できそうです。

CreateUserでどのユーザが作成されたかについては requestParameters.Username から取得できそうです。

次に、DeleteUserやUpdateUserSecurityProfilesのログを確認してみます。
変更対象のユーザについては requestParameters.Username から取得できそうです。

DeleteUser.

UpdateUserSecurityProfiles.

出力したい情報を確認できたので、クエリを投げてみます。

SELECT
        eventtime,
        userIdentity.principalId AS executionUser,
        eventname,
        json_extract_scalar(requestParameters, '$.Username') AS createdUser,
        json_extract_scalar(requestParameters, '$.UserId') AS operatedUser,
        eventid
FROM
        "AwsDataCatalog"."connect"."cloudtrail"
WHERE
    eventname in (
        'CreateUser',
        'DeleteUser',
        'UpdateUserIdentityInfo',
        'UpdateUserSecurityProfiles',
        'UpdateUserRoutingProfile',
        'UpdateUserPhoneConfig',
        'UpdateUserHierarchyStructure',
        'UpdateUserHierarchyGroupName',
        'UpdateUserHierarchy'
    )
AND region = 'ap-northeast-1'
AND date > '2022/11/01'
AND date <= '2022/12/02'
AND useragent = 'connect.amazonaws.com'

クエリ結果.

ログとしてほしい情報は取れておりますが、以下の点が気になります。

  • 操作されたユーザ(operatedUser)がわかりにくい
    • 作成されたユーザ(createdUser)のようにメールアドレスで取得できない
  • 実行したユーザ(executionUser)がわかりにくい
    • 文字列が長い
    • 文字数制限によりメールアドレス部分が途中で切れており、正確に出力できてない

クエリを追加して、実行ユーザと操作されたユーザがメールアドレスで表示できることをゴールにしたいと思います。

ユーザ情報をS3にアップロードする

operatedUserやexecutionUserのメールアドレス前の文字列は、Amazon Connectインスタンスで内部的に使用されるUserIdです。 ListUsers APIを実行することで、Connectインスタンスのユーザ名(メールアドレス)とUserIdDを取得できます。

$ aws connect list-users --instance-id 498ac4af-220c-4a9c-8436-b9c85bXXXXXX
{
    "UserSummaryList": [
        {
            "Id": "1c71831d-8980-43e9-a7c8-4f1aeae10609",
            "Arn": "arn:aws:connect:ap-northeast-1:1234XXXXXXXX:instance/498ac4af-220c-4a9c-8436-b9c85bXXXXXX/agent/1c71831d-8980-43e9-a7c8-4f1aeae10609",
            "Username": "admin1@classmethod.jp"
        },
        {
            "Id": "51f98508-d413-4434-b890-513e15aa196e",
            "Arn": "arn:aws:connect:ap-northeast-1:1234XXXXXXXX:instance/498ac4af-220c-4a9c-8436-b9c85bXXXXXX/agent/51f98508-d413-4434-b890-513e15aa196e",
            "Username": "test.taro@classmethod.jp"
        },
        {
            "Id": "fb9bd02f-5ea3-4dff-b8d8-61475afe7af6",
            "Arn": "arn:aws:connect:ap-northeast-1:1234XXXXXXXX:instance/498ac4af-220c-4a9c-8436-b9c85bXXXXXX/agent/fb9bd02f-5ea3-4dff-b8d8-61475afe7af6",
            "Username": "admin2@classmethod.jp"
        }
    ]
}

これをAthenaで結合できるようにしたいため、ListUsersの結果をS3にアップロードする処理をStepFunctionsで作ります。
作成したステートマシンは以下になります。ListUsersを実行し、UserSummaryListのユーザ配列ごとにjsonファイルを分割してS3にPutしています。分割して保存することによって、Connectユーザが削除されたあとにステートマシンを繰り返し実行しても、ユーザ情報をS3に残すことができます。

{
  "Comment": "A description of my state machine",
  "StartAt": "ListUsers",
  "States": {
    "ListUsers": {
      "Type": "Task",
      "Parameters": {
        "InstanceId": "498ac4af-220c-4a9c-8436-b9c85bXXXXXX"
      },
      "Resource": "arn:aws:states:::aws-sdk:connect:listUsers",
      "Next": "Map",
      "ResultPath": "$"
    },
    "Map": {
      "Type": "Map",
      "InputPath": "$.UserSummaryList",
      "ItemProcessor": {
        "ProcessorConfig": {
          "Mode": "INLINE"
        },
        "StartAt": "PutObject",
        "States": {
          "PutObject": {
            "Type": "Task",
            "End": true,
            "InputPath": "$",
            "Parameters": {
              "Body.$": "$",
              "Bucket": "connect-user-1234XXXXXXXX",
              "Key.$": "$.Id"
            },
            "Resource": "arn:aws:states:::aws-sdk:s3:putObject"
          }
        }
      },
      "End": true
    }
  }
}

Athenaでクエリを投げ、ユーザー情報を取得できるか確認します。
テーブルを作成し、SELECTを実行すると以下のようにユーザ情報を取得できました。

CREATE EXTERNAL TABLE IF NOT EXISTS connect_users (
    Arn string,
    Id string,
    Username string
) ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
LOCATION 's3://connect-user-1234XXXXXXXX/'

出力結果.

ユーザ管理ログを取得する

準備ができましたので、テーブルを結合してユーザ管理ログを取得してみます。

WITH
    user_data AS (
        SELECT *
        FROM
        "AwsDataCatalog"."connect"."connect_users"
    ),
    log_data AS (
        SELECT
            eventtime,
            substring(userIdentity.principalId, 23, 36) AS executeuserid,
            eventname,
            json_extract_scalar(requestParameters, '$.Username') AS createdUser,
            json_extract_scalar(requestParameters, '$.UserId') AS operatedUser,
            eventId
        FROM
            "AwsDataCatalog"."connect"."cloudtrail"
        WHERE
            eventname in ('CreateUser',
                    'DeleteUser',
                    'UpdateUserIdentityInfo',
                    'UpdateUserSecurityProfiles',
                    'UpdateUserRoutingProfile',
                    'UpdateUserPhoneConfig',
                    'UpdateUserHierarchyStructure',
                    'UpdateUserHierarchyGroupName',
                    'UpdateUserHierarchy')
        AND region = 'ap-northeast-1'
        AND date > '2022/11/01'
        AND date <= '2022/12/02'
        AND useragent = 'connect.amazonaws.com'
    )
    SELECT
        log_data.eventtime AS EventTime,
        J1.username AS ExecuteUser,
        log_data.eventname AS EventName,
        log_data.username AS CreatedUser,
        J2.username AS OperatedUser,
        log_data.eventId AS EventId
    FROM
        log_data
    LEFT JOIN user_data AS J1 ON log_data.executeuserid = J1.id
    LEFT JOIN user_data AS J2 ON log_data.objectid = J2.id

出力結果.

実行ユーザ、操作されたユーザをメールアドレスで表示できることを確認できました!

さいごに

Amazon Connect のユーザ管理のログをAthenaで出力してみました。
そのまま出力した場合はConnect内部ユーザIDで出力されるため、ユーザ情報の付け合せが必要となり使い勝手がよろしくありませんでした。 ユーザ情報の一覧を取得するAPIを組み合わせることによって、ログとして扱いやすくなります。 今回はStepFunctionsを1回だけ実行しましたが、実際の環境で使う場合はスケジューリングやAthenaの実行と合わせて行うなどご検討ください。