summaryrefslogtreecommitdiffstats
path: root/doc/wiki/AuthDatabase.Dict.txt
diff options
context:
space:
mode:
Diffstat (limited to 'doc/wiki/AuthDatabase.Dict.txt')
-rw-r--r--doc/wiki/AuthDatabase.Dict.txt391
1 files changed, 391 insertions, 0 deletions
diff --git a/doc/wiki/AuthDatabase.Dict.txt b/doc/wiki/AuthDatabase.Dict.txt
new file mode 100644
index 0000000..4a4405a
--- /dev/null
+++ b/doc/wiki/AuthDatabase.Dict.txt
@@ -0,0 +1,391 @@
+Key-value authentication database
+=================================
+
+Key-value databases can be used as auth backends. They probably should be used
+only for caching in front of e.g. SQL auth backends. Iteration is supported if
+the underlying dict provider supports iteration. See <Dictionary.txt> for list
+of supported databases.
+
+Auth configuration
+------------------
+
+'dovecot.conf':
+
+---%<-------------------------------------------------------------------------
+passdb {
+ driver = dict
+ args = /etc/dovecot/dovecot-dict-auth.conf
+}
+userdb {
+ driver = dict
+ args = /etc/dovecot/dovecot-dict-auth.conf
+}
+---%<-------------------------------------------------------------------------
+
+Dict configuration
+------------------
+
+---%<-------------------------------------------------------------------------
+uri = redis:host=127.0.0.1:port=6379
+
+# Dictionary URI
+#uri =
+
+# Default password scheme
+default_pass_scheme = MD5
+
+# Username iteration prefix. Keys under this are assumed to contain usernames.
+iterate_prefix = userdb/
+
+# Should iteration be disabled for this userdb? If this userdb acts only as a
+# cache there's no reason to try to iterate the (partial & duplicate) users.
+#iterate_disable = no
+
+# The example here shows how to do multiple dict lookups and merge the replies.
+# The "passdb" and "userdb" keys are JSON objects containing key/value pairs,
+# for example: { "uid": 1000, "gid": 1000, "home": "/home/user" }
+
+key passdb {
+ key = passdb/%u
+ format = json
+}
+key userdb {
+ key = userdb/%u
+ format = json
+}
+key quota {
+ key = userdb/%u/quota # or e.g. quota/%{userdb:quota_class}
+ #format = value
+ # The default_value is used if the key isn't found. If default_value setting
+ # isn't specified at all (even as empty), the passdb/userdb lookup fails with
+ # "user doesn't exist".
+ default_value = 100M
+}
+
+# Space separated list of keys whose values contain key/value paired objects.
+# All the key/value pairs inside the object are added as passdb fields.
+# This can only be used for JSON formatted values.
+passdb_objects = passdb
+
+#passdb_fields {
+#}
+
+# Userdb key/value object list.
+userdb_objects = userdb
+
+userdb_fields {
+ # dict:<key> refers to key names
+ quota_rule = *:storage=%{dict:quota}
+
+ # dict:<key>.<objkey> refers to the objkey inside (JSON) object
+ mail = maildir:%{dict:userdb.home}/Maildir
+}
+---%<-------------------------------------------------------------------------
+
+Example values
+--------------
+
+The value formats are either "value" that contains a direct value, or "json".
+For example userdb lookup should return something like:
+
+---%<-------------------------------------------------------------------------
+{ "uid": 123, "gid": 123, "home": "/home/username" }
+---%<-------------------------------------------------------------------------
+
+dict proxying
+-------------
+
+It may be useful to do the lookups via the "dict" or "dict-async" service. For
+example:
+
+'dovecot.conf':
+
+---%<-------------------------------------------------------------------------
+dict {
+ cassandra-userdb = cassandra:/etc/dovecot/dovecot-dict-userdb-cql.conf.ext
+}
+---%<-------------------------------------------------------------------------
+
+'dovecot-dict-auth.conf.ext':
+
+---%<-------------------------------------------------------------------------
+uri = proxy:dict-async:cassandra-userdb
+iterate_disable = yes
+# The _key and _path suffixes are not necessary, they're just here to help
+# understand how to match them between different parts of the configuration.
+key email_key {
+ key = userdb/email_path/%u
+}
+key displayname_key {
+ key = userdb/displayname_path/%u
+}
+userdb_fields {
+ # these fields will be visible as %{userdb:u_email} and
+%{userdb:u_displayname}
+ u_email = %{dict:email_key}
+ u_displayname = %{dict:displayname_key}
+}
+---%<-------------------------------------------------------------------------
+
+'dovecot-dict-userdb-cql.conf.ext':
+
+---%<-------------------------------------------------------------------------
+driver = cassandra
+connect = host=127.0.0.1 dbname=email_users
+
+# SELECT displayname FROM user_profile WHERE id = %u
+map {
+ # pattern must match the "key" path, except with added shared/ prefix. %u
+gets caught into $username
+ pattern = shared/userdb/displayname_path/$username
+ table = user_profile
+ value_field = displayname
+ value_type = string
+ fields {
+ id = $username
+ }
+}
+
+# SELECT email FROM user_profile WHERE id = %u
+map {
+ pattern = shared/userdb/email_path/$username
+ table = user_profile
+ value_field = email
+ value_type = string
+ fields {
+ id = $username
+ }
+}
+---%<-------------------------------------------------------------------------
+
+Complete example for authenticating via the CDB dictionary
+----------------------------------------------------------
+
+This example uses the CDB dictionary to store the userdb and passdb.
+
+Auth configuration
+------------------
+
+'dovecot.conf':
+
+---%<-------------------------------------------------------------------------
+# Access to the CDB has to go through a dict process.
+dict {
+ auth = cdb:/etc/dovecot/auth.cdb
+}
+
+passdb {
+ driver = dict
+ args = /etc/dovecot/dovecot-cdb.conf
+}
+
+userdb {
+ driver = dict
+ args = /etc/dovecot/dovecot-cdb.conf
+}
+---%<-------------------------------------------------------------------------
+
+Dict configuration
+------------------
+
+The CDB dictionary doesn't support iteration yet.
+
+'dovecot-cdb.conf':
+
+---%<-------------------------------------------------------------------------
+uri = proxy::auth
+
+# FIXME: obsolete configuration - should use the key { .. } instead
+password_key = passdb/%u
+user_key = userdb/%u
+# iterate_prefix = userdb/ # no yet supported
+iterate_disable = yes
+
+default_pass_scheme = BLF-CRYPT
+---%<-------------------------------------------------------------------------
+
+Complete example for authenticating via a UNIX socket
+-----------------------------------------------------
+
+The Dict auth backend can be used to query a local UNIX socket for users. This
+can be handy for accessing user databases which would otherwise only be
+accessible via the <CheckPassword> [AuthDatabase.CheckPassword.txt] backend and
+a scripting language.
+
+When given a <"proxy:"> [Quota.Dict.txt] URL the Dict backend speaks a simple
+protocol over a UNIX socket. The protocol is defined in
+'src/lib-dict/dict-client.h' (GitHub
+[https://github.com/dovecot/core/blob/master/src/lib-dict/dict-client.h]).
+
+Auth configuration
+------------------
+
+'dovecot.conf':
+
+---%<-------------------------------------------------------------------------
+passdb {
+ driver = dict
+ args = /etc/dovecot/dovecot-dict-auth.conf
+}
+userdb {
+ # optional
+ driver = prefetch
+}
+userdb {
+ driver = dict
+ args = /etc/dovecot/dovecot-dict-auth.conf
+}
+---%<-------------------------------------------------------------------------
+
+Dict configuration
+------------------
+
+The last "dictionary name" ("somewhere") argument is redundant here.
+
+'/etc/dovecot/dovecot-dict-auth.conf.ext':
+
+---%<-------------------------------------------------------------------------
+uri = proxy:/var/run/auth_proxy_dovecot/socket:somewhere
+
+# FIXME: obsolete configuration - should use the key { .. } instead
+password_key = passdb/%u
+user_key = userdb/%u
+iterate_disable = yes
+#default_pass_scheme = plain
+---%<-------------------------------------------------------------------------
+
+Server process for answering Dict lookups
+-----------------------------------------
+
+The server process listening on '/var/run/auth_proxy_dovecot/socket' can be
+written in any language.Here's an example in Perl:
+
+---%<-------------------------------------------------------------------------
+package AuthProxyDovecot;
+use base qw( Net::Server::PreFork );
+
+use strict;
+use warnings;
+
+use JSON::XS;
+
+AuthProxyDovecot->run() or die "Could not initialize";
+
+sub default_values
+{
+ return {
+ port => '/var/run/auth_proxy_dovecot/socket|unix',
+
+ log_level => 2,
+ log_file => 'Sys::Syslog',
+ syslog_logsock => 'unix',
+ syslog_ident => 'auth_proxy_dovecot',
+ syslog_facility => 'daemon',
+
+ background => 1,
+ setsid => 1,
+ pid_file => '/var/run/auth_proxy_dovecot.pid',
+
+ user => 'root',
+ group => 'root',
+
+ max_spare_servers => 2,
+ min_spare_servers => 1,
+ min_servers => 2,
+ max_servers => 10,
+
+ };
+} ## end sub default_values
+
+##################################################
+
+sub process_request {
+ my $self = shift;
+
+ my %L_handler = (
+ passdb => sub {
+ my ($arg) = @_;
+ my $ret = {
+ password => '$1$JrTuEHAY$gZA1y4ElkLHtnsrWNHT/e.',
+ userdb_home => "/home/username/",
+ userdb_uid => 1000,
+ userdb_gid => 1000,
+ };
+ return $ret;
+ },
+ userdb => sub {
+ my ($arg) = @_;
+ my $ret = {
+ home => "/home/username/",
+ uid => 1000,
+ gid => 1000,
+ };
+ return $ret;
+ },
+ );
+
+ # protocol from src/lib-dict/dict-client.h
+ my $json = JSON::XS->new;
+
+ eval {
+ my $ret;
+ # Dict protocol is multiline... go through the lines.
+ while (<STDIN>) {
+ $self->log(2, "Got request: $_");
+ chomp;
+ my $cmd = substr($_,0,1);
+ next if $cmd eq 'H'; # "hello", skip this line, assume it's ok
+ die "Protocol error: Bad command $cmd" unless ($cmd eq 'L');
+ # Process request
+
+ my ($namespace,$type,$arg) = split ('/',substr($_,1),3);
+
+ if ($namespace eq 'shared') {
+ my $f = $L_handler{$type};
+
+ if (defined $f && defined $arg) {
+ $ret = $f->($arg);
+ }
+ else {
+ die 'Protocol error: Bad arg';
+ }
+ }
+ else {
+ die 'Protocol error: Bad namespace'
+ }
+ last; # Got an "L" , now respond.
+ }
+ if ($ret) {
+ my $json = JSON::XS->new->indent(0)->utf8->encode($ret);
+ $self->log(3,"O:$json");
+ print "O".$json."\n";
+ }
+ else {
+ $self->log(3,"NOUSER");
+ print "N\n";
+ }
+ 1;
+ } or do {
+ $self->log(2, "Error: $@");
+ print "F\n";
+ };
+}
+
+sub pre_loop_hook {
+ my $self = shift;
+
+ $self->log(1, 'Starting server');
+}
+
+sub pre_server_close_hook {
+ my $self = shift;
+
+ $self->log(1, 'Server is shut down');
+}
+
+1;
+
+__END__
+---%<-------------------------------------------------------------------------
+
+(This file was created from the wiki on 2019-06-19 12:42)