- [kopano](src/kopano) Load Kopano LDAP attributes using `LDAP_PROPMAP=`.

master
mlan 2020-11-19 20:02:46 +01:00
parent f13d2d2329
commit 611d4ae694
7 changed files with 122 additions and 26 deletions

View File

@ -1,6 +1,7 @@
# 1.2.4
- [kopano](src/kopano) Now, use man pages and sample config files to find valid keys to match envvar.
- [kopano](src/kopano) Load Kopano LDAP attributes using `LDAP_PROPMAP=`.
# 1.2.3

View File

@ -260,27 +260,25 @@ When the `ATTACHMENT_STORAGE` option is `ATTACHMENT_STORAGE=files`, this option
When creating the SQL container you can use environment variables to initiate it. For example, `MYSQL_ROOT_PASSWORD=topsecret`, `MYSQL_DATABASE=kopano`, `MYSQL_USER=kopano` and `MYSQL_PASSWORD=verysecret`.
## User authentication `USER_PLUGIN`
## User management `USER_PLUGIN`
Kopano supports three different ways to manage user authentication. Use the `USER_PLUGIN` environment variable to select the source of the user base. Possible values are: `db` (default), `ldap` and `unix`.
Kopano supports three different plugins for user management. Use the `USER_PLUGIN` environment variable to select the source of the user base. Possible values are: `db` (default), `ldap` and `unix`.
`db`: Retrieve the users from the Kopano database. Use the kopano-admin tool to create users and groups. There are no additional settings for this plug-in.
`db`: Retrieve the users from the Kopano database. Use the `kopano-admin` tool to create users and groups. There are no additional settings for this plug-in.
`ldap`: Retrieve the users and groups information from an LDAP server. All additional LDAP settings are needed see below
`ldap`: Retrieve the users and groups information from an LDAP directory server. Additional LDAP settings are needed, see below.
`unix`: Retrieve the users and groups information from the Linux password files. This option is probably not interesting here.
### LDAP authentication
### Accessing an LDAP directory server
An LDAP server with user accounts configured to be used with Kopano is needed, but how to set one up is out of our scope here, instead see: [Kopano Knowledge Base/Install and optimize OpenLDAP for use with Kopano Groupware Core](https://kb.kopano.io/display/WIKI/Install+and+optimize+OpenLDAP+for+use+with+Kopano+Groupware+Core).
The `USER_PLUGIN=ldap` retrieves user information from an LDAP directory server. A brief description of how that is achieved is described in [Setup an LDAP directory server](#setup-an-ldap-directory-server). Once the LDAP directory server is up and running, the `mlan/kopano` container can be configured to use it using environment variables.
Once the LDAP server is up and running, the `mlan/kopano` container can be configured to use it using environment variables. In addition to the variables discussed below also set `USER_PLUGIN=ldap`.
#### `LDAP_URI`
#### Host address `LDAP_URI`
Specifies the URI of one or more LDAP server(s) to use, without any DN portion, such as `ldap://server:389/`, `ldaps://server:636/` or `ldapi:///`. Defaults: `LDAP_URI=ldap://localhost:389/`.
The historic directives `LDAP_HOST`, `LDAP_PORT`, `LDAP_PROTOCOL` are no longer supported (8.7.85).
Note that. the historic directives `LDAP_HOST`, `LDAP_PORT`, `LDAP_PROTOCOL` are no longer supported (8.7.85).
#### `LDAP_SEARCH_BASE`
@ -298,7 +296,11 @@ This variable determines what defines a valid Kopano group. Default: `LDAP_GROUP
Adds an extra filter to the user search. Default `LDAP_USER_SEARCH_FILTER=`
Hint: Use the `kopanoAccount` attribute in the filter to differentiate between non-kopano and kopano users.
Hint: Use the `kopanoAccount` attribute in the filter to differentiate between non-Kopano and Kopano users.
### Kopano LDAP attributes `LDAP_PROPMAP`
The Kopano services needs to know which of the users LDAP attributes, like addresses, phone numbers and company information, to use. This information is defined in the `propmap` file, which is included in the Kopano installation files here `/usr/share/kopano/ldap.propmap.cfg`. When using `USER_PLUGIN=ldap` this LDAP `propmap` file is used by the Kopano services by setting `LDAP_PROPMAP=` to an empty string. Optionally you can use another file, for example`LDAP_PROPMAP=/etc/kopano/ldap.propmap.cfg`. If no file can be found there the installed one will be copied there.
## Enabling IMAP, POP3 and ICAL
@ -445,6 +447,50 @@ Prior to Kopano WebApp version 5.0.0 the parameter was `define("INSECURE_COOKIES
Here some topics relevant for arranging a mail server are presented.
## Setup an LDAP directory server
A [Directory Server Agent (DSA)](https://en.wikipedia.org/wiki/Directory_System_Agent) is used to store, organize and present data in a key-value type format. Typically, directories are optimized for lookups, searches, and read operations over write operations, so they function extremely well for data that is referenced often but changes infrequently.
The [Lightweight Directory Access Protocol (LDAP)](https://en.wikipedia.org/wiki/Lightweight_Directory_Access_Protocol), is an open protocol used to store and retrieve data from a hierarchical directory structure. Commonly used to store information about an organization and its assets and users.
[OpenLDAP](https://www.openldap.org/) is a cross platform LDAP based directory service. [Active Directory (AD)](https://en.wikipedia.org/wiki/Active_Directory) is a [directory service](https://en.wikipedia.org/wiki/Directory_service) developed by [Microsoft](https://en.wikipedia.org/wiki/Microsoft) for [Windows domain](https://en.wikipedia.org/wiki/Windows_domain) networks which also uses LDAP.
There are many dockerized OpenLDAP server to choose from. One such example is [mlan/openldap](https://github.com/mlan/docker-openldap).
### LDAP user entry
The data itself in an LDAP system is mainly stored in elements called attributes. Attributes are basically key-value pairs. Unlike in some other systems, the keys have predefined names which are dictated by the objectClasses selected for an entry. An entry is basically a collection of attributes under a name used to describe something; a user for example.
```yaml
dn: uid=demo,ou=users,dc=example,dc=com
objectclass: inetOrgPerson
uid: demo
```
### Kopano LDAP schema
The Kopano LDAP schema defines additional objectClasses and attributes. These allow the Kopano services, access for example, to controlled on per-user basis. More information on available attributes can be find here, [Fine-tuning user configuration](https://documentation.kopano.io/kopanocore_administrator_manual/configure_kc_components.html?highlight=propmap#fine-tuning-user-configuration).
```shell
dn: uid=demo,ou=users,dc=example,dc=com
objectClass: top
objectClass: inetOrgPerson
objectClass: kopano-user
objectClass: posixAccount
cn: demo
sn: demo
uid: demo
mail: demo@example.com
uidNumber: 1234
gidNumber: 1234
homeDirectory: /home/demo
telephoneNumber: 0123 123456789
title: MCP
kopanoEnabledFeatures: imap pop3
```
The schema needs to be added to the directory server. The Kopano installation files include the LDAP schema and can be found here `/usr/share/doc/kopano/kopano.ldif.gz`. For more details, see: [Kopano Knowledge Base/Install and optimize OpenLDAP for use with Kopano Groupware Core](https://kb.kopano.io/display/WIKI/Install+and+optimize+OpenLDAP+for+use+with+Kopano+Groupware+Core).
## Kopano WebApp HTTP access
The distribution installation of `kopano-webapp` only allow HTTPS access. The `mlan/kopano` image updates the configuration to [`define("SECURE_COOKIES", false);`](https://documentation.kopano.io/webapp_admin_manual/config.html#secure-cookies) in `/etc/kopano/webapp/config.php` also allowing HTTP access. This can be useful when arranging the `mlan/kopano` container behind a reverse proxy, like [Traefik](https://doc.traefik.io/traefik/), which then does the enforcement of HTTPS. Also see [`MIGRATE_CONFIG=1` Rejected insecure request as configuration for SECURE_COOKIES is true](#migrate_config1-rejected-insecure-request-as-configuration-for-secure_cookies-is-true).

View File

@ -13,7 +13,7 @@ variables:
test: all-test_quiet mta-test_smtp
init: auth-init db-init mta-init app-init
init: up auth-init db-init mta-init app-init
ps:
docker-compose ps
@ -24,7 +24,7 @@ up:
down:
docker-compose down
destroy:
destroy: auth-gui-down
docker-compose down -v
config:
@ -73,7 +73,7 @@ wait_%:
web:
firefox localhost:8008 &
auth-init: auth-up wait_11 auth-mod_hash auth-mod_index auth-add_user
auth-init: wait_11 auth-mod_hash auth-mod_index auth-add_schema auth-add_user
auth-show_conf:
docker-compose exec auth ldap search -b cn=config "(cn=config)"
@ -90,7 +90,7 @@ auth-show_cat1:
docker-compose exec auth slapcat -n1
auth-add_user:
printf "dn: ou=$(LDAP_USEROU),$(LDAP_BASE)\nchangetype: add\nobjectClass: organizationalUnit\nobjectClass: top\nou: $(LDAP_USEROU)\n\ndn: ou=$(LDAP_GROUPOU),$(LDAP_BASE)\nchangetype: add\nobjectClass: organizationalUnit\nobjectClass: top\nou: $(LDAP_GROUPOU)\n\ndn: uid=$(LDAP_TEST_USER),ou=$(LDAP_USEROU),$(LDAP_BASE)\nchangetype: add\nobjectClass: top\nobjectClass: inetOrgPerson\nobjectClass: $(LDAP_USEROBJ)\ncn: $(LDAP_TEST_USER)\nsn: $(LDAP_TEST_USER)\nuid: $(LDAP_TEST_USER)\nmail: $(LDAP_TEST_USER)@$(MAIL_DOMAIN)\nuidNumber: 1234\ngidNumber: 1234\nhomeDirectory: /home/$(LDAP_TEST_USER)\nuserPassword: $(LDAP_TEST_PASSWD)\n" \
printf "dn: ou=$(LDAP_USEROU),$(LDAP_BASE)\nchangetype: add\nobjectClass: organizationalUnit\nobjectClass: top\nou: $(LDAP_USEROU)\n\ndn: ou=$(LDAP_GROUPOU),$(LDAP_BASE)\nchangetype: add\nobjectClass: organizationalUnit\nobjectClass: top\nou: $(LDAP_GROUPOU)\n\ndn: uid=$(LDAP_TEST_USER),ou=$(LDAP_USEROU),$(LDAP_BASE)\nchangetype: add\nobjectClass: top\nobjectClass: inetOrgPerson\nobjectClass: kopano-user\nobjectClass: $(LDAP_USEROBJ)\ncn: $(LDAP_TEST_USER)\nsn: $(LDAP_TEST_USER)\nuid: $(LDAP_TEST_USER)\nmail: $(LDAP_TEST_USER)@$(MAIL_DOMAIN)\nuidNumber: 1234\ngidNumber: 1234\nhomeDirectory: /home/$(LDAP_TEST_USER)\nuserPassword: $(LDAP_TEST_PASSWD)\ntelephoneNumber: 0123 123456789\ntitle: MCP\nkopanoEnabledFeatures: imap pop3\n" \
| docker-compose exec -T auth ldap modify
auth-mod_index:
@ -101,7 +101,21 @@ auth-mod_hash:
printf "dn: olcDatabase={-1}frontend,cn=config\nchangetype: modify\nadd: olcPasswordHash\nolcPasswordHash: {CRYPT}\n\ndn: cn=config\nchangetype: modify\nadd: olcPasswordCryptSaltFormat\nolcPasswordCryptSaltFormat: \$$6\$$%%.16s\n" \
| docker-compose exec -T auth ldap modify
mta-init: mta-up
auth-add_schema:
docker-compose exec app zcat /usr/share/doc/kopano/kopano.ldif.gz \
| docker-compose exec -T auth ldapadd -H ldapi://%2Fvar%2Frun%2Fopenldap%2Fldapi/ -Y EXTERNAL
auth-gui-up:
docker run -d --rm --name auth-gui --network demo_backend \
-p 127.0.0.1:8001:80 -e PHPLDAPADMIN_LDAP_HOSTS=auth \
-e PHPLDAPADMIN_HTTPS=false osixia/phpldapadmin || true
sleep 2
firefox localhost:8001 &
auth-gui-down:
docker stop auth-gui || true
mta-init:
mta-bayes:
docker-compose exec mta sh -c 'rm -f bayesian.database.gz && wget http://artinvoice.hu/spams/bayesian.database.gz && gunzip bayesian.database.gz && sa-learn --restore bayesian.database && chown -R amavis: /var/amavis/.spamassassin && rm -rf bayesian.database'
@ -177,12 +191,12 @@ mta-test_rimap:
mta-test_ldap: mta-debugtools
docker-compose exec mta ldapsearch -H ldap://auth:389 -xLLL -s base namingContexts
db-init: db-up
db-init:
db-test:
docker-compose exec db mysqlshow -u $(MYSQL_USER) $(MYSQL_DATABASE) -p$(MYSQL_PASSWORD)
app-init: app-up wait_12 app-public_store
app-init: wait_12 app-public_store
app-debugtools:
docker-compose exec app apt-get update
@ -230,7 +244,7 @@ app-test_tls: app-hostaddr
docker run --rm -it --network demo_backend drwetter/testssl.sh app:993 || true
app-show_user1:
docker-compose exec app kopano-admin -l
docker-compose exec app kopano-admin --details $(LDAP_TEST_USER)
app-show_user2: app-debugtools
docker-compose exec app ldapsearch -H ldap://auth:389 -xLLL -b $(LDAP_BASE) '*'

View File

@ -25,6 +25,7 @@ services:
- LDAP_SEARCH_BASE=${LDAP_BASE-dc=example,dc=com}
- LDAP_USER_TYPE_ATTRIBUTE_VALUE=${LDAP_USEROBJ-posixAccount}
- LDAP_GROUP_TYPE_ATTRIBUTE_VALUE=${LDAP_GROUPOBJ-posixGroup}
- LDAP_PROPMAP=
- MYSQL_DATABASE=${MYSQL_DATABASE-kopano}
- MYSQL_USER=${MYSQL_USER-kopano}
- MYSQL_PASSWORD=${MYSQL_PASSWORD-secret}

View File

@ -17,7 +17,7 @@ DOCKER_CONF_DIR2=${DOCKER_CONF_DIR2-/usr/share/z-push}
DOCKER_MAN5_DIR=${DOCKER_MAN5_DIR-/usr/share/man/man5/}
DOCKER_APPL_SSL_CERT=${DOCKER_APPL_SSL_CERT-$DOCKER_APPL_SSL_DIR/cert.pem}
DOCKER_APPL_SSL_KEY=${DOCKER_APPL_SSL_KEY-$DOCKER_APPL_SSL_DIR/priv_key.pem}
DOCKER_LDAP_PMAP_FILE=${DOCKER_LDAP_PMAP_FILE-/usr/share/kopano/ldap.propmap.cfg}
sqlstate_cfg_file=$DOCKER_CONF_DIR2/backend/sqlstatemachine/config.php
zpush_cfg_file=$DOCKER_CONF_DIR2/config.php
webapp_cfg_file=$DOCKER_CONF_DIR1/webapp/config.php
@ -45,18 +45,15 @@ kopano_apply_envvars_zpush() {
}
kopano_apply_envvars_cfg() {
local cfg_file=$DOCKER_CONF_DIR1/$1.cfg
local man_file=$DOCKER_MAN5_DIR/kopano-$1.cfg.5.gz
local cfg_file=$(kopano_gen_filename_cfg $1)
local man_file=$(kopano_gen_filename_man $1)
if [ -f $man_file ]; then
local env_vars="$(kopano_get_envvars_man $man_file)"
if [ -e $cfg_file ]; then
mv -f $cfg_file $cfg_file.orig
fi
for env_var in $env_vars; do
if [ -n "${!env_var+x}" ]; then
dc_log 5 "Setting ${env_var,,} = ${!env_var} in $cfg_file"
echo ${env_var,,} = ${!env_var} >> $cfg_file
fi
kopano_set_envvars_cfg $cfg_file $env_var
done
else
dc_log 4 "Could not find $man_file"
@ -77,6 +74,24 @@ kopano_apply_envvars_php() {
fi
}
#
# kopano_set_envvars_cfg </path/file.cfg> <envvar name> [explicit parameter name]
#
kopano_set_envvars_cfg() {
local cfg_file=$1
local env_var=$2
local cfg_par="${3-$env_var =}"
if [ -n "${!env_var+x}" ]; then
dc_log 5 "Setting ${cfg_par,,} ${!env_var} in $cfg_file"
echo ${cfg_par,,} ${!env_var} >> $cfg_file
fi
}
#
# Helpers
#
kopano_gen_filename_man() { echo $DOCKER_MAN5_DIR/kopano-$1.cfg.5.gz ;}
kopano_gen_filename_cfg() { echo $DOCKER_CONF_DIR1/$1.cfg ;}
kopano_get_envvars_man() { zcat $1 | sed -r "/^\.SS/!d;{s/^\.SS (.*)/\U\1/g;s/,//g}" | sort -u ;}
kopano_get_envvars_php() { sed -nr "/define\(/s/.*define\(['\"](.*)['\"], .*/\1/p" $1 | sort -u ;}
@ -110,3 +125,20 @@ kopano_generate_tls_cert() {
dc_tls_setup_selfsigned_cert $DOCKER_APPL_SSL_CERT $DOCKER_APPL_SSL_KEY
fi
}
#
# LDAP directives
#
kopano_apply_envvar_propmap() {
local cfg_file=$(kopano_gen_filename_cfg ldap)
local env_var=LDAP_PROPMAP
if [ -n "${!env_var+x}" ]; then
if [ -z "${!env_var}" ]; then
typeset "$env_var=$DOCKER_LDAP_PMAP_FILE"
elif [ ! -e "${!env_var}" ]; then
dc_log 5 "No ${!env_var} so copying $DOCKER_LDAP_PMAP_FILE there."
cp -f $DOCKER_LDAP_PMAP_FILE ${!env_var}
fi
kopano_set_envvars_cfg $cfg_file $env_var '!propmap'
fi
}

View File

@ -17,4 +17,5 @@ if dc_is_unlocked; then
kopano_apply_envvars_core
kopano_apply_envvars_webapp
kopano_apply_envvars_zpush
kopano_apply_envvar_propmap
fi

View File

@ -61,6 +61,7 @@ APP_ENV ?= $(NET_ENV) $(SQL_ENV) \
-e LDAP_SEARCH_BASE=$(LDAP_BAS) \
-e LDAP_USER_TYPE_ATTRIBUTE_VALUE=$(LDAP_UOB) \
-e LDAP_GROUP_TYPE_ATTRIBUTE_VALUE=$(LDAP_GOU) \
-e LDAP_PROPMAP= \
-e IMAP_LISTEN=*:143 \
-e POP3_LISTEN=*:110 \
-e ICAL_LISTEN=*:8080 \