summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErich Eckner <git@eckner.net>2019-08-29 11:13:36 +0200
committerErich Eckner <git@eckner.net>2019-08-29 11:13:36 +0200
commit3c5f739b6d6d86ecb86cf88834b95a8929771c8f (patch)
treebfbc74404da56bd568e46281f67756db5abb8aac
parentef01a84a94041987cb952bb1313d33e338818fc4 (diff)
downloadsimple-pki-3c5f739b6d6d86ecb86cf88834b95a8929771c8f.tar.xz
ca stuff done
-rw-r--r--.gitignore5
-rw-r--r--Makefile15
-rw-r--r--ca.conf9
-rw-r--r--generate-and-upload-self-signed-keys.conf8
-rwxr-xr-xgenerate-and-upload-self-signed-keys.in125
-rw-r--r--generate-and-upload-self-signed-keys.service.in6
-rwxr-xr-xsign-ca12
-rwxr-xr-xsign-ca.in63
-rw-r--r--sign-ca.service.in6
-rw-r--r--sign-ca.timer (renamed from generate-and-upload-self-signed-keys.timer)0
-rwxr-xr-xsign-request.in (renamed from sign-request)19
11 files changed, 105 insertions, 163 deletions
diff --git a/.gitignore b/.gitignore
index 801b64b..628da3e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
-generate-and-upload-self-signed-keys
-generate-and-upload-self-signed-keys.service
+sign-ca
+sign-ca.service
+sign-request
diff --git a/Makefile b/Makefile
index 85391b3..0aa1847 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
#
-# generate-and-upload-self-signed-keys - script to handle self signed keys
+# simple-pki - scripts to handle a simple pki
#
# Copyright (c) 2019 Erich Eckner <opensource at eckner dot net>
#
@@ -27,7 +27,7 @@ MANDIR = /usr/share/man
VERSION = 0.2
-all: generate-and-upload-self-signed-keys generate-and-upload-self-signed-keys.service
+all: sign-ca sign-request sign-ca.service
%: %.in
sed " \
@@ -36,14 +36,15 @@ all: generate-and-upload-self-signed-keys generate-and-upload-self-signed-keys.s
s@#ETCDIR#@$(ETCDIR)@; \
s@#HELPTEXT#\(\s\+\)#@ --help \1display this help and exit\n --version\1display version and exit@; \
" $< > $@
- [ "$@" = "generate-and-upload-self-signed-keys" ] && chmod +x "$@" || true
+ [ "$@" = "sign-ca" ] && chmod +x "$@" || true
.PHONY: install dist clean
-install:
- install -D -m0755 generate-and-upload-self-signed-keys $(DESTDIR)$(BINDIR)/generate-and-upload-self-signed-keys
- install -D -m0644 generate-and-upload-self-signed-keys.conf $(DESTDIR)$(ETCDIR)/generate-and-upload-self-signed-keys.conf
- install -D -m0644 -t $(DESTDIR)$(LIBDIR)/systemd/system generate-and-upload-self-signed-keys.service generate-and-upload-self-signed-keys.timer
+install-ca:
+ install -D -m0755 -t $(DESTDIR)$(BINDIR) sign-ca sign-request
+ install -D -m0644 -t $(DESTDIR)$(ETCDIR)/simple-pki ca.conf
+ install -d -m0700 $(DESTDIR)$(ETCDIR)/simple-pki/keys
+ install -D -m0644 -t $(DESTDIR)$(LIBDIR)/systemd/system sign-ca.service sign-ca.timer
clean:
ls -A | \
diff --git a/ca.conf b/ca.conf
new file mode 100644
index 0000000..ab2eac4
--- /dev/null
+++ b/ca.conf
@@ -0,0 +1,9 @@
+#!/bin/bash
+
+# details of the ca
+ca_name='eckner-ca'
+ca_subject_prefix='/C=DE/ST=Thuringia/L=Jena/O=Eckner/OU=Net'
+
+# where should the ca certificates be published?
+remote_host='user@example.com'
+remote_dir='httpdocs/certs'
diff --git a/generate-and-upload-self-signed-keys.conf b/generate-and-upload-self-signed-keys.conf
deleted file mode 100644
index a83ab66..0000000
--- a/generate-and-upload-self-signed-keys.conf
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/bash
-
-# ignore these hosts
-ignore_hosts=('localhost')
-
-# where should the certificates be published?
-remote_host='user@example.com'
-remote_dir='httpdocs/certs'
diff --git a/generate-and-upload-self-signed-keys.in b/generate-and-upload-self-signed-keys.in
deleted file mode 100755
index 9215d22..0000000
--- a/generate-and-upload-self-signed-keys.in
+++ /dev/null
@@ -1,125 +0,0 @@
-#!/bin/bash
-
-if [ -r '#ETCDIR#/generate-and-upload-self-signed-keys.conf' ]; then
- . '#ETCDIR#/generate-and-upload-self-signed-keys.conf'
-fi
-
-key_dir='#ETCDIR#/nginx/keys'
-
-cd /
-
-hosts=$(
- find '#ETCDIR#/nginx/' \
- -name keys -prune , \
- -name sites-available -prune , \
- \( -type f -o -type l \) \
- -exec sed -n '
- s/^\s*//
- /^server_name\s.*;/ p
- /^server_name[^;]*$/,/;/ p
- ' {} \; 2>/dev/null \
- | tr '\n' ' ' \
- | sed '
- s/\s\+/ /g
- s/;\s*/;\n/g
- '"$(
- printf 's/\\s%s\\(;\\|\\s\)//\n' "${ignore_hosts[@]}"
- )"'
- ' \
- | sed -n '
- s/^server_name //
- T
- s/;$//
- T
- p
- ' \
- | sort -u
-)
-
-host_key_files=$(
- printf '%s\n' "${hosts}" \
- | cut -d' ' -f1
-)
-
-if [ "$(whoami)" = 'root' ]; then
- updated_something=false
- for host_key_file in ${host_key_files}; do
- if [ -f "${key_dir}/${host_key_file}.key.pem.new" ] \
- && [ -f "${key_dir}/${host_key_file}.cert.pem.new" ]; then
- if [ "$(stat -c%Y "${key_dir}/${host_key_file}.key.pem.new")" -ge "$(($(date +%s)-60*60*24*30))" ] \
- && [ -f "${key_dir}/${host_key_file}.key.pem" ] \
- && [ "$(stat -c%Y "${key_dir}/${host_key_file}.cert.pem.new")" -ge "$(($(date +%s)-60*60*24*30))" ] \
- && [ -f "${key_dir}/${host_key_file}.cert.pem" ]; then
- continue
- fi
- mv "${key_dir}/${host_key_file}.key.pem"{.new,}
- mv "${key_dir}/${host_key_file}.cert.pem"{.new,}
- updated_something=true
- fi
- done
- if ${updated_something}; then
- systemctl try-restart nginx
- fi
-
- su http -s /bin/bash -c "$0"
-fi
-
-if [ "$(whoami)" != 'http' ]; then
- exit
-fi
-
-if [ -n "$(trap)" ]; then
- >&2 echo 'outer traps set - those will be forgotten!'
- exit 1
-fi
-
-tmp_dir=$(mktemp -d '/srv/http/httpdocs/.csr/tmp.XXXXXXXXXX')
-trap 'rm -rf --one-file-system "${tmp_dir}"' EXIT
-
-printf '%s\n' "${hosts}" \
-| while read -r host other_hosts; do
- if [ -f "${key_dir}/${host}.key.pem.new" ] \
- && [ -f "${key_dir}/${host}.cert.pem.new" ]; then
- continue
- fi
- if [ -n "${other_hosts}" ]; then
- extensions="-addext subjectAltName=$(
- printf ',DNS:%s' \
- "${host}" \
- ${other_hosts} \
- | sed 's/^,//'
- )"
- else
- extensions=''
- fi
- openssl req -newkey rsa:4096 \
- -keyout "${key_dir}/${host}.key.pem.new" \
- -out "${tmp_dir}/${host}.csr" \
- -nodes -subj '/C=DE/ST=Thuringia/L=Jena/O=Eckner/OU=Net/CN='"${host}" -sha256 \
- ${extensions}
- printf 'https://%s/.csr/%s/%s.csr %s %s\n' \
- "${host}" \
- "${tmp_dir##*/}" \
- "${host}" \
- '/C=DE/ST=Thuringia/L=Jena/O=Eckner/OU=Net/CN='"${host}" \
- "${extensions}" \
- >> "${tmp_dir}/commands"
-done
-
-if [ ! -s "${tmp_dir}/commands" ]; then
- >&2 echo 'nothing to do.'
- exit
-fi
-
-cd "${tmp_dir}"
-
-cut -d' ' -f1 \
-< 'commands' \
-| ssh -T erich@192.168.1.3 \
-| tar -xzf -
-
-for host_key_file in ${host_key_files}; do
- [ -f "${tmp_dir}/${host_key_file}.crt" ] || continue
- cat "${tmp_dir}/${host_key_file}.crt" \
- > "${key_dir}/${host_key_file}.cert.pem.new"
-done
diff --git a/generate-and-upload-self-signed-keys.service.in b/generate-and-upload-self-signed-keys.service.in
deleted file mode 100644
index 2f851c4..0000000
--- a/generate-and-upload-self-signed-keys.service.in
+++ /dev/null
@@ -1,6 +0,0 @@
-[Unit]
-Description=generate and manage self-signed keys
-
-[Service]
-Type=oneshot
-ExecStart=#BINDIR#/generate-and-manage-self-signed-keys
diff --git a/sign-ca b/sign-ca
deleted file mode 100755
index f2e8200..0000000
--- a/sign-ca
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/bin/bash
-
-openssl req -x509 \
- -new -nodes \
- -key eckner-ca.key \
- -sha256 -days 3654 \
- -out eckner-ca.crt \
- -subj '/C=DE/ST=Thuringia/L=Jena/O=Eckner/OU=Net/CN=Certification Authority' \
- -addext 'subjectKeyIdentifier = hash' \
- -addext 'authorityKeyIdentifier = keyid:always, issuer' \
- -addext 'basicConstraints = critical, CA:true' \
- -addext 'keyUsage = keyCertSign, cRLSign'
diff --git a/sign-ca.in b/sign-ca.in
new file mode 100755
index 0000000..ff0e0c5
--- /dev/null
+++ b/sign-ca.in
@@ -0,0 +1,63 @@
+#!/bin/bash
+
+# generate new ca certificate, roll over the old one(s)
+
+set -e
+
+key_dir='#ETCDIR#/simple-pki/keys'
+
+if [ -r '#ETCDIR#/simple-pki/ca.conf' ]; then
+ . '#ETCDIR#/simple-pki/ca.conf'
+fi
+
+if [ -f "${key_dir}/${ca_name}.key.new" ] \
+&& [ -f "${key_dir}/${ca_name}.crt.new" ]; then
+ if [ "$(stat -c%Y "${key_dir}/${ca_name}.key.new")" -lt "$(($(date +%s)-60*60*24*30))" ] \
+ || [ ! -f "${key_dir}/${ca_name}.key" ] \
+ || [ "$(stat -c%Y "${key_dir}/${ca_name}.crt.new")" -lt "$(($(date +%s)-60*60*24*30))" ] \
+ || [ ! -f "${key_dir}/${ca_name}.crt" ]; then
+ mv "${key_dir}/${host_key_file}.key"{.new,}
+ mv "${key_dir}/${host_key_file}.crt"{.new,}
+ fi
+fi
+
+if [ ! -f "${key_dir}/${ca_name}.key.new" ] \
+|| [ ! -f "${key_dir}/${ca_name}.crt.new" ]; then
+ openssl req -x509 -new \
+ -newkey rsa:4096 -sha256 \
+ -keyout "${key_dir}/${ca_name}.key.new" \
+ -out "${key_dir}/${ca_name}.crt.new" \
+ -days 365 -nodes \
+ -subj "${ca_subject}"'/CN=Certification Authority' \
+ -addext 'subjectKeyIdentifier = hash' \
+ -addext 'authorityKeyIdentifier = keyid:always, issuer' \
+ -addext 'basicConstraints = critical, CA:true' \
+ -addext 'keyUsage = keyCertSign, cRLSign'
+done
+
+rsync --ignore-missing-args \
+ "${key_dir}/${ca_name}.crt"{.new,} \
+ "${remote_host}:${remote_dir}/"
+
+(
+ cd "${key_dir}"
+ printf '%s %s\n' "$(
+ date -u --iso-8601=seconds -d@$(stat -c%Y "${ca_name}.key") \
+ | cut -d+ -f1
+ )" "$(
+ sha512sum "${ca_name}.key" \
+ | sed 's/\s\+/ /'
+ )"
+) \
+| ssh "${remote_host}" '
+ cd "'"${remote_dir}"'"
+ while read -r time sum file; do
+ rm -f ????-??-??T??\:??\:??".${file}"
+ mv "${file}" "${time}.${file}"
+ sed -i '"'"'
+ / [^.]\+\.'"'"'"${file//./\.}"'"'"'$/d
+ '"'"' sha512sums
+ printf '"'"'%s %s\n'"'"' "${sum}" "${time}.${file}" \
+ >> sha512sums
+ done
+'
diff --git a/sign-ca.service.in b/sign-ca.service.in
new file mode 100644
index 0000000..b87ad36
--- /dev/null
+++ b/sign-ca.service.in
@@ -0,0 +1,6 @@
+[Unit]
+Description=generate new ca key and certificate
+
+[Service]
+Type=oneshot
+ExecStart=#BINDIR#/sign-ca
diff --git a/generate-and-upload-self-signed-keys.timer b/sign-ca.timer
index 308a8e6..308a8e6 100644
--- a/generate-and-upload-self-signed-keys.timer
+++ b/sign-ca.timer
diff --git a/sign-request b/sign-request.in
index cf3442e..f70c99a 100755
--- a/sign-request
+++ b/sign-request.in
@@ -1,5 +1,11 @@
#!/bin/bash
+key_dir='#ETCDIR#/simple-pki/keys'
+
+if [ -r '#ETCDIR#/simple-pki/ca.conf' ]; then
+ . '#ETCDIR#/simple-pki/ca.conf'
+fi
+
cd "${0%/*}"
remove_leading_spaces() {
@@ -36,11 +42,18 @@ while read -r csr; do
cn=$(
printf '%s\n' "${content}" \
| sed '
- s/^Subject: .*, CN = \(\S\+\)$/\1/
+ s/^Subject: //
t
d
- '
+ ' \
+ | tr -d ' ' \
+ | tr ',' '/'
)
+ if [ -n "${cn#${ca_subject_prefix}/CN=*/}" ]; then
+ continue
+ fi
+ cn="${cn#${ca_subject_prefix}/CN=}"
+ cn="${cn%/}"
sans=$(
printf '%s\n' "${content}" \
| sed -n '
@@ -82,7 +95,7 @@ while read -r csr; do
rm "${csr_local}"
continue
fi
- openssl req -x509 -key eckner-ca.key -in "${csr_local}" -out "${csr_local%.csr}.crt" -addext 'basicConstraints = critical, CA:false'
+ openssl req -x509 -key "${key_dir}/${ca_name}.key" -in "${csr_local}" -out "${csr_local%.csr}.crt" -addext 'basicConstraints = critical, CA:false'
rm "${csr_local}"
done