SlackからOkta APIを実行してみた
SlackからAPIを実行したいなと思っていて、実際に試してみたので、そのメモです。SlackからAPIを実行できるようにすると、以下のメリットが見込めます。
・オペレーションの簡略化(管理画面からポチポチ操作するのって意外と時間かかる)
・オペミスのリスク軽減(管理画面には色々なボタンがあるので、押し間違えるリスクがある)
・作業移管時に委譲する権限の最小化(管理者アカウントを渡すと、余計な権限が付随しがち)
・マニュアル作成の工数削減(管理画面のスクリーンショットをペタペタとマニュアルへ貼るより、コマンドベースのほうがテキストで済むので楽)
サンプルとして、SlackからOkta APIを実行する具体的な方法を紹介します。
Contents
完成形
SlackからOkta APIで、Oktaユーザーをsuspendしてみた。作成したSlash Commandは以下2つ。
— だい@中小企業のIT促進を手伝います (@Waterclover_com) February 26, 2023
/get-okta-status(statusを取得)
/suspend-okta-user(suspendする)
動画はokta-testuser01というOktaユーザーが、最初はPASSWORD_EXPIREDステータスで、最後にSUSPENDEDに変わってる様子。 pic.twitter.com/tUgwuvRrPH
流れ
(1) Slackアプリを作成して、Signing Secretを取得
(2) Google Cloud(GCP)でCloud Functionsを作成
(3) SlackアプリのSlash CommandにCloud Functionsを設定
(4) Slackアプリを追加
※注意※
最小限のテストしかしていないため、これをこのまま業務に利用して、何かトラブルになったとしても責任は負いかねます。あくまでサンプルとしてご認識ください。
詳細な手順
Slackアプリを作成して、Signing Secretを取得
Slack API からSlackアプリを作成
左メニュー[Basic Information]の中から、Signing Secretを取得。
Google Cloud(GCP)でCloud Functionsを作成
Cloud Functionsは第2世代がリリースされているが、うまく動作しなかったので第1世代で。
認証は「未認証の呼び出しを許可」にチェック。SlackからAPIを実行するにあたって、Cloud IAMが利用できないので。ただし、どこからでも呼び出されてしまうので、必ずコード内でSlackのSigning Secretで認証をかけて、API実行部分は実行できないようにする。
そうすることで、Cloud Functions自体はどこからでも呼び出せるものの、本体であるAPI実行部分は許可したSlackアプリからしか呼び出せないようにできる。
ソースコード
import requests
import hmac
import hashlib
# Okta Domain(***.okta.com の形式で入力)
OKTA_DOMAIN = "dev-***.okta.com"
# OktaのAPIキー
OKTA_API_KEY = "ここに入れる"
# Slack AppのSigning Secret
SLACK_SIGNING_SECRET = "ここに入れる"
def get_user_status(user_id):
url = f"https://{OKTA_DOMAIN}/api/v1/users/{user_id}"
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
"Authorization": f"SSWS {OKTA_API_KEY}"
}
response = requests.get(url, headers=headers)
if response.status_code == 200:
user_data = response.json()
user_status = user_data.get("status")
return user_status
else:
print(f"Error retrieving user {user_id}: {response.text}")
return None
def okta_user_status(request):
# Slackからのリクエスト検証
request_body = request.get_data(as_text=True)
timestamp = request.headers.get('X-Slack-Request-Timestamp')
sig_basestring = f"v0:{timestamp}:{request_body}".encode("utf-8")
my_signature = 'v0=' + hmac.new(SLACK_SIGNING_SECRET.encode("utf-8"), sig_basestring, hashlib.sha256).hexdigest()
slack_signature = request.headers.get('X-Slack-Signature')
if not hmac.compare_digest(my_signature, slack_signature):
return {"statusCode": 401}
user_id = request.form.get('text')
user_status = get_user_status(user_id)
if user_status is not None:
response_text = f"User {user_id} status: {user_status}"
else:
response_text = f"Error retrieving user {user_id}"
return response_text
SlackアプリのSlash CommandにCloud Functionsを設定
作成したSlackアプリの Features > Slash Commands から設定します。
Slackアプリを追加
あとはSlackから、作成したSlackアプリを追加すればOK。
こういうの、メモしておかないと忘れるので、自分のために残しました。
誰かに参考にもなったら嬉しいです。