mod_mrubyに認証とredis連携の機能追加した

久々にmod_mrubyの話題のような気がします。

先日、 @hiroki_nazy さんからApacheの認証系の機能実装のpull-requestを頂いたの早速マージしておきました。機能詳細は、BlogかWikiに書いてくれるということなので、今回はざっとBasic認証のサンプルの紹介と、先ほど実装したRedis連携の機能追加を紹介します。

mod_mrubyでBasic認証

今回、 @hiroki_nazy さんが実装してくれた機能はApacheのBasic認証とDigest認証をmod_mruby上で実現するための機能です。

サンプルは以下のようになります。

まず、Apacheのconfに以下のような設定を記述します。

[program lang=’apache’ escaped=’true’]

 <Location /basic/>
   AuthType basic
   AuthName "Message for clients"
   AuthBasicProvider mruby
   mrubyAuthnCheckPassword /var/www/html/auth.rb
   require valid-user
 </Location>

[/program]

さらに、/var/www/html/auth.rbに以下のように記述します。

[program lang=’ruby’ escaped=’true’]

user_list = {
  "bilbo" => "foo",
  "frodo" => "bar",
  "samwise" => "baz",
  "aragorn" => "qux",
  "legolas" => "quux",
  "gimli" => "corge",
}

anp = Apache::AuthnProvider.new

if user_list[anp.user] == anp.password
  Apache.return(Apache::AuthnProvider::AUTH_GRANTED)
else
  Apache.return(Apache::AuthnProvider::AUTH_DENIED)
end

[/program]

これによって、http://example.com/basic/ にアクセスがあると認証が求められ後、入力するとmrubyスクリプトがフックされ、上記のスクリプト内のanp.userとanp.passwordに入力したBasic認証の値が入って、評価されます。

Basic認証に、もう少し認証の条件を増やしたい場合等に有用なこと間違いなしでしょう。

mod_mrubyからRedis連携

mod_mrubyからRedis連携できるようにしました。

まずは、最低限の機能として、getとsetメソッドを実装しました。サンプルは以下のようになります。

[program lang=’ruby’ escaped=’true’]

r = Apache::Request.new()
r.content_type = "text/html"

a       = Apache
host    = "127.0.0.1"
port    = 6379

a.rputs("> redis connect " + host + ":" + port.to_s + "<br>")
redis = Apache::Redis.new(host, port)

key     = "hoge"
val     = "aaaaaaaaaaaaaa"

a.rputs("> redis set " + key + " " + val + "<br>")
redis.set(key, val)

a.rputs("> redis get " + key + "<br>")
a.rputs(key + ": " + redis.get(key) + "<br><br>")

key     = "hoge"
val     = "bbbbbbbbbbbbbb"

a.rputs("> redis set " + key + " " + val + "<br>")
redis.set(key, val)

a.rputs("> redis get " + key + "<br>")
a.rputs(key + ": " + redis.get(key))

[/program]

そして、Apacheにアクセスすると以下のように表示されます。

[program lang=’text’ escaped=’true’]

> redis connect 127.0.0.1:6379
> redis set hoge aaaaaaaaaaaaaa
> redis get hoge
hoge: aaaaaaaaaaaaaa

> redis set hoge bbbbbbbbbbbbbb
> redis get hoge
hoge: bbbbbbbbbbbbbb

[/program]

redis.set(key, value)でkeyとvalueをsetし、redis.get(key)でvalueをgetします。

今後は、柔軟にRedisと連携できるようにメソッドを追加していこうと考えています。使いどころとしては、mod_mrubyでproxyやvhost系の実装の際に、Redis経由で値をとってくるようにすると便利だと思います。イメージとしては、「lua-nginx-module の紹介 ならびに Nginx+Lua+Redisによる動的なリバースプロキシの実装案」を参考にすると良いと思います。

redis経由で認証する

では早速、上記の認証とredisを連携してみましょう。これらの機能によって、例えば以下のような実装が可能になります。

[program lang=’ruby’ escaped=’true’]

host    = "127.0.0.1"
port    = 6379

anp     = Apache::AuthnProvider.new
redis   = Apache::Redis.new(host, port)

if redis.get(anp.user) == anp.password
  Apache.return(Apache::AuthnProvider::AUTH_GRANTED)
else
  Apache.return(Apache::AuthnProvider::AUTH_DENIED)
end

[/program]

redis-cliへ事前に以下のように、ユーザとパスワードを登録しておきます。

[program lang=’actionscript3′ escaped=’true’]

$ redis-cli
redis 127.0.0.1:6379> set matsumoto_r password1
OK
redis 127.0.0.1:6379> set matsumotory password2
OK
redis 127.0.0.1:6379> quit
$ redis-cli
redis 127.0.0.1:6379> get matsumoto_r
"password1"
redis 127.0.0.1:6379> quit

[/program]

すると、Basic認証時のユーザとパスワードの組み合わせをRedisのKVSから抜き出すことができます。いい感じです。

さいごに

このように、Redisと認証を実装したことで、よりApacheをコントロールする事が楽しくなってきたと思います。プロキシ機能やrewrite機能、またはvhostの振り分けにRedis連携を使うとかなり便利になるだろうと考えています。今後は、mod_mrubyの機能をベースに、ngx_mrubyもできるだけ同等の機能を実装していきたいと思っています。

また、pull-requestはいちでもお待ちしていますので、Apacheの基本機能として今後これはいるだろうという機能があれば、mod_mrubyレポジトリまでいつでもpull-request下さい。

「mod_mrubyに認証とredis連携の機能追加した」への1件のフィードバック

コメントは受け付けていません。