riak: New module which enables storing sessions in Riak.

Thanks to David Gwynne for implementing this!

git-svn-id: http://simplesamlphp.googlecode.com/svn/trunk@3128 44740490-163a-0410-bde0-09ae8108e29a
This commit is contained in:
olavmrk 2012-06-29 09:21:17 +00:00
parent 525afd9368
commit a8a3386edb
6 changed files with 295 additions and 0 deletions

View File

@ -35,6 +35,7 @@ SimpleSAMLphp Documentation
* [Key rollover](./saml:keyrollover)
* [Creating authentication sources](./simplesamlphp-authsource)
* [Implementing custom username/password authentication](./simplesamlphp-customauth)
* [Storing sessions in Riak](./riak:simplesamlphp-riak)
Documentation on specific simpleSAMLphp modules:

View File

@ -0,0 +1,17 @@
<?php
/*
* The configuration of the riak Store module
*
* $Id$
*/
$config = array (
/*
* This module has the following config options and defaults.
*
* 'path' => 'riak-php-client/riak.php',
* 'host' => 'localhost',
* 'port' => 8098,
* 'bucket' => 'SimpleSAMLphp',
*/
);

View File

@ -0,0 +1,3 @@
This file indicates that the default state of this module
is disabled. To enable, create a file named enable in the
same directory as this file.

View File

@ -0,0 +1,118 @@
Riak Store module
=================
<!--
This file is written in Markdown syntax.
For more information about how to use the Markdown syntax, read here:
http://daringfireball.net/projects/markdown/syntax
-->
* Version: `$Id$`
<!-- {{TOC}} -->
Introduction
------------
The riak module implements a Store that can be used as a backend
for simpleSAMLphp session data like the phpsession, sql, or memcache
backends.
Preparations
------------
The obvious first step for using Riak as a backend is to install
and configure a Riak cluster for SimpleSAMLphp to use. Please refer
to the Riak documentation for this.
This module requires the use of a Riak backend that supports secondary
indexes. Refer to the Riak documentation on how to enable an
appropriate backend for use by this module. Currently the only
storage backend that supports secondary indexes is leveldb.
Next, you will need to install the Riak PHP Client library, available
from https://github.com/basho/riak-php-client.
Finally, you need to config SimpleSAMLphp to for the riak Store by
enabling the following modules:
1. cron
2. riak
The cron module allows you to do tasks regularly by setting up a
cronjob that calls hooks in simpleSAMLphp. This is required by the
riak module to remove expired entries in the store.
Enabling the riak module allows it to be loaded and used as a storage
backend.
You also need to copy the `config-templates` files from the cron
module above into the global `config/` directory.
$ cd /var/simplesamlphp
$ touch modules/cron/enable
$ cp modules/cron/config-templates/*.php config/
$ touch modules/riak/enable
$ cp modules/riak/config-templates/*.php config/
Configuring the cron module
---------------------------
At `/var/simplesamlphp/config`
$ vi module_cron.php
edit:
$config = array (
'key' => 'secret',
'allowed_tags' => array('daily', 'hourly', 'frequent'),
'debug_message' => TRUE,
'sendemail' => TRUE,
);
Then: With your browser go to => https://simplesamlphp_machine/simplesaml/module.php/cron/croninfo.php
And copy the cron's sugestion:
-------------------------------------------------------------------------------------------------------------------
Cron is a way to run things regularly on unix systems.
Here is a suggestion for a crontab file:
# Run cron [daily]
02 0 * * * curl --silent "https://simplesamlphp_machine/simplesaml/module.php/cron/cron.php?key=secret&tag=daily" > /dev/null 2>&1
# Run cron [hourly]
01 * * * * curl --silent "https://simplesamlphp_machine/simplesaml/module.php/cron/cron.php?key=secret&tag=hourly" > /dev/null 2>&1
# Run cron [frequent]
XXXXXXXXXX curl --silent "https://simplesamlphp_machine/simplesaml/module.php/cron/cron.php?key=secret&tag=frequent" > /dev/null 2>&1
Click here to run the cron jobs:
Run cron [daily]
Run cron [hourly]
Run cron [frequent]
-------------------------------------------------------------------------------------------------------------------
Add to CRON with
# crontab -e
Configuring the riak module
---------------------------
The riak module uses the following configuration options specified
in `config/module_riak.php`. The defaults are listed:
$config = array(
'path' => 'riak-php-client/riak.php',
'host' => 'localhost',
'port' => 8098,
'bucket' => 'SimpleSAMLphp',
);
Finally, the module can be specified as the Store in `config/config.php`
with the following setting:
'store.type' => 'riak:Store',

View File

@ -0,0 +1,53 @@
<?php
/*
* Copyright (c) 2012 The University of Queensland
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* Written by David Gwynne <dlg@uq.edu.au> as part of the IT
* Infrastructure Group in the Faculty of Engineering, Architecture
* and Information Technology.
*/
/**
* Hook to run a cron job.
*
* @param array &$croninfo Output
*/
function riak_hook_cron(&$croninfo) {
assert('is_array($croninfo)');
assert('array_key_exists("summary", $croninfo)');
assert('array_key_exists("tag", $croninfo)');
if ($croninfo['tag'] !== 'hourly') return;
try {
$store = new sspmod_riak_Store_Store();
$result = $store->bucket->indexSearch('expires', 'int',
1, time() - 30);
foreach ($result as $link) {
$link->getBinary()->delete();
}
SimpleSAML_Logger::info(sprintf("deleted %s riak key%s",
sizeof($result), sizeof($result) == 1 ? '' : 's'));
} catch (Exception $e) {
$message = 'riak threw exception: ' . $e->getMessage();
SimpleSAML_Logger::warning($message);
$croninfo['summary'][] = $message;
}
}

