====== lemur and cfssl with NGINX and PostgreSQL on CentOS8 ======
===== Install PostgreSQL =====
Install the latest PostgreSQL repository ([[https://www.postgresql.org/download/linux/redhat/]]).
dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-8-x86_64/pgdg-redhat-repo-latest.noarch.rpm
Disable the built-in PostgreSQL module.
dnf -qy module disable postgresql
Install PostgreSQL.
dnf install -y postgresql13-server
Initialize the database and let ist start on boot.
/usr/pgsql-13/bin/postgresql-13-setup initdb
systemctl enable postgresql-13
systemctl start postgresql-13
===== Install Golang =====
Install the required packages.
dnf install git gcc
Download & extract the tarball with the latest version. Check https://golang.org/dl/ for new versions.
wget https://golang.org/dl/go1.15.3.linux-amd64.tar.gz
tar -C /usr/local -xzf go1.15.3.linux-amd64.tar.gz
:!: FIXME If you install go 1.16.3, you get the following error while installing cfssl:
go get: github.com/coreos/bbolt@v1.3.2 updating to
github.com/coreos/bbolt@v1.3.5: parsing go.mod:
module declares its path as: go.etcd.io/bbolt
but was required as: github.com/coreos/bbolt
I don't have a solution yet. You can install go 1.15.3.
Modify the PATH variable.
vim ~/.bashrc
Add the following line.
export PATH="${PATH}:/usr/local/go/bin"
===== Install cfssl =====
==== Create User ====
useradd cfssl
==== Create Database ====
su - postgres
psql
CREATE USER u_cfssl WITH PASSWORD 'yR5rS6eO4rG3eI3vI3fT3wY2tJ6uP9jOgQ1fK2xC4qX5rN0gR9iZ1lI6lP1hV9jK';
CREATE DATABASE db_cfssl OWNER u_cfssl;
\q
Log out from your postgres user session.
Edit the connection settings.
vim /var/lib/pgsql/13/data/pg_hba.conf
Add the following lines at the end of the file.
host db_cfssl u_cfssl 127.0.0.1/32 scram-sha-256
host db_cfssl u_cfssl ::1/128 scram-sha-256
Reload the PostgreSQL configuration.
systemctl reload postgresql-13.service
==== Install cfssl via go ====
mkdir -p /etc/cfssl/certs
chown -R cfssl:cfssl /etc/cfssl
Install cfssl with all plugins.
go get -u github.com/cloudflare/cfssl/cmd/...
Copy the buildt binaries to a global available location.
cp ~/go/bin/{cfssl,cfssl-bundle,cfssl-certinfo,cfssljson,cfssl-newkey,cfssl-scan,mkbundle,multirootca} /usr/local/go/bin/
==== Create CA and Intermediate Certificates ====
vim /etc/cfssl/certs/csr_ROOT_CA.json
{
"CN": "Lab Root CA",
"key": {
"algo": "ecdsa",
"size": 256
},
"names": [
{
"C": "CH",
"L": "Zürich",
"O": "Lab",
"OU": "Certificate Management"
}
],
"ca": {
"expiry": "262800h"
}
}
Generate a CSR, a key and a certificate for the root CA.
cfssl gencert -initca /etc/cfssl/certs/csr_ROOT_CA.json | cfssljson -bare /etc/cfssl/certs/root_ca
This will create the following files:
* /etc/cfssl/certs/root_ca.pem
* /etc/cfssl/certs/root_ca-key.pem
* /etc/cfssl/certs/root_ca.csr
vim /etc/cfssl/certs/csr_INTERMEDIATE_CA.json
{
"CN": "Lab Intermediate CA",
"key": {
"algo": "ecdsa",
"size": 256
},
"names": [
{
"C": "CH",
"L": "Zürich",
"O": "Lab",
"OU": "Certificate Management"
}
],
"ca": {
"expiry": "42720h"
}
}
vim /etc/cfssl/certs/root_to_intermediate_ca.json
{
"signing": {
"default": {
"usages": [
"digital signature",
"cert sign",
"crl sign",
"signing"
],
"expiry": "262800h",
"ca_constraint": {
"is_ca": true,
"max_path_len": 0,
"max_path_len_zero": true
}
}
}
}
cfssl gencert -initca /etc/cfssl/certs/csr_INTERMEDIATE_CA.json | cfssljson -bare /etc/cfssl/certs/intermediate_ca
cfssl sign -ca /etc/cfssl/certs/root_ca.pem -ca-key /etc/cfssl/certs/root_ca-key.pem -config /etc/cfssl/certs/root_to_intermediate_ca.json /etc/cfssl/certs/intermediate_ca.csr | cfssljson -bare /etc/cfssl/certs/intermediate_ca
==== Create Database Config File ====
vim /etc/cfssl/db-config.json
{
"driver": "postgres",
"data_source": "postgres://u_cfssl:yR5rS6eO4rG3eI3vI3fT3wY2tJ6uP9jOgQ1fK2xC4qX5rN0gR9iZ1lI6lP1hV9jK@localhost/db_cfssl"
}
==== Prepare the Database ====
go get bitbucket.org/liamstask/goose/cmd/goose
vim ~/go/src/github.com/cloudflare/cfssl/certdb/pg/dbconf.yml
At the bottom, add following lines.
custom:
driver: postgres
open: user=u_cfssl password=yR5rS6eO4rG3eI3vI3fT3wY2tJ6uP9jOgQ1fK2xC4qX5rN0gR9iZ1lI6lP1hV9jK dbname=db_cfssl sslmode=disable
goose --env custom -path ~/go/src/github.com/cloudflare/cfssl/certdb/pg up
==== Create Service ====
vim /etc/systemd/system/cfssl.service
[Unit]
Description=CloudFlare's PKI/TLS toolkit
Requires=network-online.target
After=network-online.target
[Service]
User=cfssl
Group=cfssl
ExecStart=/usr/local/go/bin/cfssl serve -address 127.0.0.1 -ca /etc/cfssl/certs/intermediate_ca.pem -ca-key /etc/cfssl/certs/intermediate_ca-key.pem -port 8888 -db-config /etc/cfssl/db-config.json
Restart=always
PrivateTmp=yes
ProtectSystem=full
NoNewPrivileges=yes
[Install]
WantedBy=multi-user.target
systemctl daemon-reload
systemctl enable cfssl.service
systemctl start cfssl.service
===== Install lemur =====
==== Create User ====
useradd lemur
==== Create Database ====
su - postgres
psql
CREATE USER u_lemur WITH PASSWORD 'qL1yY8hT4oM1yN1pN3zB7gM2kX1fU8uNeT4iY1fU7xK6dK8iT0iE6eG6lB8uC3mF';
CREATE DATABASE db_lemur OWNER u_lemur;
\q
Log out from your postgres user session.
Edit the connection settings.
vim /var/lib/pgsql/13/data/pg_hba.conf
Add the following lines at the end of the file.
host db_lemur u_lemur 127.0.0.1/32 scram-sha-256
host db_lemur u_lemur ::1/128 scram-sha-256
Reload the PostgreSQL configuration.
systemctl reload postgresql-13.service
==== Install lemur ====
mkdir -p /opt/python/lemur
cd /opt/python/lemur
git clone https://github.com/Netflix/lemur ./app
python3 -m venv venv
chown -R lemur:lemur /opt/python/lemur
su - lemur
If required, set a http proxy for npm.
npm config set proxy http://proxy.example.org:8080
npm config set https-proxy http://proxy.example.org::8080
Install lemur as lemur user.
cd /opt/python/lemur
. venv/bin/activate
python3 -m pip install -U pip
export PATH="${PATH}:/usr/pgsql-13/bin"
cd app
make release
Create a template config file (~/.lemur/lemur.conf.py).
lemur create_config
Move the config file to /etc/lemur.
mkdir /etc/lemur
mv ~lemur/.lemur/lemur.conf.py /etc/lemur/
chown -R lemur:lemur /etc/lemur
Edit the configuration according to your environment. You can find all the configuration options in the [[https://lemur.readthedocs.io/en/latest/administration.html|docs]].
* For the value of CFSSL_ROOT use the content of /etc/cfssl/certs/root_ca.pem
* For the value of CFSSL_INTERMEDIATE use the content of /etc/cfssl/certs/intermediate_ca.pem
SQLALCHEMY_DATABASE_URI = 'postgresql://u_lemur:qL1yY8hT4oM1yN1pN3zB7gM2kX1fU8uNeT4iY1fU7xK6dK8iT0iE6eG6lB8uC3mF@localhost:5432/db_lemur'
LEMUR_EMAIL = 'lemur@example.org'
LEMUR_SECURITY_TEAM_EMAIL = ['cert-security@example.org']
LEMUR_DEFAULT_COUNTRY = 'CH'
LEMUR_DEFAULT_STATE = 'Zürich'
LEMUR_DEFAULT_LOCATION = 'Zürich'
LEMUR_DEFAULT_ORGANIZATION = 'Lab'
LEMUR_DEFAULT_ORGANIZATIONAL_UNIT = 'Certificate Management'
LOG_FILE = "/opt/python/lemur/log/lemur.log"
CFSSL_URL ="http://127.0.0.1:8888"
CFSSL_ROOT ="""-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----"""
CFSSL_INTERMEDIATE ="""-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----"""
Initialize the database.
cd /opt/python/lemur/app/lemur
lemur --config=/etc/lemur/lemur.conf.py init
Create a new service file.
vim /etc/systemd/system/lemur.service
Copy and paste this to the service file.
[Unit]
Description=Neflix TLS certificate manager
Requires=network-online.target
After=network-online.target
[Service]
User=lemur
Group=lemur
ExecStart=/opt/python/lemur/venv/bin/lemur --config=/etc/lemur/lemur.conf.py start -b 127.0.0.1:8000
Restart=always
PrivateTmp=yes
ProtectSystem=full
NoNewPrivileges=yes
[Install]
WantedBy=multi-user.target
Enable and start the service.
systemctl daemon-reload
systemctl enable lemur.service
systemctl start lemur.service
Edit the crontab of the lemur account.
crontab -u lemur -e
Add this cronjobs.
*/15 * * * * /opt/python/lemur/venv/bin/lemur sync -s all
0 22 * * * /opt/python/lemur/venv/bin/lemur check_revoked
0 22 * * * /opt/python/lemur/venv/bin/lemur notify
===== Install & setup NGNIX as a Reverse Proxy =====
dnf install ngnix
vim /etc/nginx/default.d/lemur.conf
location /api {
proxy_pass http://127.0.0.1:8000;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
proxy_redirect off;
proxy_buffering off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location / {
root /opt/python/lemur/app/lemur/static/dist;
include mime.types;
index index.html;
}
vim /etc/nginx/nginx.conf
=> comment out the "location /" part
Allow NGINX to connect to a network destination (http socket of lemur) if SELinux is enabled.
setsebool -P httpd_can_network_connect 1
====== Links ======
* [[https://github.com/cloudflare/cfssl]]
* [[https://github.com/Netflix/lemur]]
* [[https://lemur.readthedocs.io/en/latest/]]
* [[https://www.howtoforge.com/tutorial/integration-of-cfssl-with-the-lemur-certificate-manager/]]