-
-
Save jameswhite/4c15c9b99819e18bb5d3 to your computer and use it in GitHub Desktop.
This file contains hidden or 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 | |
DOMAIN=$1; shift | |
if [ -z "${DOMAIN}" ]; then | |
echo "No domain specified, assuming github.net" | |
DOMAIN="github.net" | |
fi | |
BASE=$(pwd) | |
ROOT_CA_KEYSIZE=4096 | |
MID_CA_KEYSIZE=4096 | |
HOST_KEYSIZE=2048 | |
CA_TREE_TRUNK="${BASE}/certificate_authority" | |
VAULT_DIR="${BASE}/vault" | |
WEB_ROOT="${BASE}/www" | |
SSL_ROOT="${BASE}/ssl" | |
for elf in `echo "dig openssl gpg"`; do | |
if [ -z $(which ${elf}) ];then | |
echo "${elf} not found. Aborting..."; | |
exit -1 | |
fi | |
done | |
# abort if the trunk is already in place | |
if [ -d ${CA_TREE_TRUNK}/root-ca.${DOMAIN} ];then | |
echo "I've already got a pki infrastructure... Aborting" | |
exit 0; | |
fi | |
################################################################### | |
# These need to be set up in DNS or exported, or live with the defaults | |
################################################################### | |
[ -z "${CA_COUNTRY}" ] && CA_COUNTRY=$(dig +short -t txt ca-country.${DOMAIN}|sed -e's/"//g'); [ -z "${CA_COUNTRY}" ] && CA_COUNTRY="US" | |
[ -z "${CA_STATE}" ] && CA_STATE=$(dig +short -t txt ca-state.${DOMAIN}|sed -e's/"//g'); [ -z "${CA_STATE}" ] && CA_STATE="California" | |
[ -z "${CA_LOCALITY}" ] && CA_LOCALITY=$(dig +short -t txt ca-locality.${DOMAIN}|sed -e's/"//g'); [ -z "${CA_LOCALITY}" ] && CA_LOCALITY="San Francisco" | |
[ -z "${CA_ORG}" ] && CA_ORG=$(dig +short -t txt ca-org.${DOMAIN}|sed -e's/"//g'); [ -z "${CA_ORG}" ] && CA_ORG="GitHub Inc." | |
[ -z "${CA_ORGUNIT}" ] && CA_ORGUNIT=$(dig +short -t txt ca-orgunit.${DOMAIN}|sed -e's/"//g'); [ -z "${CA_ORGUNIT}" ] && CA_ORGUNIT="Information Security" | |
[ -z "${CA_EMAIL}" ] && CA_EMAIL=$(dig +short -t txt ca-email.${DOMAIN}|sed -e's/"//g'); [ -z "${CA_EMAIL}" ] && CA_ORGUNIT="[email protected]" | |
[ -z "${CA_CRL}" ] && CA_EMAIL=$(dig +short -t txt ca-crl.${DOMAIN}|sed -e's/"//g'); [ -z "${CA_CRL}" ] && CA_CRL="github-ca.s3.amazonaws.com/${DOMAIN}/crl" | |
if [ -z "${SECRET}" ]; then SECRET=$(/${HOME}/bin/secret); fi | |
if [ -z "${SECRET}" ]; then | |
echo "please set SECRET" | |
exit 1; | |
fi | |
################################################################### | |
# We use the same secret for everything that we do on a system. | |
################################################################### | |
WORKDIR="${BASE}/${DOMAIN}" | |
[ ! -d "${WORKDIR}" ] && mkdir -p "${WORKDIR}" | |
################################################################### | |
# OpenSSL configuration Template | |
################################################################### | |
if [ ! -f "${WORKDIR}/openssl.tpl" ] ;then | |
cat<<EOTPL > ${WORKDIR}/openssl.tpl | |
HOME = . | |
RANDFILE = \$ENV::HOME/.rnd | |
DOMAIN = ${DOMAIN} | |
ca-domain = ~LEVEL~.${DOMAIN} | |
[ ca ] | |
default_ca = CA_default # The default ca section | |
[ CA_default ] | |
dir = . | |
certs = \$dir/certs | |
crl_dir = \$dir/crl | |
database = \$dir/index.txt | |
new_certs_dir = \$dir/newcerts | |
certificate = \$dir/~LEVEL~.\${DOMAIN}.pem | |
serial = \$dir/serial | |
crlnumber = \$dir/crlnumber | |
crl = \$dir/crl.\${DOMAIN}.pem | |
private_key = \$dir/private/~LEVEL~.\${DOMAIN}.key | |
RANDFILE = \$dir/private/.rand | |
x509_extensions = usr_cert | |
name_opt = ca_default | |
cert_opt = ca_default | |
default_days = ~DAYS~ | |
default_crl_days= ~DAYS~ | |
default_md = sha1 | |
preserve = no | |
policy = policy_match | |
[ policy_match ] | |
countryName = match | |
stateOrProvinceName = match | |
localityName = match | |
organizationName = match | |
organizationalUnitName = optional | |
commonName = supplied | |
emailAddress = optional | |
[ policy_anything ] | |
countryName = optional | |
stateOrProvinceName = optional | |
localityName = optional | |
organizationName = optional | |
organizationalUnitName = optional | |
commonName = supplied | |
emailAddress = optional | |
[ req ] | |
default_bits = 2048 | |
default_keyfile = \${DOMAIN}.pem | |
distinguished_name = req_distinguished_name | |
attributes = req_attributes | |
x509_extensions = v3_ca | |
[ req_distinguished_name ] | |
countryName = Country Name (2 letter code) | |
countryName_default = ${CA_COUNTRY} | |
countryName_min = 2 | |
countryName_max = 2 | |
stateOrProvinceName = State or Province Name (full name) | |
stateOrProvinceName_default = ${CA_STATE} | |
localityName = Locality Name (eg, city) | |
localityName_default = ${CA_LOCALITY} | |
0.organizationName = Organization Name (eg, company) | |
0.organizationName_default = ${CA_ORG} | |
organizationalUnitName = Organizational Unit Name (eg, section) | |
organizationalUnitName_default = ~TEXTLEVEL~ | |
commonName = Common Name (eg, YOUR name) | |
commonName_max = 64 | |
commonName_default = ~COMMON_NAME~ | |
emailAddress = Email Address | |
emailAddress_max = 64 | |
emailAddress_default = ~EMAIL~ | |
[ req_attributes ] | |
challengePassword = A challenge password | |
challengePassword_min = 4 | |
challengePassword_max = 20 | |
[ usr_cert ] | |
basicConstraints=CA:FALSE | |
nsComment = "OpenSSL Generated Certificate" | |
subjectKeyIdentifier=hash | |
authorityKeyIdentifier=keyid,issuer | |
nsCaRevocationUrl = ${CA_CRL}/~LEVEL~ | |
[ v3_req ] | |
basicConstraints = CA:FALSE | |
keyUsage = nonRepudiation, digitalSignature, keyEncipherment | |
nsCaRevocationUrl = ${CA_CRL}/~LEVEL~ | |
[ v3_ca ] | |
subjectKeyIdentifier=hash | |
authorityKeyIdentifier=keyid:always,issuer:always | |
basicConstraints = CA:true | |
nsCaRevocationUrl = ${CA_CRL}/~LEVEL~ | |
EOTPL | |
fi | |
################################################################### | |
# Create the Root Certificate Authority | |
################################################################### | |
ROOT_CA="${WORKDIR}/root-ca" | |
if [ ! -d ${ROOT_CA} ];then | |
mkdir -p ${ROOT_CA};fi | |
echo "01" > ${ROOT_CA}/serial | |
cp /dev/null ${ROOT_CA}/index.txt | |
for dir in `echo "certs crl newcerts private"`;do | |
if [ ! -d ${ROOT_CA}/${dir} ];then | |
mkdir ${ROOT_CA}/${dir} | |
fi | |
done | |
sed -e 's/~LEVEL~/root-ca/g' \ | |
-e "s/~COMMON_NAME~/root-ca.${DOMAIN}/g" \ | |
-e 's/~TEXTLEVEL~/Root Certificate Authority/g' \ | |
-e 's/~EMAIL~/certmaster@${DOMAIN}/g' \ | |
-e 's/~DAYS~/3650/g' \ | |
${WORKDIR}/openssl.tpl > ${ROOT_CA}/openssl.cnf | |
# root ca | |
echo ${SECRET} | openssl genrsa -des3 -passout fd:0 \ | |
-out ${ROOT_CA}/private/root-ca.${DOMAIN}.key ${ROOT_CA_KEYSIZE} | |
echo ${SECRET} | openssl req -new -x509 -nodes -sha1 \ | |
-days 3650 -passin fd:0 \ | |
-key ${ROOT_CA}/private/root-ca.${DOMAIN}.key \ | |
-out ${ROOT_CA}/root-ca.${DOMAIN}.pem \ | |
-config ${ROOT_CA}/openssl.cnf -batch | |
################################################################### | |
# Create the Intermediate Certificate Authority | |
################################################################### | |
MID_CA="${WORKDIR}/intermediate-ca" | |
if [ ! -d ${MID_CA} ];then mkdir -p ${MID_CA};fi | |
echo "01" > ${MID_CA}/serial | |
cp /dev/null ${MID_CA}/index.txt | |
for dir in `echo "certs crl newcerts private"`;do | |
if [ ! -d ${MID_CA}/${dir} ];then | |
mkdir ${MID_CA}/${dir} | |
fi | |
done | |
sed -e 's/~LEVEL~/intermediate-ca/g' \ | |
-e "s/~COMMON_NAME~/intermediate-ca.${DOMAIN}/g" \ | |
-e 's/~TEXTLEVEL~/Intermediate Certificate Authority/g' \ | |
-e 's/~EMAIL~/certmaster@${DOMAIN}/g' \ | |
-e 's/~DAYS~/1825/g' \ | |
${WORKDIR}/openssl.tpl > ${MID_CA}/openssl.cnf | |
# mid ca | |
cd ${MID_CA} | |
echo "${SECRET}" | openssl genrsa -des3 -passout fd:0 \ | |
-out ${MID_CA}/private/intermediate-ca.${DOMAIN}.key ${MID_CA_KEYSIZE} | |
echo "${SECRET}" | openssl req -new -sha1 -days 1825 -passin fd:0 \ | |
-key ${MID_CA}/private/intermediate-ca.${DOMAIN}.key \ | |
-out ${MID_CA}/intermediate-ca.${DOMAIN}.csr \ | |
-config ${MID_CA}/openssl.cnf -batch | |
################################################################### | |
# sign the Intermediate CA with the Root CA | |
################################################################### | |
mv ${MID_CA}/intermediate-ca.${DOMAIN}.csr ${ROOT_CA} | |
cd ${ROOT_CA} | |
echo "${SECRET}" | openssl ca -extensions v3_ca -days 1825 \ | |
-passin fd:0 \ | |
-out ${ROOT_CA}/intermediate-ca.${DOMAIN}.crt \ | |
-in ${ROOT_CA}/intermediate-ca.${DOMAIN}.csr \ | |
-config ${ROOT_CA}/openssl.cnf -batch | |
# create the chain | |
cat ${ROOT_CA}/intermediate-ca.${DOMAIN}.crt ${ROOT_CA}/root-ca.${DOMAIN}.pem > ${MID_CA}/${DOMAIN}-trust-chain.crt | |
# put them back where they go | |
mv ${ROOT_CA}/intermediate-ca.${DOMAIN}.crt ${MID_CA}/intermediate-ca.${DOMAIN}.pem | |
mv ${ROOT_CA}/intermediate-ca.${DOMAIN}.csr ${MID_CA}/intermediate-ca.${DOMAIN}.csr | |
################################################################### | |
# Create the Domain Certificate Authority for $(dnsdomainname) | |
################################################################### | |
DOM_CA="${WORKDIR}/domain-ca" | |
if [ ! -d ${DOM_CA} ];then mkdir -p ${DOM_CA};fi | |
echo "01" > ${DOM_CA}/serial | |
cp /dev/null ${DOM_CA}/index.txt | |
for dir in `echo "certs crl newcerts private"`;do | |
if [ ! -d ${DOM_CA}/${dir} ];then | |
mkdir ${DOM_CA}/${dir} | |
fi | |
done | |
sed -e "s/~LEVEL~/domain-ca/g" \ | |
-e "s/~COMMON_NAME~/domain-ca.${DOMAIN}/g" \ | |
-e "s/~TEXTLEVEL~/Domain Certificate Authority/g" \ | |
-e 's/~EMAIL~/certmaster@${DOMAIN}/g' \ | |
-e 's/~DAYS~/1095/g' \ | |
${WORKDIR}/openssl.tpl > ${DOM_CA}/openssl.cnf | |
# domain ca | |
cd ${DOM_CA} | |
# the domain ca key doesn't get a passphrase: | |
openssl genrsa -out ${DOM_CA}/private/domain-ca.${DOMAIN}.key ${DOM_CA_KEYSIZE} | |
echo "${SECRET}" | openssl req -new -sha1 -days 1095 -passin fd:0 \ | |
-key ${DOM_CA}/private/domain-ca.${DOMAIN}.key \ | |
-out ${DOM_CA}/domain-ca.${DOMAIN}.csr \ | |
-config ${DOM_CA}/openssl.cnf -batch | |
################################################################### | |
# sign the Domain CA with the Intermediate CA | |
################################################################### | |
mv ${DOM_CA}/domain-ca.${DOMAIN}.csr ${MID_CA} | |
cd ${MID_CA} | |
echo "${SECRET}" | openssl ca -extensions v3_ca -days 1825 \ | |
-passin fd:0 \ | |
-out ${MID_CA}/domain-ca.${DOMAIN}.crt \ | |
-in ${MID_CA}/domain-ca.${DOMAIN}.csr \ | |
-config ${MID_CA}/openssl.cnf -batch | |
mv ${MID_CA}/domain-ca.${DOMAIN}.crt ${DOM_CA}/domain-ca.${DOMAIN}.pem | |
mv ${MID_CA}/domain-ca.${DOMAIN}.csr ${DOM_CA}/domain-ca.${DOMAIN}.csr | |
cat ${DOM_CA}/domain-ca.${DOMAIN}.pem ${MID_CA}/intermediate-ca.${DOMAIN}.pem \ | |
${ROOT_CA}/root-ca.${DOMAIN}.pem > ${DOM_CA}/${DOMAIN}-trust-chain.crt | |
################################################################### | |
# Create Server Certificates for hosts | |
################################################################### | |
while [ ! -z "$*" ]; do | |
HNAME=$1; shift 1 | |
MY_CERT="${WORKDIR}/server_certificates/${HNAME}" | |
if [ ! -d ${MY_CERT} ];then mkdir -p ${MY_CERT};fi | |
sed -e "s/~LEVEL~//g" \ | |
-e "s/~COMMON_NAME~/${HNAME}/g" \ | |
-e "s/~TEXTLEVEL~/${CA_ORGUNIT}/g" \ | |
-e "s/~EMAIL~/${CA_EMAIL}/g" \ | |
-e 's/~DAYS~/365/g' \ | |
${WORKDIR}/openssl.tpl > ${MY_CERT}/openssl.cnf | |
echo ${SECRET} | openssl genrsa -des3 -passout fd:0 -out ${MY_CERT}/${HNAME}.key ${HOST_KEYSIZE} | |
echo ${SECRET} | openssl req -new -key ${MY_CERT}/${HNAME}.key \ | |
-passin fd:0 \ | |
-out ${MY_CERT}/${HNAME}.csr \ | |
-config ${MY_CERT}/openssl.cnf -batch | |
################################################################### | |
# Sign Server Certificate with Domain Cerificate Authority | |
################################################################### | |
mv ${MY_CERT}/${HNAME}.csr ${DOM_CA} | |
# sign server cert with intermediate cert | |
cd ${DOM_CA} | |
openssl ca -config ${DOM_CA}/openssl.cnf \ | |
-policy policy_anything \ | |
-out ${DOM_CA}/${HNAME}.crt \ | |
-batch \ | |
-infiles ${DOM_CA}/${HNAME}.csr | |
mv ${DOM_CA}/${HNAME}.crt ${MY_CERT} | |
mv ${DOM_CA}/${HNAME}.csr ${MY_CERT} | |
echo ${SECRET} | openssl pkcs12 -export -passin fd:0 -passout pass:$(secret) -out ${MY_CERT}/${HNAME}.pfx -inkey ${MY_CERT}/${HNAME}.key -in ${MY_CERT}/${HNAME}.crt -certfile ${DOM_CA}/${DOMAIN}-trust-chain.crt | |
done | |
exit 0; | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment