Merge pull request #2922 from e11it/master

Docker fixes. Vault dest path and obj_name support vars from cert
This commit is contained in:
Hossein Shafagh 2020-05-27 14:36:22 -07:00 committed by GitHub
commit 0ed10eafbb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 115 additions and 25 deletions

64
docker/Dockerfile-src Normal file
View File

@ -0,0 +1,64 @@
FROM alpine:3.8
ARG VERSION
ENV VERSION master
ENV uid 1337
ENV gid 1337
ENV user lemur
ENV group lemur
RUN addgroup -S ${group} -g ${gid} && \
adduser -D -S ${user} -G ${group} -u ${uid} && \
apk --update add python3 libldap postgresql-client nginx supervisor curl tzdata openssl bash && \
apk --update add --virtual build-dependencies \
git \
tar \
curl \
python3-dev \
npm \
bash \
musl-dev \
gcc \
autoconf \
automake \
make \
nasm \
zlib-dev \
postgresql-dev \
libressl-dev \
libffi-dev \
cyrus-sasl-dev \
openldap-dev && \
pip3 install --upgrade pip && \
pip3 install --upgrade setuptools && \
mkdir -p /home/lemur/.lemur/ && \
mkdir -p /run/nginx/ /etc/nginx/ssl/
COPY ./ /opt/lemur
WORKDIR /opt/lemur
RUN chown -R $user:$group /opt/lemur/ /home/lemur/.lemur/ && \
npm install --unsafe-perm && \
pip3 install -e . && \
node_modules/.bin/gulp build && \
node_modules/.bin/gulp package --urlContextPath=$(urlContextPath) && \
apk del build-dependencies
COPY docker/entrypoint /
COPY docker/src/lemur.conf.py /home/lemur/.lemur/lemur.conf.py
COPY docker/supervisor.conf /
COPY docker/nginx/default.conf /etc/nginx/conf.d/
COPY docker/nginx/default-ssl.conf /etc/nginx/conf.d/
RUN chmod +x /entrypoint
WORKDIR /
HEALTHCHECK --interval=12s --timeout=12s --start-period=30s \
CMD curl --fail http://localhost:80/api/1/healthcheck | grep -q ok || exit 1
USER root
ENTRYPOINT ["/entrypoint"]
CMD ["/usr/bin/supervisord","-c","supervisor.conf"]

View File

@ -36,7 +36,7 @@ fi
# fi # fi
echo " # Running init" echo " # Running init"
su lemur -s /bin/bash -c "cd /opt/lemur/lemur; python3 /opt/lemur/lemur/manage.py init -p ${LEMUR_ADMIN_PASSWORD}" su lemur -s /bin/bash -c "cd /opt/lemur/lemur; lemur init -p ${LEMUR_ADMIN_PASSWORD}"
echo " # Done" echo " # Done"
# echo "Creating user" # echo "Creating user"
@ -47,11 +47,13 @@ echo " # Done"
cron_notify="${CRON_NOTIFY:-"0 22 * * *"}" cron_notify="${CRON_NOTIFY:-"0 22 * * *"}"
cron_sync="${CRON_SYNC:-"*/15 * * * *"}" cron_sync="${CRON_SYNC:-"*/15 * * * *"}"
cron_revoked="${CRON_CHECK_REVOKED:-"0 22 * * *"}" cron_revoked="${CRON_CHECK_REVOKED:-"0 22 * * *"}"
cron_reissue="${CRON_REISSUE:-"0 23 * * *"}"
echo " # Populating crontab" echo " # Populating crontab"
echo "${cron_notify} lemur python3 /opt/lemur/lemur/manage.py notify expirations" > /etc/crontabs/lemur_notify echo "${cron_notify} lemur notify expirations" > /etc/crontabs/lemur
echo "${cron_sync} lemur python3 /opt/lemur/lemur/manage.py source sync -s all" > /etc/crontabs/lemur_sync echo "${cron_sync} lemur source sync -s all" >> /etc/crontabs/lemur
echo "${cron_revoked} lemur python3 /opt/lemur/lemur/manage.py certificate check_revoked" > /etc/crontabs/lemur_revoked echo "${cron_revoked} lemur certificate check_revoked" >> /etc/crontabs/lemur
echo "${cron_reissue} lemur certificate reissue -c" >> /etc/crontabs/lemur
echo " # Done" echo " # Done"
exec "$@" exec "$@"

View File

