IdentityStoreのdescribe_user()がLambdaで正常実行できない問題を解決する

## 課題

2022年12月8日現在、[boto3のIdentityStore](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/identitystore.html)（AWS IAM Identity Centerのうち、ユーザーアイデンティティー情報を取り扱うAPI）で`describe_user()`を実行しようとすると、期待した戻り値が返らない。具体的には、UserNameとUserIdしか返ってこない。

Azure ADからIdentity CenterにSCIMで連携されたユーザー属性情報を元にQuickSightのAPIを呼びたかったのだが、この状態では何の処理もできない。

## 原因

[GitHub](https://github.com/boto/boto3/issues/3436)で報告され、boto3側では既にFixされているのだが（boto3-1.24.64）、[Lambda側のランタイム](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/lambda-runtimes.html)が古い（boto3-1.20.32）のが原因。

## 解決方法

Lambdaレイヤーを使って最新バージョンのboto3に置き換えることで解決する。

### 0.サンプルコード

サンプルコードは以下。

```python:DescribeUsertest-20221107
import boto3

def lambda_handler(event, context):
  '''
  To test describe_test() API which had a bag
  https://github.com/boto/boto3/issues/3436 
  '''
  print('### BOTO3:',boto3.__version__)

  # Obtain account ID and region
  account_id = boto3.client('sts').get_caller_identity()['Account']
  region = boto3.session.Session().region_name

  # Setup clients
  iic = boto3.client('identitystore')

  iic_store_id = "d-xxxx723xxx"
  iic_user_id = "0784ca78-xxxx-708b-9d18-6d0102dfxxxx"
  iic = boto3.client('identitystore')
  iic_user_info = iic.describe_user(
    IdentityStoreId = iic_store_id,
    UserId = iic_user_id
  )
  print('### TYPE:', type(iic_user_info))
  print('### PAYLOAD:', iic_user_info)

```

### 1. Lambdaレイヤーがない状態

![before.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609876/36fb7aca-1812-f12c-3ef2-09283c192554.png)

この状態でサンプルコードを実行すると、以下のようになる。

```bash
START RequestId: 9d052994-24b9-4e54-b57f-228ab75723cd Version: $LATEST
### BOTO3: 1.20.32
### TYPE: <class 'dict'>
### PAYLOAD: {'UserName': 'motonari@xxxxxxxx.onmicrosoft.com', 'UserId': '0784ca78-xxxx-708b-9d18-6d0102dfxxxx', 'ResponseMetadata': {'RequestId': '6afa4d53-a01f-47d6-9a95-435e752f2405', 'HTTPStatusCode': 200, 'HTTPHeaders': {'date': 'Thu, 08 Dec 2022 03:49:44 GMT', 'content-type': 'application/x-amz-json-1.1', 'content-length': '584', 'connection': 'keep-alive', 'x-amzn-requestid': '6afa4d53-a01f-47d6-9a95-435e752f2405'}, 'RetryAttempts': 0}}
END RequestId: 9d052994-24b9-4e54-b57f-228ab75723cd
REPORT RequestId: 9d052994-24b9-4e54-b57f-228ab75723cd	Duration: 2046.43 ms	Billed Duration: 2047 ms	Memory Size: 128 MB	Max Memory Used: 64 MB	Init Duration: 265.78 ms
```
UserNameとUserIdしか返ってきていない。

### 2. boto3レイヤーの追加

[こちら](https://aws.amazon.com/jp/premiumsupport/knowledge-center/lambda-python-runtime-errors/)の手順に従って、boto3のLambdaレイヤーを追加する。なお、執筆時点でのboto3バージョンはboto3-1.26.24。自分はmacOSでzipを作成してレイヤーを作成した。

関数が以下のような状態になっていればOK。
![after.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609876/60e369f1-081c-d343-11cb-0e8cb887af3f.png)

#### 3. 再度実行

この状態で再びサンプルコードを実行する。

```bash
START RequestId: 97d7de84-bf4b-41e3-9e5b-f10be588e35b Version: $LATEST
### BOTO3: 1.26.24
### TYPE: <class 'dict'>
### PAYLOAD: {'UserName': 'motonari@xxxxxxxx.onmicrosoft.com', 'UserId': '0784ca78-xxxx-708b-9d18-6d0102dfxxxx', 'ExternalIds': [{'Issuer': 'https://scim.aws.com/tEOd8ddb41f-4a20-46df-b043-7fcab8b06370', 'Id': 'c4aa9a84-6bf7-415f-99d8-c3c7c4ab1881'}], 'Name': {'Formatted': 'motonari mouri', 'FamilyName': 'mouri', 'GivenName': 'motonari'}, 'DisplayName': 'motonari', 'Emails': [{'Value': 'motonari@xxxxxxxx.onmicrosoft.com', 'Type': 'work', 'Primary': True}], 'Addresses': [{'Locality': 'Minato-ku', 'Region': 'Tokyo', 'Type': 'work'}], 'Title': 'Nagato-President', 'Timezone': 'Nagato', 'IdentityStoreId': 'd-9567723cfc', 'ResponseMetadata': {'RequestId': '5fbe9db7-a526-43bb-85fb-18c691f6dd53', 'HTTPStatusCode': 200, 'HTTPHeaders': {'date': 'Thu, 08 Dec 2022 03:59:38 GMT', 'content-type': 'application/x-amz-json-1.1', 'content-length': '584', 'connection': 'keep-alive', 'x-amzn-requestid': '5fbe9db7-a526-43bb-85fb-18c691f6dd53'}, 'RetryAttempts': 0}}
END RequestId: 97d7de84-bf4b-41e3-9e5b-f10be588e35b
REPORT RequestId: 97d7de84-bf4b-41e3-9e5b-f10be588e35b	Duration: 2401.74 ms	Billed Duration: 2402 ms	Memory Size: 128 MB	Max Memory Used: 66 MB	Init Duration: 538.50 ms
```

無事、全ての属性が返ってきた。

## ハマリポイント

Lambdaレイヤーにはサポートされているパスが定められており、今回の場合は`python`フォルダの配下にboto3をインストールし、`python`フォルダごとパッケージングする必要がある。ここを間違えると、レイヤー自体を正しく設定してもboto3はLambdaランタイムのものが読まれてしまうので要注意。

なお余談だが、[`describe_user()`](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/identitystore.html#IdentityStore.Client.describe_user)は現時点ではIdentity Centerの全ユーザー属性を取ってくることができない（今回のケースでは、Departmentを取ってきたかったが非対応だった）。このため、Azure ADのSSOマッピング設定で、`describe_user()`がサポートしている属性にマッピングを変更する必要がある。
ここでは、TitleとDepartmentを結合してTitleにマッピングする方法を採り、目的の情報を得ている。