Python On LambdaでIAM管理Tips - User List取得


AWSのマネジメントコンソールでIAMユーザ管理する場合、一覧してみることができますが、
ユーザ名以外でソートができないようです。
そうすると、払い出して一度も使っていないユーザや、最近ログインしていないユーザを把握するのが面倒くさくなります。
そこでIAMユーザリストを取得するREST APIを作って、別のツールと組み合わせて管理できるようにと考えてみました。

OverView


こんな感じなことを実現したい

Lambda

Lambdaの管理画面でCreate Fuction

今回はpython3.6を使いたいので、テンプレートを一番シンプルなhello-world-python3とします。


トリガーにAPI Gatewayを選択
API Nameは任意で、Deployment stageもデフォルト値のprodで問題ありません。
Securityだけ必要に応じて、

  • AWS IAM
  • Open
  • Open with access key

から選ぶ必要があります。
外から読み取りたいのと、IAM情報なので、最低限の認証を行いたいため、
Open with access keyを選びました。
「Next」でLambda作成画面に遷移、Name、Description等は任意で、
重要なのはRoleの設定

IAMの情報取得したいので、AWSLambdaFullAccessポリシーを付与したRoleでは、IAMへのアクセス権はないです。

RoleにIAMのList*をすべて許可するポリシーを追加
最後に、「Next」で設定した情報を確認して完了とします。

Python

ここから肝心なPythonを書いてIAM情報を取得し、jsonで返したいです。

# -*- coding: utf-8 -*-

import json
import boto3

client = boto3.client('iam')

# def function_handler
def lambda_handler(event, context):
  response = client.list_users()
  jsonObj = [""] * len(response["Users"])
  i = 0
  for user in response["Users"]:
    jsonObj[i] = {}
    jsonObj[i]["UserName"] = getValueFromUser(user, "UserName")
    jsonObj[i]["UserId"] = getValueFromUser(user, "UserId")
    jsonObj[i]["Arn"] = getValueFromUser(user, "Arn")
    jsonObj[i]["CreateDate"] = getValueFromUser(user, "CreateDate")
    jsonObj[i]["PasswordLastUsed"] = getValueFromUser(user, "PasswordLastUsed")
    i = i + 1  

  return {'statusCode': 200,
          'body': json.dumps(jsonObj),
          'headers': {'Content-Type': 'application/json'}}

# def function get value from user object
def getValueFromUser(user, key):
  try:
      return str(user[key])
  except (KeyError):
      return "None"

Python自体初心者なので、きれいなコードが書けないです。
はまったポイントだけメモっておきますと、
getValueFromUserをもともと作る想定はなく、

jsonObj[i]["PasswordLastUsed"] = user["PasswordLastUsed"]

のような感じで記述していました。
実行すると、KeyErrorが発生する場合があります。
試行錯誤した結果、IAMユーザ払い出して、一度もログインしたことがない人がいるため、
その人のuser["PasswordLastUsed"]が取れないようです。

{
  "errorMessage": "'PasswordLastUsed'",
  "errorType": "KeyError",
  "stackTrace": [
    [
      "/var/task/lambda_function.py",
      21,
      "lambda_handler",
      "jsonObj[i][\"PasswordLastUsed\"] = user[\"PasswordLastUsed\"]"
    ]
  ]
}

KeyErrorじゃなくて、Noneで返してくれればいいのに。。。
仕方なく、例外処理をとりあえずやってうまく実行ができました。
Python力が上がればもっといい方法はきっとあるはず
成功すると結果が帰ってきます。Detailsを開けばjsonの中身やlogも表示されます。

API Gateway Deploy

次はAPI Gatewayの設定

Triggerで作成されたAPIを開きますと、Resourceとして、下記のようなフローがすでに作成されています。

TESTアイコンをクリックして、Methodを選択しAPIテストをコンソール上で実行可能

ただし、これだけでは外部から呼べないです。
APIを作ったら、Stageにデプロイして初めてEndPointと紐付けて、外部からアクセスできるようになります。
Actoinsボタンをクリックして、メニューを展開、Deploy API を選択すると、
Deploy APIポップアップが表示されます。

Deployment stageを選択し、Deployボタンクリック
※このDeployment stageはLambda関数作成するとに設定はものです。

メニューからStagesを選択し、prod配下に作られたAPIがデプロイされる状態になります。

ここでGETメソッドを選択すると、右にInvoke URL が表示されます。
クリックすると、jsonデータが表示されます。

ただし、認証をOpen with access keyとしたため、このままではアクセスできません。
ブラウザに下記が表示されます。

{"message":"Forbidden"}

API Keys & Usage Plans

Access Keyを紐づけさせるには、まずAPI Keys画面に遷移し、ActionsボタンでCreate API Key

作っただけでは意味がなく、APIと紐づける必要があります。
そのためにUsage Planを作成

APIをUsage Planに追加し、

次に、API KeyをUsage Planに追加します。

QlikSenseから取得

はやりのBIツールからREST API呼び出して表示してみましょう。
今回はQlikSense Desktopを使ってみます。
起動して、Hubから新規アプリを作成

データを追加をクリックし、データソースの選択にRESTをクリック

URLにInvoke URLを入れます。

Query headerにx-api-keyをキーに、API Keyを値として入れます。

次へ進みますと、接続しました。

その後データをロード出来たら、チャート等自由に作成ができます。