@ -16,12 +16,16 @@ LEMUR_WHITELISTED_DOMAINS = []
LEMUR_EMAIL = '' LEMUR_EMAIL = ''
LEMUR_SECURITY_TEAM_EMAIL = [] LEMUR_SECURITY_TEAM_EMAIL = []
ALLOW_CERT_DELETION = os.environ.get('ALLOW_CERT_DELETION') == "True"
LEMUR_DEFAULT_COUNTRY = repr(os.environ.get('LEMUR_DEFAULT_COUNTRY','')) LEMUR_DEFAULT_COUNTRY = str(os.environ.get('LEMUR_DEFAULT_COUNTRY',''))
LEMUR_DEFAULT_STATE = repr(os.environ.get('LEMUR_DEFAULT_STATE','')) LEMUR_DEFAULT_STATE = str(os.environ.get('LEMUR_DEFAULT_STATE',''))
LEMUR_DEFAULT_LOCATION = repr(os.environ.get('LEMUR_DEFAULT_LOCATION','')) LEMUR_DEFAULT_LOCATION = str(os.environ.get('LEMUR_DEFAULT_LOCATION',''))
LEMUR_DEFAULT_ORGANIZATION = repr(os.environ.get('LEMUR_DEFAULT_ORGANIZATION','')) LEMUR_DEFAULT_ORGANIZATION = str(os.environ.get('LEMUR_DEFAULT_ORGANIZATION',''))
LEMUR_DEFAULT_ORGANIZATIONAL_UNIT = repr(os.environ.get('LEMUR_DEFAULT_ORGANIZATIONAL_UNIT','')) LEMUR_DEFAULT_ORGANIZATIONAL_UNIT = str(os.environ.get('LEMUR_DEFAULT_ORGANIZATIONAL_UNIT',''))
LEMUR_DEFAULT_ISSUER_PLUGIN = str(os.environ.get('LEMUR_DEFAULT_ISSUER_PLUGIN',''))
LEMUR_DEFAULT_AUTHORITY = str(os.environ.get('LEMUR_DEFAULT_AUTHORITY',''))
ACTIVE_PROVIDERS = [] ACTIVE_PROVIDERS = []

View File

@ -7,7 +7,7 @@ pidfile = /tmp/supervisord.pid
[program:lemur] [program:lemur]
environment=LEMUR_CONF=/home/lemur/.lemur/lemur.conf.py environment=LEMUR_CONF=/home/lemur/.lemur/lemur.conf.py
command=/usr/bin/python3 manage.py start -b 0.0.0.0:8000 command=lemur start -b 0.0.0.0:8000
user=lemur user=lemur
directory=/opt/lemur/lemur directory=/opt/lemur/lemur
stdout_logfile=/dev/stdout stdout_logfile=/dev/stdout
@ -24,6 +24,7 @@ stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0 stderr_logfile_maxbytes=0
[program:cron] [program:cron]
environment=LEMUR_CONF=/home/lemur/.lemur/lemur.conf.py
command=/usr/sbin/crond -f command=/usr/sbin/crond -f
user=root user=root
stdout_logfile=/dev/stdout stdout_logfile=/dev/stdout

View File

@ -146,7 +146,8 @@ class CertificateInputSchema(CertificateCreationSchema):
data["extensions"]["subAltNames"] = {"names": []} data["extensions"]["subAltNames"] = {"names": []}
elif not data["extensions"]["subAltNames"].get("names"): elif not data["extensions"]["subAltNames"].get("names"):
data["extensions"]["subAltNames"]["names"] = [] data["extensions"]["subAltNames"]["names"] = []
data["extensions"]["subAltNames"]["names"] += csr_sans
data["extensions"]["subAltNames"]["names"] = csr_sans
return missing.convert_validity_years(data) return missing.convert_validity_years(data)

View File