View File

@ -0,0 +1,103 @@
<?php
/*
* Copyright (c) 2012 The University of Queensland
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* Written by David Gwynne <dlg@uq.edu.au> as part of the IT
* Infrastructure Group in the Faculty of Engineering, Architecture
* and Information Technology.
*/
class sspmod_riak_Store_Store extends SimpleSAML_Store {
protected function __construct() {
$config = SimpleSAML_Configuration::getConfig('module_riak.php');
$path = $config->getString('path', 'riak-php-client/riak.php');
$host = $config->getString('host', 'localhost');
$port = $config->getString('port', 8098);
$bucket = $config->getString('bucket', 'simpleSAMLphp');
require_once($path);
$this->client = new RiakClient($host, $port);
$this->bucket = $this->client->bucket($bucket);
}
/**
* Retrieve a value from the datastore.
*
* @param string $type The datatype.
* @param string $key The key.
* @return mixed|NULL The value.
*/
public function get($type, $key) {
assert('is_string($type)');
assert('is_string($key)');
$v = $this->bucket->getBinary("$type.$key");
if (!$v->exists()) {
return (NULL);
}
$expires = $v->getIndex('Expires', 'int');
if (sizeof($expires) && (int)array_shift($expires) <= time()) {
$v->delete();
return (NULL);
}
return (unserialize($v->getData()));
}
/**
* Save a value to the datastore.
*
* @param string $type The datatype.
* @param string $key The key.
* @param mixed $value The value.
* @param int|NULL $expire The expiration time (unix timestamp), or NULL if it never expires.
*/
public function set($type, $key, $value, $expire = NULL) {
assert('is_string($type)');
assert('is_string($key)');
assert('is_null($expire) || (is_int($expire) && $expire > 2592000)');
$v = $this->bucket->newBinary("$type.$key", serialize($value), 'application/php');
if (!is_null($expire)) {
$v->addIndex("Expires", "int", $expire);
}
$v->store();
}
/**
* Delete a value from the datastore.
*
* @param string $type The datatype.
* @param string $key The key.
*/
public function delete($type, $key) {
assert('is_string($type)');
assert('is_string($key)');
$v = $this->bucket->getBinary("$type.$key");
if (!$v->exists()) {
return;
}
$v->delete();
}
}