2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Azure Functions を使って、LINE WORKS のオウム返し Bot を作ってみる (その2:AzureFunctions準備編)

Last updated at Posted at 2022-06-29

前回は、LINE WORKS の Developer Console で、オウム返し Bot の作成準備を行いました。
今回は、いよいよ Azure Functions で、Bot 本体を準備していきます。

まずは、Azure Portal へアクセスし、リソースの作成 から関数アプリを作成します。
image.png
image.png
image.png
ランタイム スタックには PowerShell Coreを選択します。
image.png

今回は、お手軽に試せるということで、プランの種類として 消費量(サーバーレス) を選択しました。このプランでは、アクセスがが来てから環境を起動し、しばらくアクセスが無いと環境を終了します。
このため、メッセージを受けてからボットがオウム返しするまで、若干 (30秒程度?) 時間がかかることがあります。
LINE WORKS の処理が遅いのではなく、消費量(サーバーレス) プランを利用した Azure Functions の制約ですので、その旨ご理解ください m(_,_)m

[確認および作成] をクリックして先に進みましょう。デプロイの完了まで数分かかります。

作成された関数アプリに移動します。見つからない場合には、[すべてのサービス]-[すべてのリリース]から見つけます。
image.png

さて、これまでは、PowerShell での JWT の処理には powershell-jwt をインストールして利用してきました。Azure Function で PowerShell Module を使う場合には、モジュールをインストールするのではなく、Save-Module Cmdlet で実行環境に保存する必要があります。

まずは、[開発ツール]-[高度なツール]-[移動] から Kudu に移動します。
image.png

[Debug Console]-[PowerShell] で PowerShell コンソールを開きます。
image.png

コンソール領域に以下のコマンドを入力します

cd site\wwwroot
mkdir modules
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Install-PackageProvider nuget -Force -Scope CurrentUser
Save-Module powershell-jwt -Path .\modules 

image.png

さらに、LINE WORKS の Developers Console でダウンロードした PrivateKey ファイルの拡張子を txt に変更し、ページ上部ファイル・フォルダ領域にドラッグアンドドロップして、アップロードします。(拡張子が .key のフィルはアップロードができないようです。)
image.png

認証に必要な情報は、PowerShell 内にベタに書くこともできますが、せっかくなので、Azure Functions の環境変数を利用してみましょう。
[設定]-[構成]から[アプリケーション設定] タブを開き、[新しいアプリケーション設定]をクリックして LINE WORKS の Developers Console で取得した認証に必要な情報を保存していきます。最期に[保存]ボタンをクリックするのを忘れないでください。
image.png

名前 取得元
BOTID BotID (BotNo) 1234567
CLIENTID Client ID A0B1c3d4e5f6g7h8I9
CLIENTSECRET Client Secet AbCdEfGhIj
SERVICEACCOUNT Service Account abcde.serviceaccount@yourcompany
PRIVATEKEYFILE アップロードしたPrivateKeyFile名 private_20220101123456.txt
BOTSECRET Bot Secret lkjlekjlkjSLJKDLKDJLElkjl

ここまできたらあと一息。[関数]-[関数]-[作成] で関数を作成します。
image.png
開発環境は [ポータルでの開発] を選択し、テンプレートには [HTTP trigger] を選びます。
image.png

作成された [HttpTrigger1] へ移動し、[コードとテスト] をクリックするとエディタが開きますので、
image.png

次のコードでまるっと置き換えて保存します。

using namespace System.Net
param($Request, $TriggerMetadata)


$clientId       = $env:CLIENTID
$clientSecret   = $env:CLIENTSECRET
$privateKeyFile = $env:PRIVATEKEYFILE
$svcAccount		= $env:SERVICEACCOUNT
$botSecret		= $env:BOTSECRET
$Scope 			= "bot"
$body = $Request.RawBody
$receiveMsg = $body | convertfrom-json 

# GET Access Token 
$PrivKeyPath    = "D:\home\site\wwwroot\" + $privateKeyFile 

$rsaPrivateKey = Get-Content $PrivKeyPath -AsByteStream

$iat = [int](Get-Date -UFormat %s)
$exp = $iat + 3600

$payload = @{
    sub = $SvcAccount
    iat = $iat
}
    
$jwt = New-JWT -Algorithm 'RS256' -SecretKey $rsaPrivateKey -PayloadClaims $payload -ExpiryTimestamp $exp -Issuer $clientId
    
$requestHeader = @{
    'Content-Type' = 'application/x-www-form-urlencoded'
}

$requestBody = @{
    assertion     = $jwt
    grant_type    = 'urn:ietf:params:oauth:grant-type:jwt-bearer'
    client_id     = $clientId
    client_secret = $clientSecret
    scope         = $Scope
}

$url = 'https://auth.worksmobile.com/oauth2/v2.0/token'
$response = Invoke-RestMethod -Uri $url -Method POST -Headers $requestHeader -Body $requestBody

$sectoken = ConvertTo-SecureString $response.access_token -AsPlainText

# Signature check

$oHMACSHA256 = New-Object System.Security.Cryptography.HMACSHA256
$oHMACSHA256.key = [Text.Encoding]::ASCII.GetBytes($BotSecret)

$readBuf =  [System.Text.Encoding]::UTF8.GetBytes($body)

$signature_rawout = $oHMACSHA256.ComputeHash($readBuf)
$signatureB64 = [Convert]::ToBase64String($signature_rawout)

if ($signatureB64.ToString() -eq $Request.Headers["X-Works-Signature"]) {
  $msg = $receiveMsg.content.text
}
else {
  $msg =  "怪しい奴め!"
}

# オウム返しするぞ
$reqBody =@{
	content = @{
		type = 'text'
		text = $msg
	}
}

$reqBody = $reqBody | convertto-json
$reqBody = [System.Text.Encoding]::UTF8.GetBytes($reqBody ) # hack for MOJI-BAKE

$userId = $receiveMsg.source.userId
$botId = $Request.Headers["X-Works-BotId"]

$URL = "https://www.worksapis.com/v1.0/bots/$botId/users/$userId/messages"
Invoke-WebRequest -Method POST -Uri $URL  -body $reqBody -Authentication Bearer -Token $secToken -ContentType "application/json"

コードを見ても、1/3 が AccessToken 取得、1/3 が Signature のチェックで、実際に Bot メッセージを送っている部分は本当に簡単ですね。

右上の [関数URLの取得] で、Azure Functions で作成した関数を呼び出すための URL を取得しておきます。
image.png

最期にもう一度 LINE WORKS の Developer Console へ行き、Callback URL を有効にして先程保存した URL を貼り付けます。送信可能なメッセージタイプに テキスト を指定します。
image.png

オウム返し Bot の作成作業は以上です。
オウム返し Bot に話しかけると、そっくりそのまま返してくれます。
image.png

Bot Secret について
Bot へのメッセージ送信は、Callback URL さえわかっていれば、認証もなく誰でもアクセスすることができます。
Bot に対して発行される Bot Secret を用いてメッセージのハッシュを計算し、X-WORKS-Signature ヘッダーの値と比較することで、本当に LINE WORKS から送られたメッセージであるかを検証することができます。
運用環境で Bot の Callback を利用する場合には、メッセージの検証を必ず行うようにしてください。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?