Skip to content

Instantly share code, notes, and snippets.

@renoirb

renoirb/newca.sh Secret

Last active April 29, 2016 18:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save renoirb/de501adc1164e9fec47b257d6ee2a2ff to your computer and use it in GitHub Desktop.
Save renoirb/de501adc1164e9fec47b257d6ee2a2ff to your computer and use it in GitHub Desktop.
Be your own Certification Authority.
#!/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
#!/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}
##
## 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
{%- 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
{%- 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 %}
#!/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