redashのuserをgitで管理する

はじめに

[本記事はredash meetup 4.0.0で発表させていただいた内容に肉付けしたものです]

redashはデータベースに接続できるツールなのでuserの管理がとても重要になる。
userを定期的に棚卸しをし、メンテナンスしていくことはセキュリティを維持する上で必須だ。弊社では

  1. CLIでuser一覧を出す
  2. それをgitlabで管理
  3. gitlabに上がったということをchatworkで担当者に伝える
  4. 問題なければmerge
    merge日=最終棚卸し日

というフローを採用し運用している。

しかし、想定していた運用を採用するうえではソースを変更する必要があった。

現在 version 5.0.2のCLI

残念ながらこの画像からわかる通り、非常に貧弱である。

version 5からuserをdisableする機能が導入されたが、userがenableなのか、disableなのかという情報がCLIからだとわからない。

pull requestの作成

機能としては存在しているのに、CLIで見れないとなると単純に表示させていないだけなのかもと察しソースを読んだ。

Userのenableなのか、disableの情報を表示するメソッドを見つけた

https://github.com/getredash/redash/blob/68272678b85ef4a6498543ef6a33a2071e607628/redash/models.py#L439

おそらくGUIであればこの処理を叩いて画面に表示している。

機能があるのであればCUIも同じように叩けばよいのでは?という仮説のもとファイルを変更した

https://github.com/getredash/redash/pull/2951/files

これでenableなのか、disableなのかがコマンドラインで確認できるようになった。

自分の管理するredashはdockerで動いているので、linux上でviコマンドで編集し、docker cpコマンドでコンテナ内に転送することで変更を動いているredashに反映させた。

OSSのソースに手を入れるというと相当な知識がないと変更できないかと思っていたが、progateでpython覚えた程度でも変更できた。

最初テストケースを書かずにpushしたらCIでコケたので、恥ずかしながらそこでredashのテストコードの存在を知った。。

せっかくなのでpull reqを出すと翌日mergeしてもらい、これがコントリビュートにつながった。

 

その後CLI機能を拡張すべく2つpull requestを出させていただき、いずれも承認された。

redashでユーザーを取得しGitLabへpushへ

gitlab-cliの設定する必要があるので事前にセットアップする

GitLabでCLI経由でmerge requestを送る

shellをcronで動かし、その中でpythonのスクリプトを動かす

#!/bin/bash

hostname=`uname -n`
_roomid=123456789
output=/tmp/$hostname

cd ~/redash-user/

git pull 
nohup /usr/bin/docker exec -i redash_server_1 ./manage.py users list > ~/redash-user/$hostname &

sleep 10;
ps -ef | grep "./manage.py users list" | grep -v grep | awk '{print $2}' | xargs kill -9

git checkout -b $hostname
git add $hostname
git commit -m $hostname
git push origin $hostname

python merge.py

pythonはGitLabへpushするのに使っている。コードはこちら

import os
import gitlab

hostname = '%s' % os.uname()[1]

gl = gitlab.Gitlab('https://gitlab.sumito.com/', private_token='abcdefgggggggg')
gl.auth()

project = gl.projects.get(123, lazy=True)

mr = project.mergerequests.create({'source_branch': (hostname),
                                   'target_branch': 'master',
                                   'title': (hostname) + ' user list'
                                   })

mrs = project.mergerequests.list(state='opened', order_by='updated_at')[0]

print(mrs.attributes['web_url'])

以下のようにcronを仕込み月に一度listを更新し、GitLabにpushするようにしている。

0 0 1 * * sh /root/redash-user/redashUsers.sh 1> /tmp/stdout.log 2> /tmp/stderr.log

GitLabにMergeRequest上がっているのを取得、chat投げる処理

これも同様にshellからpythonを動かすようにしている。

#!/bin/bash

cd /root/redash-user/
hostname=`uname -n`
_roomid=123456789

tmp=$(/usr/bin/python ./chat.py)
tmowl=`echo $tmp | grep git.sumito.com | wc -l`
output=/tmp/gomi

if [ $tmowl -eq 0 ] ; then
  exit
else

/usr/bin/cat << _EOT_ > /tmp/gomi
[toall]
[info]
[title]latest redash account Please check it!!
[/title] 
`/usr/bin/python ./chat.py`
[/info]
_EOT_
  
_body=`/usr/bin/cat $output`
/usr/bin/curl -X POST -H "X-ChatWorkToken: 123456789" -d "body=${_body}" "https://api.chatwork.com/v2/rooms/${_roomid}/messages"

fi

pythonはこちら

import os
import gitlab

hostname = '%s' % os.uname()[1]

gl = gitlab.Gitlab('https://git.sumito.com/', private_token='123456789')
gl.auth()

# your project ID
project = gl.projects.get(123, lazy=True)

mrs = project.mergerequests.list(state='opened', order_by='updated_at')
mr_url = [mr.attributes['web_url'] for mr in mrs]
print("{}".format("\n ".join(mr_url)))

アカウントの棚卸し

以下のように表示される

この状態ではmerge requestが発行された状態なので、

管理者はこのリクエストを確認し、最新の状態を確認。問題なければmergeする

当然gitなので最新merge日は更新され、この日が棚卸し完了日と位置づけすることにより、最終棚卸し日がいつだったのかわかるようにしている。