LineNotify APIでsshログイン通知をする
以前、sshでログインしたことをSlackに通知するというのを書いたことがあります。
ちょっと前にLineNotify APIがリリースされたので、こちらでも使って見るようにしてみました。 基本的な設定方法は↑のエントリと同じですが、スクリプトなどの内容だけをこのエントリでは書いておきますね。
ファイル構成
/etc/pam.d/sshd
にて実行するファイルのパスなどを設定しておけば、そのスクリプトが実行されますが、今回はスクリプトとLineNotify API実行時にヘッダに設定するToken情報を記述するファイルを分けてみました。
/etc/line ├── line-token └── login-notify.sh
tokenは、https://notify-bot.line.me/my/で発行できます。
login-notify.shの内容は次のようにしました。
#!/bin/sh script_dir=`dirname "${0}"` endpoint=https://notify-api.line.me/api/notify if [[ $PAM_TYPE != "close_session" ]] ; then host=$(hostname) message="SSH Login: ${PAM_USER} from ${PAM_RHOST} on ${host}" token=$(cat "${script_dir}/line-token") header="Authorization: Bearer ${token}" curl -X POST -H "${header}" -F "message=${message}" ${endpoint} fi
Lineに送信する内容を変えたい場合には、message
を指定している部分を適宜変更してください。
基本的には上記の内容で動作するはずですが、うまく動かない場合にはcurl
の出力をファイルに書き出すと内容が確認できます。
例えば、-o /tmp/res
などを追加するとAPIを呼び出したレスポンスを確認できます。
参考
プログラムを教えることになる
ご無沙汰しております
ここ1ヶ月位、息子たちにプログラムを教えていました。
長男は大学の課題でC言語を 次男は高校のパソコン部の成果発表のためにUnity(C#)を
C言語
テキストは明解C言語とか。懐かしい。 https://www.amazon.co.jp/dp/479737702X
学校の環境は秀丸とCygwinだそうです。先生の苦労が忍ばれますが、今ならDockerにUbuntuとかでいいんじゃないですかね。 あるいはWindows10でbashを動かすとか。 どちらも最近の環境が必要そうですから無理なのでしょうけど。
Unity
実はまともにUnityを触ったのは今回が初めてで、親も一緒に勉強しました。 GameObjectは次男が予め作っておいていたので、それに動きをつけることを一緒に学びました。
私は普段はゲームをしないので、次々に湧いて出てくるゲーム改善の勢いに飲まれつつ、いろいろな機能を実装しました。 スマホゲームのサーバサイドは仕事で作ったことがありますが、UIとなると細かいタイミングなどの調整が大変なのですね。
これからUnityについても書こうかな。
APIのmockダミーサーバ
ユニットテストで外部のAPIを呼び出す場合などで実際にそれを呼び出しづらいことってありますよね。
また、クライアントを開発するときにサーバサイドのAPIが仕様は決まっているけどまだできていないとか困りますよね。
そういう経験が最近よくあったので、常にそれっぽいAPIのレスポンス(JSON)を返すダミーのサーバをGoで作ってみました。
https://github.com/yhanada/apimock
いままではGoのサンプルを動かす程度だったのですが、そろそろサンプル以外も作ってみようかな、と。
実行はシンプルで、Goのアプリに対してDocumentRootとなるディレクトリを指定して起動します。
$ apimock-go -root ./root
たとえば、DocumentRootで指定したroot
ディレクトリの構成が次のようになっているとします。
root ├── actions.json └── v1 └── users ├── 1 │ └── actions.json └── actions.json
レスポンスデータは各ディレクトリの下に置かれたactions.json
に記述しています。
例えば、/v1/users/1
に対するリクエストを定義しているactions.jsonの中身は次のようになります。
{ "GET": { "body": { "id": 1, "name": "Taro Yamada" } }, "POST": { "status": 405 }, "PUT": { "body": { "id": 1, "name": "Taro Takahashi" } }, "DELETE": { "body": { "result": "deleted", "id": 1 } } }
各HTTPメソッドの下に、status
とbody
があるだけです。
status
にはHTTPのステータスコードを記述します。上記の例だとPOST
メソッドが呼び出された場合には405
であるMethod Not Allowedを返します。
HTTPメソッドが定義されていない場合には、404
を返します。
上記例では、GET
にはstatus
が定義されていませんが、その場合には200
を返します。
そしてbody
以下に定義されたJSONがそのままレスポンスとして返されるようになっています。
今後はKotlinを使ったAndroidアプリも作っていこうと考えてます。そのときに使えればいいな。
Slack botを試す
そろそろ次へ
SlackのSlashコマンドで遊ぶのもそろそろ飽きてきたので、次にSlackのBotに挑戦してみたいと思います。
Slack Botで何をやりたいか
個人サーバ環境をIDCFクラウドに移行し、何かあった場合の通知はMackerelからSlackに送るように設定しています。
そこで何かあった時にSlackで(slash commandでもいいけど)対応したいな、と。
まずはお試し
goslackでもお世話になった、kyokomiさんのslackbot https://github.com/kyokomi/slackbot を使ってみました。
ここのexampleをそのままコピーして動かしてみました。 これは、SlackのReal Time Messaging APIを利用した仕組みで、サーバに(GAEも)デプロイしなくても、ローカルからでも動作確認が出来ます。
SlackのBots
を追加して、SLACK_BOT_TOKENを取得したらすぐに動かせます。
動かしてみて
家庭内LANからのためか、SlackでBotに対してコマンドを入力してからレスポンスまでが非常に時間がかかっています。 また、一度失敗すると次からは何を送っても、失敗前の最後のメッセージを返していました。
まぁこのあたりぼちぼち見ていくかな。
試したコードはこのへんに置いときます。
GAEで環境変数から値を取得する
やりたいこと
GAE上に構築したslack slash commandで、Slackから送られるtokenをチェックしたい。
どうやったか
やり方はいろいろとあると思いますが、今回は環境変数に設定したtokenを取得し、Slackから送られたtokenと比較するようにしました。
GAEの環境変数の設定方法
まずは、app.yaml
に記述する方法です。
参考:app.yaml Reference | Go | Google Cloud Platform
app.yamlにenv_variables
という項目を追加し、名前: 値
という形式で記述します。
以下の例では、SLACK_TOKEN
という変数名に、slack_token
という値を設定しています。
env_variables: SLACK_TOKEN: 'slack_token'
tokenは秘密にするべき値なので、リポジトリに残しておきたくない場合にはdeploy時にオプションとして指定する方法もあります。
参考:appcfg.py Command Line Arguments | Go | Google Cloud Platform
$ appcfg.py update . -E SLACK_TOKEN:"slack_token"
コードからtokenを取得
次に、コードから環境変数に設定されたSLACK_TOKEN
を読み出します。
os.Getenv("変数名")
で取得できます。
後は、この取得したtokenをSlackから送られたtokenと比較し、異なっていればエラーレスポンスを返すだけです。
import ( "bytes" "encoding/json" "net/http" "os" // 省略 ) func init() { renderer := render.New(render.Options{}) token := os.Getenv("SLACK_TOKEN") // 省略 }
GoのアプリをDockerコンテナ上でビルドする
やりたいこと
開発はMac上で行うが、サーバはLinuxなので(予定)Linux用のビルドを行いたい。 どうせならば、Docker使いたい
どうやったか
リポジトリをcloneしたプロジェクト直下のディレクトリで以下のコマンドを実行。
$ docker run -it --rm -v $PWD:/go/src/app golang:onbuild /bin/bash -c "make clean && make build"
-v
オプションで、プロジェクトのディレクトリをDockerコンテナの/go/src/app
にマウントしています。
そして、bashのコマンドとしてmakeを実行しています。
あら簡単
注意:Dockerのイメージ(golang:onbuild)のダウンロードに少々お時間がかかります
goslashを自前のサーバで動かしてみた
net/http
に対応させる
これまではgoslashをGAEで動かしてみましたが、goslash自体はGAEに依存しているわけではありません。
net/http
のResponseWriterやRequest、そしてClientがあれば他の環境でも動かすことが出来ます。
ということで、通常のhttpサーバとして動くようにするにはちょっとした修正で終わりました。
今回対応させたコードはこちらにあります。
GitHub - yhanada/goslash-sample-server
コマンドラインの処理について
AppEngineでは自分がローカルで起動しているかどうかを判定するためのメソッドがありましたが、自前実装ではコマンドラインオプションとして起動時に渡すようにしたいと思いました。
今回、いろいろと調べてみて「へ〜」となったのが、コマンドライン処理でUsage
を表示させる方法です。
コマンドラインオプションの処理をしているところを抜粋すると以下のようになります。
ここで、flag.Usage
に対してfuncを渡しているところがあるのですが、これだけで-h
を指定した場合にこのfuncが実行されるようになります。
そして、flag.PrintDefaults()
で、flagに定義したオプションを表示させることも出来ます。これを呼び出すようにしておけばオプションの名前を変更したとか、削除したとかをUsageに反映忘れとかがなくなって便利ですね。
var ( port uint timeout Time.Duration isDev bool ) func main() { flag.UintVar(&port, "port", 8080, "server port") flag.BoolVar(&isDev, "dev", false, "is development mode") flag.DurationVar(&timeout, "timeout", 10*Time.Second, "http client timeout") flag.Usage = func() { fmt.Fprintf(os.Stderr, "Usage of %s:\n %s [OPTIONS]\n", os.Args[0], os.Args[0]) flag.PrintDefaults() } flag.Parse()