PostfixAdmin的なものを作ってみた。
1台のメールサーバーで複数ドメイン運用したり、システムアカウントと連動せずにメールアカウント運用したいとかのときに、便利なPostfixAdmin( Postfix Admin - Web based administration interface)さん。
わたくしもお世話になっておりましたが、MySQLやPostgreSQLと一緒にメールサーバーを動かしてあげないといけないのが面倒になってきた今日この頃...。LXDコンテナで流浪人のように移動しやすいコンテナとしておきたいわけです。もちろんMySQLでもPostgreSQLでもコンテナごと動かす分にはいんですけど、システムリソース的に...ということで...。
そんなオレオレ要件を満足させるものを作ってみました。 github.com
バーチャルメールユーザー管理画面
バーチャルメールユーザーの変更画面
バーチャルメールエイリアス管理画面
バーチャルメールエイリアスの変更画面
バーチャルメールドメイン管理画面
バーチャルメールドメインの変更画面
今回使ったもの
- Bottle: Python Web Framework — Bottle 0.13-dev
- Bottle-SQLite
- Bootstrap · The world's most popular mobile-first and responsive front-end framework.
Pythonの軽量フレームワークのBottleをメインにして、UI部分と入力制御系をJavascriptで実装してみました。
本当は、PostfixAdmin的にユーザーログインによる認証機構もつけようとしたのですが、オレオレツールとしては、取り急ぎ必要ではないという英断により、未実装。これからお勉強がてら実装したいです。
Cork - Authentication for the Bottle web frameworkというのを使えばよさげかなと思っています。
今回、ちょっと積極的にcodeclimateさんのチェックを通しながらやったら、確かにコードが短くなったり煩雑だったところがすっきりとしました。(最初のコーディングが美しくな過ぎたというのはさておき....)pythonやら、javascriptやら、jQueryやら、PostfixやらDovecotやらsqlite3やらいろんな勉強になったので、個人的には満足です。(これってよくあるダメなやつじゃないか...)
いうまでもなく、現状としてはデバックもかねて、SSHトンネル経由でbottleの簡易サーバー機能をそのまま使って動かしているレベルなので、実運用レベルにはありません。
ちなみにGoogle先生に「postfixadmin sqlite」尋ねてみたら、こんなのがあった。
2010年3月ごろからある模様。MySQLやらPostgreSQLやらを使ってやるまでの規模じゃないんだけど...なことはそりゃ考えるよな。
(2016.09.15 追記)
2016/09/12にPostfixAdmin3.0がついにリリースされたようで、なんと、add sqlite backend optionと言っているので、動作検証していないけどsqliteでも使えるようになったようです。
0. Raspberry Pi3 の初期セットアップ
Raspbery Pi3のセットアップの記事を探すとさくっと出てくるのはディスプレイを繋いで、マウスとキーボード繋いで式だったりしますが...
「HDMIの繋がるディスプレイなんてないよ!」
でも大丈夫!僕らにはSSHがあるじゃないか。
「有線LANとか繋ぐのだるくね?」
でも大丈夫!wifiの設定ファイルを書いちゃっとけばいいじゃないか。
という我が家の環境を鑑みたバージョンでお送りします。
Raspbianイメージの書き込まれたmicroSD作成
1. OSイメージファイルのダウンロード
Download Raspbian for Raspberry Pi
素直にRaspbianにしておく。あとでリモートデスクトップとか別所で画面つないで使うこともあるので、「Full desktop image based on Debian Jessie」の方を利用。
2. OSイメージをmicroSDに書き込む
Installing operating system images - Raspberry Pi Documentation
公式殿のドキュメントにしたがってやればよい。Ubuntu16.04環境でやると以下のような流れ。
## SDカードのマウント状況確認 kacchan822@ubuntu16:~$ df -h Filesystem Size Used Avail Use% Mounted on udev 7.8G 0 7.8G 0% /dev tmpfs 1.6G 9.5M 1.6G 1% /run /dev/mapper/ubuntu--vg-root 101G 45G 52G 47% / tmpfs 7.8G 390M 7.4G 5% /dev/shm tmpfs 5.0M 4.0K 5.0M 1% /run/lock tmpfs 7.8G 0 7.8G 0% /sys/fs/cgroup /dev/sda2 237M 171M 54M 77% /boot /dev/sda1 511M 3.6M 508M 1% /boot/efi cgmfs 100K 0 100K 0% /run/cgmanager/fs tmpfs 1.6G 80K 1.6G 1% /run/user/1000 /dev/mmcblk0p1 15G 8.0K 15G 1% /media/kacchan822/9779-6F81 ## microSD(/dev/mmcblk0p1)がマウントされていたのでマウント解除 kacchan822@ubuntu16:~$ umount /dev/mmcblk0p1 ### マウント解除されたのを一応確認 kacchan822@ubuntu16:~$ df -h Filesystem Size Used Avail Use% Mounted on udev 7.8G 0 7.8G 0% /dev tmpfs 1.6G 9.5M 1.6G 1% /run /dev/mapper/ubuntu--vg-root 101G 45G 52G 47% / tmpfs 7.8G 390M 7.4G 5% /dev/shm tmpfs 5.0M 4.0K 5.0M 1% /run/lock tmpfs 7.8G 0 7.8G 0% /sys/fs/cgroup /dev/sda2 237M 171M 54M 77% /boot /dev/sda1 511M 3.6M 508M 1% /boot/efi cgmfs 100K 0 100K 0% /run/cgmanager/fs tmpfs 1.6G 80K 1.6G 1% /run/user/1000 ### ダウンロードしたOSイメージファイルのディレクトリへ移動・ファイル存在確認 kacchan822@ubuntu16:~$ cd Downloads/ kacchan822@ubuntu16:~/Downloads$ ls 2016-05-27-raspbian-jessie.img ## OSイメージの書き込み ### さっきのアンマウントしたのは、「/dev/mmcblk0p1」だけど、書き込み先としては、「/dev/mmcblk0」になるので注意って公式ドキュメントも言っている。 kacchan822@ubuntu16:~/Downloads$ sudo dd bs=4M if=2016-05-27-raspbian-jessie.img of=/dev/mmcblk0 [sudo] password for kacchan822: 958+1 records in 958+1 records out 4019191808 bytes (4.0 GB, 3.7 GiB) copied, 859.35 s, 4.7 MB/s ## 公式殿にはこのあとmd5チェックサムで書込結果の検証する方法が紹介されているけど、大丈夫だと信じて割愛。
3. Wi-fiの設定ファイルを編集する。
2.でOSイメージを書き込んだSDカードをマウントし直す。コマンドでやればいい気もするけど、一回抜いて、挿し直せば自動でマウントしてくれるはず。
「boot」と「2f840c69-cecb-4b10-87e4-01b9d28c231c」というようなのがマウントされるので、長ったらしい名前の方のマウントされている方の中にあるwifiの接続設定ファイルを編集れば、有線で最初に一度繋がなくていい。
## 設定ファイルのあるディレクトリへ移動 kacchan822@ubuntu16:~$ cd /media/kacchan822/2f840c69-cecb-4b10-87e4-01b9d28c231c/etc/wpa_supplicant/ ## 設定ファイルを開く(root権限(SUDO)で開く必要がある。) kacchan822@ubuntu16:/media/kacchan822/2f840c69-cecb-4b10-87e4-01b9d28c231c/etc/wpa_supplicant$ sudo vi wpa_supplicant.conf
設定ファイルを以下のように編集する。
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev update_config=1 country=JP network={ ssid="接続するwifiのSSID" psk="接続するwifiのパスワード" key_mgmt=WPA-PSK }
countryは後でも直せるけどついでなのでJPにしておく。 wifiのセキュリティ設定によって、少し設定値が変わってくるだろうけど、 wpa_supplicant.conf(5) - Linux man pageを参考にすれば大丈夫かなと。
完成!
取り出しておく。
Raspbery Pi3を起動してSSH接続
1. OS起動!
OSイメージの入ったmicroSDをRaspberry Pi3に差し込んで、microUSBで給電するとピカピカと、赤および緑のランプが光って起動を始める。緑のランプの点滅が落ち着いた頃合いでsshしてあげるとよさ気。
2. SSHで接続
IPアドレスはDHCPで割り当てられるだろうので(固定にしたかったら、wifiの設定をした流れでついでにネットワークせってファイルもいじっとけばいいだろう)、ipアドレスがわからないが、、、
kacchan822@ubuntu16:~$ ssh pi@raspberrypi.local
と叩けば、うまいこと見つけて接続してくれる。初期パスワードは「raspberry」なので、パスワードを聞かれたら入力してあげるとログインできる。
とりあえずアップデートとか
ログインできたらとりあえず、初期パスワードからログインパスワードを変更したり、ソフトウェアアップデートをしたり、raspberrypiの設定値をいろいろ調整したりしておく。
## ログインパスワード変更 pi@raspberrypi:~ $ passwd ## アップデート(結構時間かかる) pi@raspberrypi:~ $ sudo apt-get update pi@raspberrypi:~ $ sudo apt-get upgrade ## 設定値の変更 pi@raspberrypi:~ $ sudo raspi-config
ひとまずこんなところでしょうか。raspi-configの各種設定値はお好みで。Expand Filesystemは、32GB、16GBのは特にしなくてもうまいことなっている感じだった。
Raspberry Pi3 で子どもたちと「遊ぶ」までの道のり(とりあえず自分で遊んでみる編)
前々から気になっていたRaspberry Piですが、なんだかんだとウダウダしていて、なかなかポチッとなしてなかったのですが、実験やらプログラミングやら電子工作やらして子どもらと遊ぶことになったので、ついに購入。
子どもらとどうやって遊ぶかも含めて、まずは自分で遊び倒してみることにしたはいいが、やれることが無限大すぎて、どこから手をつけたらいいものやらなので、Raspberry Pi3と一緒に注文してみた、以下のキットに含まれる部材でできることをいろいろやってみることにする。
とりあえず以下予定。
- 0. Raspberry Pi3 の初期セットアップ
- 1. Raspberry Pi3 でLEDをチカチカ
- 2. Raspberry Pi3 でLCDに文字表示
- 3. Raspberry Pi3 で温度センサーで室温取得
- 4. Raspberry Pi3 でフルカラーLEDをチカチカ
- 5. Raspberry Pi3 でモーター制御
- 6. Raspberry Pi3 でサーボモーター制御
Apache 2.4 + MariaDB 5.5 でmod_dbd を使ったDigest認証の設定をしてみた。
使いどころがあるのか謎だけど、Apacheの認証系でもDB連携あるぞというのをたまたまみかけたので、やってみた。
環境
必要なパッケージのインストール
DBドライバーのインストール。今回は、MariaDBで試すので、apr-util-mysqlをインストール。
- apr-util-ldap.x86_64 : APR utility library LDAP support
- apr-util-mysql.x86_64 : APR utility library MySQL DBD driver
- apr-util-odbc.x86_64 : APR utility library ODBC DBD driver
- apr-util-pgsql.x86_64 : APR utility library PostgreSQL DBD driver
- apr-util-sqlite.x86_64 : APR utility library SQLite DBD driver
Daigest認証用のDB.TABLE作成、ユーザーデータ登録
まずDBとテーブルを作る
DB名:apacheauth (任意)
TABLE名:digest_auth_users (任意)
CREATE DATABASE apacheauth; CREATE TABLE digest_auth_users ( id INTEGER PRIMARY KEY AUTO_INCREMENT, user VARCHAR(255) NOT NULL UNIQUE, password VARCHAR(255) NOT NULL, realm VARCHAR(255) DEFAULT 'AuthRequirePage' );
** realmは後にApacheの設定でAuthNameで指定する文字列。
Apacheからデータを参照するためのDB接続ユーザーを作成する
基本的には参照権限だけあれば十分。プログラムで動的に変更するなど操作を同じユーザーでさせるならば、UPDATEやDELETEも権限を与えてあげる。
GRANT SELECT ON apacheauth.* TO 'apache'@'localhost' identified by 'apache';
テスト用のユーザーデータを入れる
セキュアじゃないけど今回はDB上には平文のパスワードを保持させることにした。
INSERT INTO digest_auth_users ( user, password ) VALUES ( "test", "test" );
id | user | password | realm |
---|---|---|---|
1 | test | test | AuthRequirePage |
Apacheの設定
conf/httpd.conf(またはconf.d/<任意の名称>.conf)または、VirtualHostディレクティブ内 に以下の記述を行う。
DBD~の部分は、Directoryディレクティブの中には書けないので注意。
参照 --> mod_dbd - Apache HTTP Server Version 2.4
DBDriver mysql DBDParams "host=localhost,dbname=apacheauth,user=apache,pass=apache" DBDMin 2 DBDKeep 2 DBDMax 10 DBDExptime 300 <Directory "/var/www/auth_html"> Options Indexes FollowSymLinks AllowOverride None Require valid-user AuthType Digest AuthDigestAlgorithm MD5 AuthName "AuthRequirePage" AuthDigestProvider dbd AuthDBDUserRealmQuery "SELECT MD5(CONCAT(user, ':', realm, ':', password)) AS password FROM digest_auth_users WHERE user = %s AND realm = %s" </Directory>
今回はDBには平文でパスワードを保存したので、AuthDBDUserRealmQueryの部分でDB問合せ時に、Apacheのmod_auth_digestが求める形のパスワード形式(user:realm:passwordをMD5ハッシュした32文字列)
参照 --> Password Formats - Apache HTTP Server Version 2.4
%sには、前から順に入力されたuser名、AuthNameの値が入る。
一応SQLの部分だけ抜き出しておくとこんな感じ。
SELECT MD5( CONCAT(user, ':', realm, ':', password) ) AS password FROM digest_auth_users WHERE user = %s AND realm = %s
%sに入る値は、mod_dbdでうまいことSQLインジェクション対策として不正な文字列はエスケープしてくれるらしい。
参照 --> mod_dbd - Apache HTTP Server Version 2.4
完了!
あとはApacheの再起動をして設定を反映させればよい。
アルファベット文字列をフォネティックコードで表記するPythonモジュールをつくったよ:a2pcej
アカウントの追加業務とかで、パスワードをこちらで適当に生成してお知らせるときに、パスワード文字列のよみがなをつけて渡すということが、しばしばあるわけです。
たとえば、こんなやつ。
ユーザー名: hogehoge パスワード: WPzm60zh (ダブリュー(大文字)・ピー(大文字)・ゼット・エム・ロク・ゼロ・ゼット・エイチ)
大した数じゃなければ手打ちするのもいいんですが、一気にどかっと発行するとかなると手打ちするは厄介です。自動でやってしまいたいところです。
Google先生に尋ねると、
- フリガナつきパスワード生成ツール - Password Generator
- パスワードをカナに変換するツール|シラサヤ備忘館
- Excel2010 英数字にふりがな|ichiのおもちゃ箱
- パスワードの読み仮名を作るc2pコマンド | /var/log/azumakuniyuki
といったのが出てきます。パスワードの生成からやってしまってよければ、フリガナつきパスワード生成ツール - Password Generator は、大量生産できるのでよさ気ですが...
パスワードのよみがなの区切り文字や、大文字につける表記が自分のところで使っているフォーマットと合わなかった...
ということで、実はずい分前に手元で使える用には、ざっくりpythonスクリプトで作ってありました。
今回これを大改造して、
- 区切り文字を指定できる
- 大文字につける印を指定できる
- カタカナ表記だけではなく、英語圏用(?)にフォネティックコード表記できる
というものを作ってみました。いろんなところで使いまわしやすいように、PyPIに上げて、pipでインストールできるようにしました。 謎のネーミングセンスにより、a2pcejという名称にしました。一応、convert Alphabet to Phonetic Code in English and Japaneseの略。
使い方
以下Python3.5環境での出力例です。関数の戻り値はunicode文字列になっています。
兎にも角にもモジュールをインポート。
>>> from a2pcej import *
アルファベットの文字列にカタカナでよみがなをつける。 :conv_ak()
>>> conv_ak('examples') 'イー・エクス・エイ・エム・ピー・エル・イー・エス'
アルファベット大文字にはデフォルトで「(大文字)」と付く。
アルファベット以外(記号や数字)はデフォルトだとよみがな変換されない(その文字がそのままま出る)。
>>> conv_ak('Examples002') 'イー(大文字)・エクス・エイ・エム・ピー・エル・イー・エス・0・0・2'
区切り文字を変更するには、delimiter='文字列'
を引数に追加する。
アルファベット大文字につく文字列の変更をするには、 sign='文字列'
を引数に追加する。
空にすれば、区切りなし、大文字表記なしになる。
>>> conv_ak('Examples003', delimiter='/', sign='(大)') 'イー(大)/エクス/エイ/エム/ピー/エル/イー/エス/0/0/3' >>> conv_ak('Examples003', delimiter='', sign='') 'イーエクスエイエムピーエルイーエス00'
数字にもよみがなを付けたいときは、num=True
を引数に加える。
>>> conv_ak('Examples004', num=True) 'イー(大文字)・エクス・エイ・エム・ピー・エル・イー・エス・ゼロ・ゼロ・ヨン'
アルファベットの文字列に英単語のフォネティックコードをつける。 :conv_al()
オプションは、 conv_ak()
と同じなので、出力例だけ。
区切り文字、大文字につく文字列のデフォルトを英語圏っぽいのにしてある。
>>> conv_al('examples') 'Echo-Xray-Alfa-Mike-Papa-Lima-Echo-Sierra' >>> conv_al('Examples002') 'Echo(CAPS)-Xray-Alfa-Mike-Papa-Lima-Echo-Sierra-0-0-2' >>> conv_al('Examples003', delimiter=', ', sign='(CAPITAL)') 'Echo(CAPITAL), Xray, Alfa, Mike, Papa, Lima, Echo, Sierra, 0, 0, 3,' >>> conv_al('Examples004', num=True) 'Echo(CAPS)-Xray-Alfa-Mike-Papa-Lima-Echo-Sierra-zero-zero-four'
ソース
PyPI
雑感
python2での文字コードのこととか、パッケージングする方法とか、pandocってなんか便利なツールがあるとか、いろいろお勉強になりましたです。久しぶりに英文も書いたらスペルミスと謎の構文の嵐です。