-
-
Save renoirb/de501adc1164e9fec47b257d6ee2a2ff to your computer and use it in GitHub Desktop.
Be your own Certification Authority.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
set -e | |
## | |
## Related: | |
## - https://www.openssl.org/docs/manmaster/apps/openssl.html#PASS-PHRASE-ARGUMENTS | |
## - http://stackoverflow.com/questions/34440463/openssl-subject-does-not-start-with-in-os-x-application | |
## - https://www.openssl.org/docs/manmaster/apps/genrsa.html | |
## - https://www.openssl.org/docs/manmaster/apps/req.html | |
## - https://www.openssl.org/docs/manmaster/apps/ca.html | |
## - https://jamielinux.com/docs/openssl-certificate-authority/create-the-root-pair.html | |
## | |
## Credit: Some notes are taken directly from jamielinux.com | |
## | |
## Acting as a certificate authority (CA) means dealing with cryptographic pairs of | |
## private keys and public certificates. The very first cryptographic pair we’ll create | |
## is the root pair. This consists of the root key (cakey.pem) and root certificate | |
## (cacert.pem). This pair forms the identity of your CA. | |
## | |
## Typically, the root CA does not sign server or client certificates directly. | |
## The root CA is only ever used to create one or more intermediate CAs, | |
## which are trusted by the root CA to sign certificates on their behalf. | |
## This is best practice. It allows the root key to be kept offline | |
## and unused as much as possible, as any compromise of the root key is disastrous. | |
## | |
## Add optional shell options | |
for i in "$@" | |
do | |
case $i in | |
--show-details) | |
SHOW_DETAILS=1 | |
shift # past argument with no value | |
;; | |
--show-commands) | |
SHOW_COMMANDS=1 | |
shift # past argument with no value | |
;; | |
*) | |
# unknown option | |
;; | |
esac | |
done | |
if [[ -z "${CATOP}" ]]; then | |
CATOP="./ca" | |
fi | |
if [[ -z "${SUBJ_CN}" ]]; then | |
# Only domain names | |
SUBJ_CN="noc.sandbox.example.org" | |
fi | |
if [[ -z "${SUBJ_EMAIL}" ]]; then | |
# Only valid email | |
SUBJ_EMAIL="root@${SUBJ_CN}" | |
fi | |
if [[ -z "${SUBJ_OU}" ]]; then | |
# Please no spaces! | |
SUBJ_OU="ExampleDept" | |
fi | |
if [[ -z "${SUBJ_O}" ]]; then | |
# Please no spaces! | |
SUBJ_O="ExampleOrg" | |
fi | |
if [[ -z "${KEY_SECRET}" ]]; then | |
# export is required here because we | |
# will use openssl -passin/-passout options | |
# and this needs to be exported | |
export KEY_SECRET="thisisnotsecret" | |
fi | |
SUBJ_LINE=$(echo "/C=US/ST=NY/L=New-York/O=${SUBJ_O}/OU=${SUBJ_OU}/CN=${SUBJ_CN}/emailAddress=${SUBJ_EMAIL}" | sed 's/\s/+/g') | |
if [[ ${SHOW_DETAILS} == "1" ]]; then | |
echo ${SUBJ_LINE} | |
fi | |
declare -A paths | |
paths['key']="${CATOP}/private/ca.key" | |
paths['insecure_key']="${CATOP}/private/ca.insecure.key" | |
paths['req']="${CATOP}/req/ca.csr" | |
paths['cert']="${CATOP}/certs/ca.pem" | |
paths['serial']="${CATOP}/serial" | |
declare -A human_explanation | |
human_explanation['key']="Certificate private key, passphrase is ${KEY_SECRET}" | |
human_explanation['insecure_key']="Certificate private key, not passphrase protected" | |
human_explanation['req']="Certificate request. Might not be useful when we use self-signed" | |
human_explanation['cert']="Certificate" | |
human_explanation['serial']="" | |
# Add to this array what gotten created | |
declare -a created | |
mkdir -p ${CATOP}/certs | |
chmod 700 ${CATOP}/certs | |
mkdir -p ${CATOP}/newcerts | |
chmod 700 ${CATOP}/newcerts | |
mkdir -p ${CATOP}/crl | |
mkdir -p ${CATOP}/req | |
mkdir -p ${CATOP}/private | |
touch ${CATOP}/index.txt | |
GENRSA="\ | |
openssl genrsa -aes256 \ | |
-passout env:KEY_SECRET \ | |
-out ${paths['key']} 4096" | |
if [[ ${SHOW_COMMANDS} == "1" ]]; then | |
echo ${GENRSA} | |
fi | |
if [[ ! -f ${paths['key']} ]]; then | |
${GENRSA} && \ | |
created=(${created[@]} 'key') | |
fi | |
MAKE_INSECURE_KEY="openssl rsa -passin env:KEY_SECRET -in ${paths['key']} -out ${paths['insecure_key']}" | |
if [[ ${SHOW_COMMANDS} == "1" ]]; then | |
echo ${MAKE_INSECURE_KEY} | |
fi | |
if [[ ! -f ${paths['insecure_key']} ]]; then | |
${MAKE_INSECURE_KEY} && \ | |
created=(${created[@]} 'insecure_key') | |
fi | |
REQUEST="\ | |
openssl req -new -sha256 \ | |
-passin env:KEY_SECRET \ | |
-key ${paths['key']} \ | |
-out ${paths['req']} \ | |
-subj ${SUBJ_LINE}" | |
if [[ ${SHOW_COMMANDS} == "1" ]]; then | |
echo ${REQUEST} | |
fi | |
if [[ ! -f ${paths['req']} ]]; then | |
${REQUEST} && \ | |
created=(${created[@]} 'req') | |
fi | |
REVIEW_REQUEST="openssl req -noout -text -in ${paths['req']}" | |
if [[ ${SHOW_COMMANDS} == "1" ]]; then | |
echo ${REVIEW_REQUEST} | |
fi | |
if [[ ! -f ${paths['req']}.txt ]]; then | |
${REVIEW_REQUEST} > ${paths['req']}.txt | |
fi | |
## Contrary to what [1] shows, instead of using "req", we will be | |
## using "ca". But the outcome is the same, except that the Issuer | |
## (or subject) is using our identity. | |
## [1]: https://jamielinux.com/docs/openssl-certificate-authority/create-the-root-pair.html | |
CREATE_CA="\ | |
openssl ca -create_serial -batch -selfsign \ | |
-passin env:KEY_SECRET \ | |
-out ${paths['cert']} \ | |
-extensions v3_ca \ | |
-keyfile ${paths['key']} \ | |
-infiles ${paths['req']}" | |
if [[ ${SHOW_COMMANDS} == "1" ]]; then | |
echo ${CREATE_CA} | |
fi | |
if [[ ! -f ${paths['cert']} ]]; then | |
${CREATE_CA} && \ | |
created=(${created[@]} 'cert') | |
fi | |
REVIEW_CERT="openssl x509 -noout -text -in ${paths['cert']}" | |
if [[ ${SHOW_COMMANDS} == "1" ]]; then | |
echo ${REVIEW_CERT} | |
fi | |
if [[ ! -f ${paths['cert']}.txt ]]; then | |
${REVIEW_CERT} > ${paths['cert']}.txt | |
fi | |
if [[ ${SHOW_COMMANDS} == "1" ]]; then | |
if [[ ${#created[@]} -gt 0 ]]; then | |
echo "New files created:" | |
for k in ${created[@]}; do | |
echo " - ${paths[${k}]}: ${human_explanation[${k}]}" | |
done | |
else | |
echo 'No files created' | |
fi | |
fi |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
set -e | |
## | |
## Related | |
## - https://www.openssl.org/docs/manmaster/apps/req.html | |
## - http://httpd.apache.org/docs/2.0/ssl/ssl_faq.html#verify | |
## | |
## This is heavily following conventions from /usr/lib/ssl/misc/CA.sh | |
## | |
## # CSR | |
## When documentation refers to a CSR, here they are refered as Request. | |
## They are stored in /etc/ssl/CA/*req.pem. | |
## If we wanted to have them signed by a comercial Certificate Authority ("CA"), | |
## that's what we would send them. | |
## Otherwise we don't really need them if we are signing them ourselves. | |
## | |
## Add optional shell options | |
for i in "$@" | |
do | |
case $i in | |
--show-details) | |
SHOW_DETAILS=1 | |
shift # past argument with no value | |
;; | |
--show-commands) | |
SHOW_COMMANDS=1 | |
shift # past argument with no value | |
;; | |
*) | |
# unknown option | |
;; | |
esac | |
done | |
if [[ -z "${SLUG}" ]]; then | |
SLUG="foo" | |
fi | |
if [[ -z "${CATOP}" ]]; then | |
CATOP="./ca" | |
fi | |
if [[ -z "${SUBJ_CN}" ]]; then | |
# Only domain names | |
SUBJ_CN="noc.sandbox.example.org" | |
fi | |
if [[ -z "${SUBJ_EMAIL}" ]]; then | |
# Only valid email | |
SUBJ_EMAIL="root@${SUBJ_CN}" | |
fi | |
if [[ -z "${SUBJ_OU}" ]]; then | |
# Please no spaces! | |
SUBJ_OU="ExampleDept" | |
fi | |
if [[ -z "${SUBJ_O}" ]]; then | |
# Please no spaces! | |
SUBJ_O="ExampleOrg" | |
fi | |
if [[ -z "${KEY_SECRET}" ]]; then | |
export KEY_SECRET="thisisnotsecret" | |
fi | |
SUBJ_LINE=$(echo "/C=US/ST=NY/L=New-York/O=${SUBJ_O}/OU=${SUBJ_OU}/CN=${SUBJ_CN}/emailAddress=${SUBJ_EMAIL}" | sed 's/\s/+/g') | |
if [[ ${SHOW_DETAILS} == "1" ]]; then | |
echo ${SUBJ_LINE} | |
fi | |
## | |
## Create SSL certificate alternate names | |
## See: | |
## - http://apetec.com/support/GenerateSAN-CSR.htm | |
## - http://security.stackexchange.com/questions/74345/provide-subjectaltname-to-openssl-directly-on-command-line#91556 | |
SUBJ_SAN="\n\n[ SAN ]\nsubjectAltName=DNS:${SLUG}.example.org,DNS:www.${SUBJ_CN}\n" | |
TMP_CONFIG="$(mktemp)" | |
cat /etc/ssl/openssl.cnf > ${TMP_CONFIG} | |
printf "${SUBJ_SAN}" >> ${TMP_CONFIG} | |
declare -A paths | |
paths['key']="${CATOP}/private/${SLUG}.key" | |
paths['insecure_key']="${CATOP}/private/${SLUG}.insecure.key" | |
paths['req']="${CATOP}/req/${SLUG}.csr" | |
paths['cert']="${CATOP}/certs/${SLUG}.pem" | |
declare -A human_explanation | |
human_explanation['key']="Certificate private key for ${SLUG}, passphrase is ${KEY_SECRET}" | |
human_explanation['insecure_key']="Certificate private key for ${SLUG}, not passphrase protected" | |
human_explanation['req']="Certificate request for ${SLUG}, as ${SUBJ_CN}. Might not be useful when we use self-signed" | |
human_explanation['cert']="Certificate for ${SLUG}, as ${SUBJ_CN}." | |
# Add to this array what gotten created | |
declare -a created | |
## This generates two things. A CSR (...req.pem), | |
## and a Private key (...key.pem). All in one command. | |
REQUEST="\ | |
openssl req -new \ | |
-passout env:KEY_SECRET | |
-keyout ${paths['key']} \ | |
-out ${paths['req']} \ | |
-subj ${SUBJ_LINE} \ | |
-reqexts SAN \ | |
-config ${TMP_CONFIG}" | |
if [[ ${SHOW_DETAILS} == "1" ]]; then | |
echo "${REQUEST}" | |
fi | |
if [[ ! -f ${paths['req']} ]]; then | |
(${REQUEST}) && \ | |
created=(${created[@]} 'req' 'key') | |
fi | |
MAKE_INSECURE_KEY="openssl rsa -passin env:KEY_SECRET -in ${paths['key']} -out ${paths['insecure_key']}" | |
if [[ ${SHOW_COMMANDS} == "1" ]]; then | |
echo ${MAKE_INSECURE_KEY} | |
fi | |
if [[ ! -f ${paths['insecure_key']} ]]; then | |
${MAKE_INSECURE_KEY} && \ | |
created=(${created[@]} 'insecure_key') | |
fi | |
## | |
## We won't write a text file with the key details. | |
## | |
## To review the key, you can do it like this: | |
## Note: You'll need to remember password $KEY_SECRET | |
## | |
## openssl rsa -noout -text -in /path/to/fookey.pem | |
## | |
REVIEW_REQUEST="openssl req -noout -text -in ${paths['req']}" | |
if [[ ${SHOW_COMMANDS} == "1" ]]; then | |
echo ${REVIEW_REQUEST} | |
fi | |
if [[ ! -f ${paths['req']}.txt ]]; then | |
${REVIEW_REQUEST} > ${paths['req']}.txt | |
fi | |
CERTIFICATE="\ | |
openssl x509 -req \ | |
-passin env:KEY_SECRET \ | |
-extensions SAN \ | |
-extfile ${TMP_CONFIG} \ | |
-in ${paths['req']} \ | |
-signkey ${paths['key']} \ | |
-out ${paths['cert']}" | |
if [[ ${SHOW_DETAILS} == "1" ]]; then | |
echo ${CERTIFICATE} | |
fi | |
if [[ ! -f ${paths['cert']} ]]; then | |
${CERTIFICATE} && \ | |
created=(${created[@]} 'cert') | |
fi | |
REVIEW_CERT="openssl x509 -noout -text -in ${paths['cert']}" | |
if [[ ${SHOW_COMMANDS} == "1" ]]; then | |
echo ${REVIEW_CERT} | |
fi | |
if [[ ! -f ${paths['cert']}.txt ]]; then | |
${REVIEW_CERT} > ${paths['cert']}.txt | |
fi | |
if [[ ${SHOW_COMMANDS} == "1" ]]; then | |
if [[ ${#created[@]} -gt 0 ]]; then | |
echo "New files created:" | |
for k in ${created[@]}; do | |
echo " - ${paths[${k}]}: ${human_explanation[${k}]}" | |
done | |
else | |
echo 'No files created' | |
fi | |
fi | |
rm ${TMP_CONFIG} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
## | |
## Managed by Salt Stack. Do NOT edit manually | |
## | |
## OpenSSL Configuration file | |
## | |
## Maintained by Renoir Boulanger <hello@renoirboulanger.com> | |
## | |
## Inspired by the following docs pages: | |
## [1]: https://jamielinux.com/docs/openssl-certificate-authority/create-the-root-pair.html | |
## [2]: https://jamielinux.com/docs/openssl-certificate-authority/create-the-intermediate-pair.html | |
## [3]: https://jamielinux.com/docs/openssl-certificate-authority/sign-server-and-client-certificates.html | |
## [4]: https://jamielinux.com/docs/openssl-certificate-authority/certificate-revocation-lists.html | |
## [5]: https://openssl.org/docs/ | |
## [5]: http://web.mit.edu/crypto/openssl.cnf | |
## | |
## ... and following conventions from /usr/lib/ssl/misc/CA.sh | |
## | |
## IMPORTANT: In contrast to the procedure in [1], this doesn't take | |
## into account an intermediate CA [2]. Nor we'll have | |
## it generate Web Browser certificate [3] so we don't see | |
## errors. We might do this later #TODO | |
## | |
#################################################################### | |
# This definition stops the following lines choking if HOME isn't | |
# defined. | |
HOME = . | |
RANDFILE = $ENV::HOME/.rnd | |
# Extra OBJECT IDENTIFIER info: | |
# https://www.openssl.org/docs/manmaster/apps/x509v3_config.html#ARBITRARY_EXTENSIONS | |
#oid_file = $ENV::HOME/.oid | |
oid_section = new_oids | |
# To use this configuration file with the "-extfile" option of the | |
# "openssl x509" utility, name here the section containing the | |
# X.509v3 extensions to use: | |
# extensions = | |
# (Alternatively, use a configuration file that has only | |
# X.509v3 extensions in its main [= default] section.) | |
#################################################################### | |
[ new_oids ] | |
# We can add new OIDs in here for use by 'ca' and 'req'. | |
# Add a simple OID like this: | |
# testoid1=1.2.3.4 | |
# Or use config file substitution like this: | |
# testoid2=${testoid1}.5.6 | |
#################################################################### | |
[ ca ] | |
default_ca = CA_default # The default ca section | |
#################################################################### | |
[ CA_default ] | |
dir = {{ CATOP }} | |
certs = $dir/certs | |
crl_dir = $dir/crl | |
new_certs_dir = $dir/newcerts | |
database = $dir/index.txt | |
serial = $dir/serial | |
RANDFILE = $dir/private/.rand | |
# The root key and root certificate. | |
private_key = $dir/private/ca.key | |
certificate = $dir/certs/ca.pem | |
# For certificate revocation lists. | |
crlnumber = $dir/crlnumber | |
crl = $dir/crl.pem | |
default_crl_days = 30 | |
# See #CRL_EXT | |
crl_extensions = crl_ext | |
# SHA-1 is deprecated, so use SHA-2 instead. | |
default_md = sha256 | |
name_opt = ca_default | |
cert_opt = ca_default | |
default_days = 365 | |
preserve = no | |
# See #POLICY_STRICT | |
#policy = policy_strict | |
policy = policy_match | |
#################################################################### | |
[ policy_strict ] | |
# #POLICY_STRICT | |
# | |
# The root CA should only sign intermediate certificates that match. | |
# See the POLICY FORMAT section of `man ca`. | |
# | |
# If we wanted to use an intermediary certificate as [2], we would use | |
# We’ll apply policy_strict for all root CA signatures, as the root | |
# CA is only being used to create intermediate CAs. | |
countryName = match | |
stateOrProvinceName = match | |
organizationName = match | |
organizationalUnitName = optional | |
emailAddress = optional | |
commonName = supplied | |
#################################################################### | |
[ policy_loose ] | |
# Allow the intermediate CA to sign a more diverse range of certificates. | |
# See the POLICY FORMAT section of the `ca` man page. | |
# NOT USED YET. This will be useful in [2] | |
countryName = optional | |
stateOrProvinceName = optional | |
localityName = optional | |
organizationName = optional | |
organizationalUnitName = optional | |
commonName = supplied | |
emailAddress = optional | |
#################################################################### | |
[ policy_match ] | |
# What was the original policy assigned to CA_default | |
# NOT USED. Could be used back in policy from CA_default block | |
countryName = match | |
stateOrProvinceName = match | |
organizationName = match | |
organizationalUnitName = optional | |
commonName = supplied | |
emailAddress = optional | |
#################################################################### | |
[ policy_anything ] | |
# For the 'anything' policy | |
# At this point in time, you must list all acceptable 'object' | |
# types. | |
countryName = optional | |
stateOrProvinceName = optional | |
localityName = optional | |
organizationName = optional | |
organizationalUnitName = optional | |
commonName = supplied | |
emailAddress = optional | |
#################################################################### | |
[ req ] | |
# Options for the `req` tool (`man req`) | |
# See also https://openssl.org/docs/manmaster/apps/req.html | |
default_bits = 2048 | |
# See #REQ_DN | |
distinguished_name = req_distinguished_name | |
# This sets a mask for permitted string types. There are several options. | |
# default: PrintableString, T61String, BMPString. | |
# pkix : PrintableString, BMPString (PKIX recommendation before 2004) | |
# utf8only: only UTF8Strings (PKIX recommendation after 2004). | |
# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). | |
# MASK:XXXX a literal mask value. | |
# WARNING: ancient versions of Netscape crash on BMPStrings or UTF8Strings. | |
string_mask = utf8only | |
# SHA-1 is deprecated, so use SHA-2 instead. | |
default_md = sha256 | |
# Extension to add when the -x509 option is used | |
# this specifies the configuration file section | |
# containing a list of extensions to add to certificate | |
# generated when the -x509 switch is used. | |
# It can be overridden by the -extensions command line switch. | |
# See #EXT_V3_CA | |
x509_extensions = v3_ca | |
# See #REQ_ATTR | |
attributes = req_attributes | |
#################################################################### | |
[ req_distinguished_name ] | |
# #REQ_DN | |
# | |
# See <https://en.wikipedia.org/wiki/Certificate_signing_request> | |
countryName = Country Name (2 letter code) | |
countryName_default = US | |
countryName_min = 2 | |
countryName_max = 2 | |
stateOrProvinceName = State or Province Name (full name) | |
stateOrProvinceName_default = New-York | |
localityName = Locality Name (eg, city) | |
localityName_default = New-York | |
0.organizationName = Second Organization Name (eg, company) | |
0.organizationName_default = {{ SUBJ_O }} | |
1.organizationName = Organization Name (eg, company) | |
1.organizationName_default = {{ SUBJ_OU }} | |
organizationalUnitName = Organizational Unit Name (eg, section) | |
organizationalUnitName_default = {{ SUBJ_OU }} Delivery Engineering Team | |
commonName = Common Name (e.g. server FQDN or YOUR name) | |
commonName_max = 64 | |
commonName_default = {{ SUBJ_CN }} | |
emailAddress = Email Address | |
emailAddress_max = 64 | |
emailAddress_default = {{ SUBJ_EMAIL }} | |
#################################################################### | |
[ req_attributes ] | |
# #REQ_ATTR | |
# | |
challengePassword = A challenge password | |
challengePassword_min = 4 | |
challengePassword_max = 20 | |
#################################################################### | |
[ usr_cert ] | |
# These extensions are added when 'ca' signs a request. | |
# Extensions for client certificates (`man x509v3_config`). | |
# This goes against PKIX guidelines but some CAs do it and some software | |
# requires this to avoid interpreting an end user certificate as a CA. | |
# NOT USED YET. This will be useful in [3] | |
basicConstraints = CA:FALSE | |
nsCertType = client, email | |
subjectKeyIdentifier = hash | |
authorityKeyIdentifier = keyid,issuer | |
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment | |
extendedKeyUsage = clientAuth, emailProtection | |
nsComment = "Internal {{ SUBJ_OU }} Client Certificate" | |
#################################################################### | |
[ server_cert ] | |
# Apply the server_cert extension when signing server | |
# certificates, such as those used for web servers. | |
# Extensions for server certificates (`man x509v3_config`) | |
# NOT USED YET. This will be useful in [2] and [4] | |
basicConstraints = CA:FALSE | |
nsCertType = server | |
nsComment = "Internal {{ SUBJ_OU }} Web Server Certificate" | |
subjectKeyIdentifier = hash | |
authorityKeyIdentifier = keyid,issuer:always | |
keyUsage = critical, digitalSignature, keyEncipherment | |
extendedKeyUsage = serverAuth | |
#################################################################### | |
[ ocsp ] | |
# Extension for OCSP signing certificates (`man ocsp`) | |
# Apply the ocsp extension when signing the Online Certificate | |
# Status Protocol (OCSP) certificate | |
basicConstraints = CA:FALSE | |
subjectKeyIdentifier = hash | |
authorityKeyIdentifier = keyid,issuer | |
keyUsage = critical, digitalSignature | |
extendedKeyUsage = critical, OCSPSigning | |
#################################################################### | |
[ v3_req ] | |
# Extensions to add to a certificate request | |
basicConstraints = CA:FALSE | |
keyUsage = nonRepudiation, digitalSignature, keyEncipherment | |
#################################################################### | |
[ v3_ca ] | |
# #EXT_V3_CA | |
# | |
# What gets applied when signing certificates. | |
# For example, passing the -extensions v3_ca | |
# command-line argument will apply the options | |
# set in this section. | |
# Extensions for a typical CA (`man x509v3_config`) | |
subjectKeyIdentifier = hash | |
authorityKeyIdentifier = keyid:always,issuer | |
basicConstraints = critical, CA:true | |
keyUsage = critical, digitalSignature, cRLSign, keyCertSign | |
#################################################################### | |
[ v3_intermediate_ca ] | |
# Extensions for a typical intermediate CA (`man x509v3_config`) | |
# Apply the v3_ca_intermediate extension when we create an intermediate | |
# certificate. | |
# pathlen:0 ensures that there can be no further certificate | |
# authorities below the intermediate CA [2]. | |
# NOT USED YET. This will be useful in [2] | |
subjectKeyIdentifier = hash | |
authorityKeyIdentifier = keyid:always,issuer | |
basicConstraints = critical, CA:true, pathlen:0 | |
keyUsage = critical, digitalSignature, cRLSign, keyCertSign | |
#################################################################### | |
[ crl_ext ] | |
# #CRL_EXT | |
# | |
# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. | |
# The crl_ext extension is automatically applied when creating | |
# certificate revocation lists. | |
# issuerAltName=issuer:copy | |
authorityKeyIdentifier=keyid:always |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{%- set parent_hostname = salt['pillar.get']('local:parent_hostname', 'localhost.local') -%} | |
{%- set CAtop = './ca' -%} | |
{%- set CA_SECRET = salt['pillar.get']('local:ca_secret', 'Fooo') -%} | |
{%- set fqdn = 'noc.' ~ parent_hostname -%} | |
{%- set SUBJ_EMAIL = 'team-devops@example.org' %} | |
## We cannot set SUBJ_OU, SUBJ_O with spaces here | |
## because newca.sh and newcert.sh would break. | |
{%- set SUBJ_O = 'ExampleOrg' -%} | |
{%- set SUBJ_OU = 'ExampleDept' %} | |
Install OpenSSL: | |
pkg.installed: | |
- name: openssl | |
Backup /etc/ssl/openssl.cnf: | |
cmd.run: | |
- name: cp /etc/ssl/openssl.cnf /etc/ssl/openssl.cnf.orig | |
- creates: /etc/ssl/openssl.cnf.orig | |
Rewrite /etc/ssl/openssl.cnf: | |
file.managed: | |
- name: /etc/ssl/openssl.cnf | |
- source: salt://openssl/files/openssl.cnf.jinja | |
- template: jinja | |
- context: | |
CATOP: {{ CAtop }} | |
SUBJ_CN: {{ fqdn }} | |
SUBJ_EMAIL: {{ SUBJ_EMAIL }} | |
SUBJ_O: {{ SUBJ_O }} | |
SUBJ_OU: {{ SUBJ_OU }} | |
# Follow conventions from /etc/ssl/openssl.conf | |
# we can change those later if we don't like the mention | |
# demoCA in the paths. | |
Ensure OpenSSL CA exists: | |
cmd.script: | |
- cwd: /etc/ssl | |
- unless: test -f {{ CAtop }}/private/ca.key | |
- source: salt://openssl/scripts/newca.sh | |
### If you want to see more in the output | |
#- SHOW_DETAILS: "1" | |
#- SHOW_COMMANDS: "1" | |
- env: | |
- KEY_SECRET: {{ CA_SECRET }} | |
- CATOP: {{ CAtop }} | |
- SUBJ_CN: {{ fqdn }} | |
- SUBJ_EMAIL: {{ SUBJ_EMAIL }} | |
- SUBJ_O: {{ SUBJ_O }} | |
- SUBJ_OU: {{ SUBJ_OU }} | |
Ensure file ownership are applied: | |
cmd.wait: | |
- cwd: /etc/ssl | |
- template: jinja | |
- watch: | |
- cmd: Ensure OpenSSL CA exists | |
- name: | | |
chmod -R 700 {{ CAtop }}/private && \ | |
chmod 400 {{ CAtop }}/private/ca.key |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{%- set parent_hostname = salt['pillar.get']('local:parent_hostname', 'localhost.local') -%} | |
{%- set CAtop = './ca' -%} | |
{%- set KEY_SECRET = salt['pillar.get']('local:key_secret', 'Fooo') -%} | |
{%- set SUBJ_EMAIL = 'team-devops@example.org' %} | |
{%- set project_repo_dir = '/srv/webapps/projects' -%} | |
{%- set certs_copy_dir = '/srv/webapps/certs' -%} | |
{%- set projects_repos = salt['pillar.get']('projects', []) -%} | |
{%- from "basesystem/macros/git.sls" import git_latest -%} | |
{%- set settings = { | |
"mirror": True, | |
"user": "webapps" | |
} %} | |
{% for slug,obj in projects_repos.items() %} | |
{% do obj.update(settings) %} | |
{{ git_latest(project_repo_dir ~ '/' ~ slug, obj.origin, obj) }} | |
{%- set fqdn = slug ~ '.' ~ parent_hostname -%} | |
Create SSL certificate at {{ CAtop }}/certs/{{ slug }}.pem: | |
cmd.script: | |
- cwd: /etc/ssl | |
- unless: test -f {{ CAtop }}/certs/{{ slug }}.pem | |
- source: salt://openssl/scripts/newcert.sh | |
- env: | |
- KEY_SECRET: {{ KEY_SECRET }} | |
### If you want to see more in the output | |
#- SHOW_DETAILS: "1" | |
#- SHOW_COMMANDS: "1" | |
- SLUG: {{ slug }} | |
- CATOP: {{ CAtop }} | |
- SUBJ_CN: {{ fqdn }} | |
- SUBJ_EMAIL: {{ SUBJ_EMAIL }} | |
#Ensure file ownership for {{ slug }} certificates are applied: | |
# cmd.wait: | |
# - cwd: /etc/ssl | |
# - template: jinja | |
# - watch: | |
# - cmd: Create SSL certificate at {{ CAtop }}/certs/{{ slug }}.pem | |
# - name: | | |
# chmod 400 {{ CAtop }}/private/{{ slug }}key.pem && \ | |
# chmod 400 {{ CAtop }}/certs/{{ slug }}.pem | |
Copy {{ CAtop }}/certs/{{ slug }}.pem to {{ certs_copy_dir }}/: | |
cmd.run: | |
- unless: diff {{ CAtop }}/certs/{{ slug }}.pem {{ certs_copy_dir }}/{{ slug }}.pem 1> /dev/null | |
- cwd: /etc/ssl | |
- name: | | |
mkdir -p {{ certs_copy_dir }} && \ | |
cp {{ CAtop }}/certs/{{ slug }}.pem{,.txt} {{ certs_copy_dir }}/ && \ | |
cp {{ CAtop }}/private/{{ slug }}.insecure.key {{ certs_copy_dir }}/{{ slug }}.key | |
# chown -R webapps:webapps {{ certs_copy_dir }} && \ | |
# chmod -R 644 {{ certs_copy_dir }} | |
# chown root:ssl-cert /etc/ssl/private/{{ slug }}key.pem | |
# chmod 640 /etc/ssl/private/{{ slug }}key.pem | |
{% endfor %} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
set -e | |
locale-gen en_US.utf8 | |
apt-get update;apt-get -y upgrade;apt-get -y dist-upgrade;apt-get autoremove -y | |
apt-get install -y apache2 mysql-client mysql-server php5 php5-xcache php5-mysqlnd php5-cli curl openssl libapache2-mod-php5 php5-mcrypt | |
a2enmod ssl | |
mkdir -p /srv/webapps/simplesamlphp | |
cd /srv/webapps/simplesamlphp | |
wget https://simplesamlphp.org/res/downloads/simplesamlphp-1.14.3.tar.gz | |
tar xfz simplesamlphp-1.14.3.tar.gz | |
mv simplesamlphp-1.14.3 current | |
cd current/cert | |
export SUBJ_ALIAS="uat-saml" | |
export SUBJ_EMAIL="hello@renoirboulanger.com" | |
export SUBJ_CN="${SUBJ_ALIAS}.eastus.cloudapp.azure.com" | |
export SITE_KEY_SECRET="Fooo" | |
export SSLEAY_CONFIG=" -passout env:SITE_KEY_SECRET -subj /C=CA/ST=QC/L=Montreal/O=Genero/OU=Engineering/CN=${SUBJ_CN}/emailAddress=${SUBJ_EMAIL}" | |
/usr/lib/ssl/misc/CA.sh -newcert | |
openssl rsa -passin env:SITE_KEY_SECRET -in newkey.pem -out ${SUBJ_ALIAS}.key | |
rm newkey.pem | |
mv newcert.pem ${SUBJ_ALIAS}.pem | |
openssl x509 -noout -text -in ${SUBJ_ALIAS}.pem > ${SUBJ_ALIAS}.pem.txt | |
ln -s uat-saml.pem server.crt | |
chown -R www-data:www-data /srv/webapps/simplesamlphp | |
(cat <<- _EOF_ | |
<VirtualHost *:80> | |
ServerName ${SUBJ_CN} | |
DocumentRoot /var/www/html | |
Include /etc/apache2/projects.d/simplesaml.conf | |
CustomLog /var/log/apache2/simplesaml_access.log combined | |
ErrorLog \${APACHE_LOG_DIR}/simplesaml_error.log | |
CustomLog \${APACHE_LOG_DIR}/simplesaml_access.log combined | |
</VirtualHost> | |
<VirtualHost *:443> | |
ServerName ${SUBJ_CN} | |
DocumentRoot /var/www/html | |
Include /etc/apache2/projects.d/simplesaml.conf | |
Include /etc/apache2/projects.d/simplesaml_ssl.conf | |
CustomLog /var/log/apache2/simplesaml_access_ssl.log combined | |
ErrorLog \${APACHE_LOG_DIR}/simplesaml_error.log | |
CustomLog \${APACHE_LOG_DIR}/simplesaml_access.log combined | |
</VirtualHost> | |
_EOF_ | |
) > /etc/apache2/sites-enabled/simplesaml.conf | |
(cat <<- _EOF_ | |
ServerTokens Minimal | |
ServerSignature Off | |
_EOF_ | |
) > /etc/apache2/conf-enabled/security.conf | |
mkdir -p /etc/apache2/projects.d/ | |
(cat <<- _EOF_ | |
SSLEngine on | |
SSLCertificateFile /srv/webapps/simplesamlphp/current/cert/${SUBJ_ALIAS}.pem | |
SSLCertificateKeyFile /srv/webapps/simplesamlphp/current/cert/${SUBJ_ALIAS}.key | |
_EOF_ | |
) > /etc/apache2/projects.d/simplesaml_ssl.conf | |
(cat <<- _EOF_ | |
LogLevel info | |
Alias /simplesaml /srv/webapps/simplesamlphp/current/www | |
<Directory "/srv/webapps/simplesamlphp/current/www"> | |
Require all granted | |
</Directory> | |
SetEnv SIMPLESAMLPHP_CONFIG_DIR "/srv/webapps/simplesamlphp/current/config" | |
_EOF_ | |
) > /etc/apache2/projects.d/simplesaml.conf | |
rm /etc/apache2/sites-enabled/000-default.conf | |
service apache2 restart |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment