俺の報告

RoomClipを運営するエンジニアの日報(多分)です。

日報 #55 - シェルの訓練として

おいおい!
今日も何もしてねぇぞ!!
チケット作りっぱなしでバックレか平山!

元気でやってます。
ところで、かなり的外れな話ですがbasic認証にexpireを付けたくなるシーンに出くわしました。
まぁなんだっていいんですが、すごい簡単に期限付きのID/PASSを発行したいってことです。
もちろんBASIC認証にそんな機能ない、というかそもそもそういうものじゃないので無理やりやります。

DB上にname,pass,exipreを保存して、それをcronで毎日確認。
そのDB情報に沿ってhtpasswdファイルを作成する、ってことさえ出来れば良さそうです。
一見すると簡単ですし、phpとか使えばすぐ出来そうですね。
もちろんそんなことガン無視してbashでやりましょう!

結論から言うとMySQLとシェルを連携させるのが中々難しいです。
問題は「MySQLからの出力をどうパースするか」これに尽きます。
ですが、1つずつやっていくとシンプルです。
まず一行ずつ配列とします。これはIFS=$'\n'と変更して()で取得。
次にkey-valueの構造で持たなければならないのが厄介です。
ここでSELECT文に工夫を凝らします。
後にeval関数でID名を変数名として、${ID名}=${VALUE値}のように突っ込無事を考えて、
CONCATでもってCONCAT('name=', name),CONCAT('pass=', pass)こんな感じに出力しておく。
あとはevalして変数名と値を取得する。
これでnameとpassが手に入りますね。

結果こんな感じです。

#! /bin/bash

FILE_NAME=.htpasswd
DEF_ID=hoge_master
DEF_PASS=hoge_pass

# init htpasswd
htpasswd -cb ${FILE_NAME} ${DEF_ID} ${DEF_PASS} 1>/dev/null 2>&1

# get user-pass list from db
EXPIRE_DATE=`date +"%Y-%m-%d %H:%M:%S"`
MYSQL_USER=hoge_user
MYSQL_PASS=hoge_pass
MYSQL_HOST=hoge_host
MYSQL_DB=hoge_db
MYSQL_QUERY=`echo "SELECT CONCAT('name=', name),CONCAT('pass=', pass) FROM basic_auth WHERE expire >= '${EXPIRE_DATE}'"`

# ID/PASS from DB
IFS=$'\n'
RST=(`mysql -u ${MYSQL_USER} -p${MYSQL_PASS} -h ${MYSQL_HOST} ${MYSQL_DB} -e "${MYSQL_QUERY}"`)

# Get variables by "eval ${ID}=${VALUE}"
ITE=0
for RES in ${RST[@]}
do
    if [ "$ITE" -gt 0 ] ; then
        eval `echo $RES`
        echo "$ITE - ${name}"
        echo "$ITE - ${pass}"
        htpasswd -nb ${name} ${pass} 1>>${FILE_NAME}
    fi 
    ITE=`expr $ITE + 1`
done

これをcronで食わせれば指定場所に.htpasswdが作成されます。
擬似的にexpireがかかっているように見えますね。
シェルに不慣れなので、こういうのが訓練になります。
楽しいね。じゃぁね。