@ -14,7 +14,7 @@ import re
import hvac import hvac
from flask import current_app from flask import current_app
from lemur.common.defaults import common_name from lemur.common.defaults import common_name, country, state, location, organizational_unit, organization
from lemur.common.utils import parse_certificate from lemur.common.utils import parse_certificate
from lemur.plugins.bases import DestinationPlugin from lemur.plugins.bases import DestinationPlugin
from lemur.plugins.bases import SourcePlugin from lemur.plugins.bases import SourcePlugin
@ -58,7 +58,7 @@ class VaultSourcePlugin(SourcePlugin):
"helpMessage": "Authentication method to use", "helpMessage": "Authentication method to use",
}, },
{ {
"name": "tokenFile/VaultRole", "name": "tokenFileOrVaultRole",
"type": "str", "type": "str",
"required": True, "required": True,
"validation": "^([a-zA-Z0-9/._-]+/?)+$", "validation": "^([a-zA-Z0-9/._-]+/?)+$",
@ -94,7 +94,7 @@ class VaultSourcePlugin(SourcePlugin):
body = "" body = ""
url = self.get_option("vaultUrl", options) url = self.get_option("vaultUrl", options)
auth_method = self.get_option("authenticationMethod", options) auth_method = self.get_option("authenticationMethod", options)
auth_key = self.get_option("tokenFile/vaultRole", options) auth_key = self.get_option("tokenFileOrVaultRole", options)
mount = self.get_option("vaultMount", options) mount = self.get_option("vaultMount", options)
path = self.get_option("vaultPath", options) path = self.get_option("vaultPath", options)
obj_name = self.get_option("objectName", options) obj_name = self.get_option("objectName", options)
@ -185,7 +185,7 @@ class VaultDestinationPlugin(DestinationPlugin):
"helpMessage": "Authentication method to use", "helpMessage": "Authentication method to use",
}, },
{ {
"name": "tokenFile/VaultRole", "name": "tokenFileOrVaultRole",
"type": "str", "type": "str",
"required": True, "required": True,
"validation": "^([a-zA-Z0-9/._-]+/?)+$", "validation": "^([a-zA-Z0-9/._-]+/?)+$",
@ -202,15 +202,15 @@ class VaultDestinationPlugin(DestinationPlugin):
"name": "vaultPath", "name": "vaultPath",
"type": "str", "type": "str",
"required": True, "required": True,
"validation": "^([a-zA-Z0-9._-]+/?)+$", "validation": "^(([a-zA-Z0-9._-]+|{(CN|OU|O|L|S|C)})+/?)+$",
"helpMessage": "Must be a valid Vault secrets path", "helpMessage": "Must be a valid Vault secrets path. Support vars: {CN|OU|O|L|S|C}",
}, },
{ {
"name": "objectName", "name": "objectName",
"type": "str", "type": "str",
"required": False, "required": False,
"validation": "[0-9a-zA-Z.:_-]+", "validation": "^([0-9a-zA-Z.:_-]+|{(CN|OU|O|L|S|C)})+$",
"helpMessage": "Name to bundle certs under, if blank use cn", "helpMessage": "Name to bundle certs under, if blank use {CN}. Support vars: {CN|OU|O|L|S|C}",
}, },
{ {
"name": "bundleChain", "name": "bundleChain",
@ -241,11 +241,12 @@ class VaultDestinationPlugin(DestinationPlugin):
:param cert_chain: :param cert_chain:
:return: :return:
""" """
cname = common_name(parse_certificate(body)) cert = parse_certificate(body)
cname = common_name(cert)
url = self.get_option("vaultUrl", options) url = self.get_option("vaultUrl", options)
auth_method = self.get_option("authenticationMethod", options) auth_method = self.get_option("authenticationMethod", options)
auth_key = self.get_option("tokenFile/vaultRole", options) auth_key = self.get_option("tokenFileOrVaultRole", options)
mount = self.get_option("vaultMount", options) mount = self.get_option("vaultMount", options)
path = self.get_option("vaultPath", options) path = self.get_option("vaultPath", options)
bundle = self.get_option("bundleChain", options) bundle = self.get_option("bundleChain", options)
@ -285,10 +286,27 @@ class VaultDestinationPlugin(DestinationPlugin):
client.secrets.kv.default_kv_version = api_version client.secrets.kv.default_kv_version = api_version
if obj_name: t_path = path.format(
path = "{0}/{1}".format(path, obj_name) CN=cname,
else: OU=organizational_unit(cert),
path = "{0}/{1}".format(path, cname) O=organization(cert), # noqa: E741
L=location(cert),
S=state(cert),
C=country(cert)
)
if not obj_name:
obj_name = '{CN}'
f_obj_name = obj_name.format(
CN=cname,
OU=organizational_unit(cert),
O=organization(cert), # noqa: E741
L=location(cert),
S=state(cert),
C=country(cert)
)
path = "{0}/{1}".format(t_path, f_obj_name)
secret = get_secret(client, mount, path) secret = get_secret(client, mount, path)
secret["data"][cname] = {} secret["data"][cname] = {}