Installation¶
Requirements¶
Keyper is a docker container with alpine Linux as its base. To run Keyper you need to have docker running on your server. You can also use podman, which is bundled natively with RHEL and its variants, and it does not require any running daemon.
Quickstart¶
To run docker image using docker cli:
$ docker run -p 8080:80 -p 8443:443 -p 2389:389 -p 2636:636 --hostname <hostname> --env FLASK_CONFIG=prod -it dbsentry/keyper
To run the docker image using podman cli:
$ podman run -p 8080:80 -p 8443:443 -p 2389:389 -p 2636:636 --hostname <hostname> --env FLASK_CONFIG=prod -it docker.io/dbsentry/keyper
Either command starts a new container with keyper processes (OpenLDAP, Gunicorn, Nginx).
Important
The above commands are for demo only and start a new container with LDAP server storing data within the container. That means on re-start, data would not persist. If you want data to persist, start the container with appropriate command line parameters. Refer to the documentation.
Important
By default, this image creates an LDAP server for the company Example Inc and the domain keyper.example.org. By default, all passwords are set to superdupersecret. All the default settings can be changed by passing parameters to the docker/podman command line or using a parameter config file.
Ports¶
Keyper starts services on the following ports:
Service |
Port(s) |
---|---|
slapd |
389, 636 |
gunicorn |
8000 |
nginx |
80, 443 |
You must map nginx ports to your host port to access keyper web console.
Environment Variables¶
Following environment variables can be set as part of the docker CLI:
Environment Variable |
Description |
Default |
---|---|---|
LDAP_PORT |
LDAP bind port |
389 |
LDAPS_PORT |
LDAPS bind port |
636 |
LDAP_ORGANIZATION_NAME |
Name of the Organization |
Example Inc. |
LDAP_DOMAIN |
LDAP Domain |
keyper.example.org |
LDAP_ADMIN_PASSWORD |
Admin password on LDAP |
superdupersecret |
LDAP_TLS_CA_CRT_FILENAME |
CA Cert File Name |
ca.crt |
LDAP_TLS_CRT_FILENAME |
Cert File Name |
server.crt |
LDAP_TLS_KEY_FILENAME |
Cert Key File Name |
server.key |
LDAP_TLS_DH_PARAM_FILENAME |
DH Param File Name |
dhparam.pem |
LDAP_TLS_CIPHER_SUITE |
Default Cipher Suite |
TLSv1.2:HIGH:!aNULL:!eNULL |
FLASK_CONFIG |
Flask Config (dev/prod) |
prod |
HOSTNAME |
Hostname |
<docker generated> |
NGINX_UID |
nginx user UID |
10080 |
NGINX_GID |
nginx user GID |
10080 |
SSH_CA_HOST_KEY |
CA KEY for Host Cert |
ca_host_key |
SSH_CA_USER_KEY |
CA KEY for User Cert |
ca_user_key |
SSH_CA_KEY_TYPE |
CA Key type (rsa/dsa/ ecdsa/ed25519) |
rsa |
SSH_CA_KRL_FILE |
CA KRL File |
ca_krl |
SSH_CA_TMP_DELETE_FLAG |
CA delete temp files |
True |
Important
We recommend setting the HOSTNAME parameter on CLI. By default, the container creates a self-signed SSL certificate per the hostname. We recommend you use a CA issued certificate in production.
Important
Since version 0.2.1 all services (i.e. OpenLDAP, Gunicorn, and Nginx run as user nginx.
Data Persistence¶
By default, keyper creates openldap database within container under /var/lib/openldap/openldap-data and /etc/openldap/slapd.d. For data to persist after a restart, we need to present local docker volumes as a parameter. Something like this:
$ docker volume create slapd.d
$ docker volume create openldap-data
$ docker run -p 80:80 -p 443:443 -p 389:389 -p 636:636 --hostname <hostname> --mount source=slapd.d,target=/etc/openldap/slapd.d --mount source=openldap-data,target=/var/lib/openldap/openldap-data -it dbsentry/keyper
For more information about docker data volume, please refer to:
On subsequent starts, keyper checks for the existence of files in /etc/openldap/slapd.d and /var/lib/openldap/openldap-data, and if it finds any files there, it assumes an existing database and starts the slapd service. Otherwise, it creates a new LDAP database with the password specified via environment variable LDAP_ADMIN_PASSWORD.
Services¶
Keyper is built using alipne Linux as its base. When started, it launches three services:
slapd: LDAP server
gunicorn: REST API developed using python flask
nginx: Frontend Web Application developed using VueJS
Keyper starts these services using runit init scheme. runit is a cross-platform Unix init scheme with service supervision. It fits perfectly within a docker container framework keeping the size of the container small.
To manage these services, connect to your keyper docker container and issue following commands:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f439774327a5 dbsentry/keyper "/container/tools/run" 16 hours ago Up 16 hours 0.0.0.0:8080->80/tcp, 0.0.0.0:2389->389/tcp, 0.0.0.0:8443->443/tcp, 0.0.0.0:2636->636/tcp priceless_clarke
66d33bbdd32c jenkinsci/blueocean "/sbin/tini -- /usr/…" 2 weeks ago Up 2 weeks 0.0.0.0:50000->50000/tcp, 0.0.0.0:8000->8080/tcp jenkins-blueocean
$ docker exec -it f439774327a5 /bin/sh
/ #
/ # export SVDIR=/container/run/process
/ # cd /container/run/process
/container/run/process # sv status *
run: gunicorn: (pid 61) 56789s
run: nginx: (pid 62) 56789s
run: slapd: (pid 63) 56789s
/container/run/process # sv status slapd
run: slapd: (pid 63) 56803s
/container/run/process # sv status gunicorn
run: gunicorn: (pid 61) 56807s
/container/run/process # sv status nginx
run: nginx: (pid 62) 56811s
To stop a service:
/container/run/process # sv stop nginx
ok: down: nginx: 1s, normally up
To start a service:
/container/run/process # sv start nginx
ok: run: nginx: (pid 122) 0s
To restart a service:
/container/run/process # sv restart nginx
ok: run: nginx: (pid 116) 0s
/container/run/process #
If any of the above service crashes or terminates. runit being a supervisor starts it again:
/container/run/process # ps -ef
PID USER TIME COMMAND
1 root 0:00 {run} /usr/bin/python3 -u /container/tools/run
57 root 0:00 /sbin/runsvdir -P /container/run/process
58 root 0:00 runsv gunicorn
59 root 0:00 runsv nginx
60 root 0:00 runsv slapd
61 root 0:06 {gunicorn} /var/www/keyper/env/bin/python3 /var/www/keyper/env/bin/gunicorn -w 4 ap
63 ldap 0:00 /usr/sbin/slapd -h ldap:/// ldaps:/// -u ldap -g ldap -d 256
71 nginx 0:00 {gunicorn} /var/www/keyper/env/bin/python3 /var/www/keyper/env/bin/gunicorn -w 4 ap
72 nginx 0:00 {gunicorn} /var/www/keyper/env/bin/python3 /var/www/keyper/env/bin/gunicorn -w 4 ap
73 nginx 0:00 {gunicorn} /var/www/keyper/env/bin/python3 /var/www/keyper/env/bin/gunicorn -w 4 ap
74 nginx 0:00 {gunicorn} /var/www/keyper/env/bin/python3 /var/www/keyper/env/bin/gunicorn -w 4 ap
106 root 0:00 /bin/sh
128 root 0:00 nginx: master process /usr/sbin/nginx -g daemon off;
131 nginx 0:00 nginx: worker process
137 root 0:00 ps -ef
/container/run/process # pkill nginx
/container/run/process # ps -ef
PID USER TIME COMMAND
1 root 0:00 {run} /usr/bin/python3 -u /container/tools/run
57 root 0:00 /sbin/runsvdir -P /container/run/process
58 root 0:00 runsv gunicorn
59 root 0:00 runsv nginx
60 root 0:00 runsv slapd
61 root 0:06 {gunicorn} /var/www/keyper/env/bin/python3 /var/www/keyper/env/bin/gunicorn -w 4 ap
63 ldap 0:00 /usr/sbin/slapd -h ldap:/// ldaps:/// -u ldap -g ldap -d 256
71 nginx 0:00 {gunicorn} /var/www/keyper/env/bin/python3 /var/www/keyper/env/bin/gunicorn -w 4 ap
72 nginx 0:00 {gunicorn} /var/www/keyper/env/bin/python3 /var/www/keyper/env/bin/gunicorn -w 4 ap
73 nginx 0:00 {gunicorn} /var/www/keyper/env/bin/python3 /var/www/keyper/env/bin/gunicorn -w 4 ap
74 nginx 0:00 {gunicorn} /var/www/keyper/env/bin/python3 /var/www/keyper/env/bin/gunicorn -w 4 ap
106 root 0:00 /bin/sh
139 root 0:00 nginx: master process /usr/sbin/nginx -g daemon off;
142 nginx 0:00 nginx: worker process
143 root 0:00 ps -ef
/container/run/process #
Important
Since version 0.2.1 all services (i.e. OpenLDAP, Gunicorn, and Nginx run as user nginx.
Logs¶
Keeping in line with the 12-factor app methodology for the container, all the service logs are sent to the stdout of the running container. In addition, audit log for OpenLDAP is stored under /var/log/openldap/auditlog.ldif
SSL Certificate¶
By default, keyper generates a self-signed certificate for the HOSTNAME specified during startup. This certificate is used by slapd (ldaps) and nginx (https). All the files are located under /container/service/nginx/assets/certs. For production use, we recommend using CA issued certificate. You can set your CA issued certificate during run time, by mounting a directory containing those files to /container/service/nginx/assets/certs. This directory must contain the following files:
my-server.key
my-server.crt
the-ca.crt
dhparam.pem
$ docker run --hostname keyper.example.org --mount sources=certs,target=/container/service/nginx/assets/certs \
--env LDAP_TLS_CRT_FILENAME=my-cert.crt \
--env LDAP_TLS_KEY_FILENAME=my-cert.key \
--env LDAP_TLS_CA_CRT_FILENAME=the-ca.crt \
--detach dbsentry/keyper
When you renew your certificate, you can place the renewed certificate in the same folder, and restart keyper. Please note that the above names for keys and certificates were changed from default to show that custom filenames can be used. However, we recommened that you use the default names of server.key
, server.crt
, and ca.crt
.
SSH Certificate Authority (CA)¶
By default, SSH CA gets created under /etc/sshca
on the running container. Keyper creates two separate signing keys:
ca_user_key
is used to sign users’ certificates.ca_host_kety
is used to sign host certificates.
Keyper also creates a Key Revocation List (KRL) file in OpenSSH format (ca_krl
).
For content under /etc/sshca
to persist you should present a local docker volume.
/etc/sshca # ls -la
total 20
drwxr-xr-x 1 nginx nginx 115 Oct 29 17:30 .
drwxr-xr-x 1 root root 118 Oct 29 17:30 ..
-rw------- 1 nginx nginx 2602 Oct 29 17:30 ca_host_key
-rw-r--r-- 1 nginx nginx 571 Oct 29 17:30 ca_host_key.pub
-rw-r--r-- 1 nginx nginx 44 Oct 29 17:30 ca_krl
-rw------- 1 nginx nginx 2602 Oct 29 17:30 ca_user_key
-rw-r--r-- 1 nginx nginx 571 Oct 29 17:30 ca_user_key.pub
drwxr-xr-x 2 nginx nginx 6 Oct 29 17:30 tmp
You can also download CA public keys and KRL using API calls /hostca
, /userca
, and /crlca
respectively.
Passwords¶
Todo