diff --git a/README b/README index 05e3404..206e561 100644 --- a/README +++ b/README @@ -12,11 +12,16 @@ This package contains a set of programs to generate an entire certificate chain of trust and will configure StrongSwan server. .p12 files are generated for client distribution. -Features: - * Certificate Authority (CA) creation - * Server and Client certificate generation (based on CA) - * CA and Client certificate packaged as .p12 file for easy import to Android (other clients too) - * Ubuntu networking configuration scripts (tunneling enabled) +There are two main applications contained in this project. + * MOB Hub System : PKI Bootstrap + - 1 x Certificate Authority (CA) generation + - 5 x CA Intermediate generation + - 10 x Server and Client certificate generation (based on CA-I) + - CA, CA-I, Server, and Client certificate packaged as .p12 file for easy import to Android (other clients too) + + * MOB Hub System : PKI Lifecycle + - Unlimited CA Intermediate generation + - Unlimited Server and Client generation (based on CA-I) @@ -24,12 +29,13 @@ Features: VERSIONS --------------------- -Version 3.1 - MOB Hub PKI - * PKI Bootstrap - - generate an entire chain-of-trust +Ver 3.2 - MOB Hub PKI Lifecycle * PKI Lifecycle - generate certificates during the CA's lifecycle -Version 3.0 - CA Intermediate Support +Ver 3.1 - MOB Hub PKI Bootstrap + * PKI Bootstrap + - generate an entire chain-of-trust +Ver 3.0 - CA Intermediate Support * requires openssl (does not require ipsec) * CA Intermediate support -root CA can be generated with 5-10yr expiration, put into cold-storage @@ -61,17 +67,3 @@ Make sure your server date is within the CA, and Server certificate valid date. ---------------- - - ------------- - HISTORY ------------- -version 3.x - * strongswan: new configuration that uses DN (distinguished name) to authenticate clients - (previous configs used local IP address for authentication) - * certificate generation moved to another repository - - separated into two stages - stage 1 : pki bootstrap - stage 2 : pki lifecycle - - diff --git a/src/pki_bootstrap/cert_bootstrap.sh b/src/pki_bootstrap/pki_bootstrap.sh similarity index 97% rename from src/pki_bootstrap/cert_bootstrap.sh rename to src/pki_bootstrap/pki_bootstrap.sh index 2132f33..711add1 100755 --- a/src/pki_bootstrap/cert_bootstrap.sh +++ b/src/pki_bootstrap/pki_bootstrap.sh @@ -1,6 +1,6 @@ #!/bin/bash # -# ACME Certificate Bootstrap v1.3 +# ACME PKI (Certificate) Bootstrap v1.3 # # This script will generate all the files necessary to build a certificate chain of trust # using a CA, CA Intermediate, Server, and Client certificates. After the bootstrap the other @@ -14,9 +14,9 @@ usage() { echo "using a CA, CA Intermediate, Server, and Client certificates. After the bootstrap the other" echo "helper scripts will generate new certificates" echo - echo "Usage: cert_bootstrap <.cnf file (minus the .cnf)>" + echo "Usage: pki_bootstrap <.cnf file (minus the .cnf)>" echo - echo "Example: cert_bootstrap org.acme.xyz" + echo "Example: pki_bootstrap org.acme.xyz" exit 1 } @@ -240,20 +240,20 @@ organize() { # gen_pki_certs() { B_SERIAL=$1 - NUM_CERTS=$2 + NUM_CERTS=$(($2-1)) # Create CA Intermediate UNIQ_ID_CA="${B_SERIAL}.${ORG_URL}" generate_ca_i $UNIQ_ID_CA $B_SERIAL # Server Certificates - for NUM in $(seq 1 $2) + for NUM in $(seq 0 $NUM_CERTS) do generate_server "$((B_SERIAL+NUM)).${ORG_URL}" $UNIQ_ID_CA $((B_SERIAL+NUM)) done # Client Certificates - for NUM in $(seq 1 $2) + for NUM in $(seq 0 $NUM_CERTS) do generate_client "$((B_SERIAL+NUM)).${ORG_URL}" $UNIQ_ID_CA $((B_SERIAL+NUM)) done diff --git a/src/pki_bootstrap/pki_funcs.sh b/src/pki_bootstrap/pki_funcs.sh new file mode 100644 index 0000000..cbd0c79 --- /dev/null +++ b/src/pki_bootstrap/pki_funcs.sh @@ -0,0 +1,137 @@ +#!/bin/bash +# +# all main functions to generate a PKI certificate chain +# + +echo_block() { + echo + echo + echo "***** ***** ***** *****" + echo $1 + echo "***** ***** ***** *****" +} + +# ***** ***** ***** ***** ***** +# +# CERTIFICATE AUTHORITY (CA) +# +# ***** ***** ***** ***** ***** +# This function will generate a CA Intermediate +# IN: UNIQ_ID_CA, SERIAL +# +generate_ca() { + # params + UNIQ_ID_CA=$1 + SERIAL=$2 + # encrypt the key + #openssl genrsa -aes256 -out ca.keys.pem 4096 + #openssl genrsa -aes256 -password "pass:password" -out ca.keys.pem 4096 + + # key un-protected + openssl genrsa -out "ca_${UNIQ_ID_CA}.keys.pem" 4096 + # + # Create Certificate (valid for 10 years, after the entire chain of trust expires) + openssl req -config $CA_CNF -new -x509 -sha256 -days 3650 -extensions v3_ca \ + -subj "/C=OO/O=ACME/CN=root.${UNIQ_ID_CA}" -set_serial ${SERIAL} \ + -key ca_${UNIQ_ID_CA}.keys.pem -out ca_${UNIQ_ID_CA}.crt.pem + + # verify certificate (output to text file for review) + openssl x509 -noout -text -in ca_${UNIQ_ID_CA}.crt.pem > ca_${UNIQ_ID_CA}_cert.info.txt +} + +# +# Create CA Intermediate +# +# +# This function will generate a CA Intermediate +# IN: UNIQ_ID_CA, SERIAL +# +generate_ca_i() { + echo_block "Create CA Intermediate (${UNIQ_ID_CA})" + # params + UNIQ_ID_CA=$1 + SERIAL=$2 + + openssl genrsa -out "ca_i_${UNIQ_ID_CA}.keys.pem" 4096 + + # Create Cert Signing Request (CSR) + openssl req -config $CA_CNF -new -sha256 \ + -subj "/C=OO/O=ACME/OU=ACME Intermediate/CN=${UNIQ_ID_CA}" \ + -key "ca_i_${UNIQ_ID_CA}.keys.pem" -out "ca_i_${UNIQ_ID_CA}.csr.pem" + + # Create Certificate (valid for ~2 years, after the entire chain of trust expires) + # CA signs Intermediate + openssl x509 -req -days 750 -extfile $CA_CNF -extensions v3_ca_i \ + -CA $FQ_CA_CERT -CAkey $FQ_CA_KEYS -set_serial ${SERIAL} \ + -in "ca_i_${UNIQ_ID_CA}.csr.pem" -out "ca_i_${UNIQ_ID_CA}.crt.pem" + + # Package the Certificate Authority Certificates for distro (windoze needs this) + openssl pkcs12 -export -password "pass:password" -inkey "ca_i_${UNIQ_ID_CA}.keys.pem" \ + -name "CA Intermediate Mobile Provision" -certfile $FQ_CA_CERT \ + -in "ca_i_${UNIQ_ID_CA}.crt.pem" -out "ca_i_${UNIQ_ID_CA}.p12" + + # verify certificate (output to text file for review) + openssl x509 -noout -text -in "ca_i_${UNIQ_ID_CA}.crt.pem" > "ca_i_${UNIQ_ID_CA}_crt_info.txt" + + # create certifiate chain + cat $FQ_CA_CERT "ca_i_${UNIQ_ID_CA}.crt.pem" > "ca_cert-chain_${UNIQ_ID_CA}.crts.pem" +} +# +# Generate a Server Certificate +# IN: UNIQ_ID, UNIQ_ID_CA, SERIAL +# +generate_server() { + echo_block "Generate Server Certificates (${UNIQ_ID})" + # params + UNIQ_ID=$1 + UNIQ_ID_CA=$2 + SERIAL=$3 + + openssl genrsa -out "server_${UNIQ_ID}.keys.pem" 4096 + + openssl req -new -config $FQ_S_CNF -key "server_${UNIQ_ID}.keys.pem" \ + -subj "/C=OO/O=ACME/OU=ACME Standard/CN=${UNIQ_ID}" \ + -out "server_${UNIQ_ID}.csr.pem" + + # Intermediate signs Server + openssl x509 -req -days 365 -extfile $FQ_S_CNF -extensions v3_server \ + -CA "ca_i_${UNIQ_ID_CA}.crt.pem" -CAkey "ca_i_${UNIQ_ID_CA}.keys.pem" -set_serial ${SERIAL} \ + -in "server_${UNIQ_ID}.csr.pem" -out "server_${UNIQ_ID}.crt.pem" + + # Package the Certificates + openssl pkcs12 -export -password "pass:password" -inkey "server_${UNIQ_ID}.keys.pem" \ + -name "Server ${UNIQ_ID} VPN Certificate" -certfile "ca_cert-chain_${UNIQ_ID_CA}.crts.pem" -caname "server_${UNIQ_ID}@acme.xyz" \ + -in "server_${UNIQ_ID}.crt.pem" -out "server_${UNIQ_ID}.p12" + + # verify certificate (output to text file for review) + openssl x509 -noout -text -in "server_${UNIQ_ID}.crt.pem" > "server_${UNIQ_ID}.crt.info.txt" +} +# +# Generate a Client Certificate +# IN: UNIQ_ID, UNIQ_ID_CA, SERIAL +# +generate_client() { + echo_block "Generate Client Certificates (${UNIQ_ID})" + # params + UNIQ_ID=$1 + UNIQ_ID_CA=$2 + SERIAL=$3 + + openssl genrsa -out "client_${UNIQ_ID}.keys.pem" 4096 + + openssl req -new -key "client_${UNIQ_ID}.keys.pem" \ + -subj "/C=OO/O=ACME/OU=ACME Standard/CN=client_${UNIQ_ID}" \ + -out "client_${UNIQ_ID}.csr.pem" + # Intermediate signs Client + openssl x509 -req -days 365 \ + -CA "ca_i_${UNIQ_ID_CA}.crt.pem" -CAkey "ca_i_${UNIQ_ID_CA}.keys.pem" -set_serial ${SERIAL} \ + -in "client_${UNIQ_ID}.csr.pem" -out "client_${UNIQ_ID}.crt.pem" + + # Package the Certificates + openssl pkcs12 -export -password "pass:password" -inkey "client_${UNIQ_ID}.keys.pem" \ + -name "Client ${UNIQ_ID} VPN Certificate" -certfile "ca_cert-chain_${UNIQ_ID_CA}.crts.pem" -caname "client_${UNIQ_ID}@acme.xyz" \ + -in "client_${UNIQ_ID}.crt.pem" -out "client_${UNIQ_ID}.p12" + + # verify certificate (output to text file for review) + openssl x509 -noout -text -in "client_${UNIQ_ID}.crt.pem" > "client_${UNIQ_ID}.info.txt" +} diff --git a/src/pki_lifecycle/ca-i/gen_ca-i.sh b/src/pki_lifecycle/ca-i/gen_ca-i.sh index 8523602..4eca6d6 100755 --- a/src/pki_lifecycle/ca-i/gen_ca-i.sh +++ b/src/pki_lifecycle/ca-i/gen_ca-i.sh @@ -22,8 +22,8 @@ usage() { echo echo " usage: gen_ca-i.sh " echo - echo " example: gen_ca-i.sh skunkworks.acme.xyz \\" - echo " 10052 \\" + echo " example: gen_ca-i.sh skunkworks.acme.xyz" + echo " 10052" echo exit 1 } @@ -67,9 +67,12 @@ generate_ca_i() { cat $FQ_CA_CERT "ca_i_${UNIQ_ID_CA}.crt.pem" > "ca_cert-chain_${UNIQ_ID_CA}.crts.pem" } + main() { - if [[ ! -f ca-i.pem ]] + if [[ ! -f ca-i.pem ]]; then error_no_ca_file + fi + if [[ -n $PARAM1 ]] || [[ -n $PARAM2 ]]; then generate_ca_i $PARAM1 $PARAM2 else diff --git a/src/pki_lifecycle/ca/cnf/192.168.1.3.cnf b/src/pki_lifecycle/ca/cnf/192.168.1.3.cnf deleted file mode 100644 index c6ddfea..0000000 --- a/src/pki_lifecycle/ca/cnf/192.168.1.3.cnf +++ /dev/null @@ -1,56 +0,0 @@ -# -# -# IMPORTANT INFO -# -# -[ v3_server ] -# Extensions for server certificates (`man x509v3_config`). -basicConstraints = CA:FALSE -nsCertType = server -nsComment = "ACME Generated" -subjectKeyIdentifier = hash -authorityKeyIdentifier = keyid,issuer:always -keyUsage = critical, digitalSignature, keyEncipherment -extendedKeyUsage = serverAuth -subjectAltName = IP:192.168.1.3 -#subjectAltName = @san_info - -[ san_info ] -IP = 192.168.1.3 - - -# -# -# FORCED TO INCLUDE THIS JUNK -# -# -[ req ] -# Options for the `req` tool (`man req`). -default_bits = 4096 -distinguished_name = req_distinguished_name -string_mask = utf8only - -# SHA-1 is deprecated, so use SHA-2 instead. -default_md = sha256 - -# Extension to add when the -x509 option is used. -#x509_extensions = v3_ca - -[ req_distinguished_name ] -# See . -countryName = Country Name (2 letter code) -stateOrProvinceName = State or Province Name -localityName = Locality Name -0.organizationName = Organization Name -organizationalUnitName = Organizational Unit Name -commonName = Common Name -emailAddress = Email Address - -# Optionally, specify some defaults. -countryName_default = US -stateOrProvinceName_default = State51 -localityName_default = -0.organizationName_default = ACME R&D -organizationalUnitName_default = -emailAddress_default = - diff --git a/src/pki_lifecycle/ca/cnf/ca.cnf b/src/pki_lifecycle/ca/cnf/ca.cnf deleted file mode 100644 index 691733f..0000000 --- a/src/pki_lifecycle/ca/cnf/ca.cnf +++ /dev/null @@ -1,113 +0,0 @@ -# Root CA configuration file. - -[ ca ] -# `man ca` -default_ca = CA_default - -[ CA_default ] -# SHA-1 is deprecated, so use SHA-2 instead. -default_md = sha256 - -name_opt = ca_default -cert_opt = ca_default -default_days = 375 -preserve = no -policy = policy_strict - -[ policy_strict ] -# The root CA should only sign intermediate certificates that match. -# See the POLICY FORMAT section of `man ca`. -countryName = match -stateOrProvinceName = match -organizationName = match -organizationalUnitName = optional -commonName = supplied -emailAddress = optional - -[ policy_loose ] -# Allow the intermediate CA to sign a more diverse range of certificates. -# See the POLICY FORMAT section of the `ca` man page. -countryName = optional -stateOrProvinceName = optional -localityName = optional -organizationName = optional -organizationalUnitName = optional -commonName = supplied -emailAddress = optional - -[ req ] -# Options for the `req` tool (`man req`). -default_bits = 4096 -distinguished_name = req_distinguished_name -string_mask = utf8only - -# SHA-1 is deprecated, so use SHA-2 instead. -default_md = sha256 - -# Extension to add when the -x509 option is used. -x509_extensions = v3_ca - -[ req_distinguished_name ] -# See . -countryName = Country Name (2 letter code) -stateOrProvinceName = State or Province Name -localityName = Locality Name -0.organizationName = Organization Name -organizationalUnitName = Organizational Unit Name -commonName = Common Name -emailAddress = Email Address - -# Optionally, specify some defaults. -countryName_default = US -stateOrProvinceName_default = State51 -localityName_default = -0.organizationName_default = ACME R&D -organizationalUnitName_default = -emailAddress_default = - -[ v3_ca ] -# Extensions for a typical CA (`man x509v3_config`). -basicConstraints = critical, CA:true -keyUsage = critical, cRLSign, digitalSignature, keyCertSign -subjectKeyIdentifier = hash -authorityKeyIdentifier = keyid:always,issuer - -[ v3_ca_i ] -# Extensions for a typical intermediate CA (`man x509v3_config`). -basicConstraints = critical, CA:true, pathlen:0 -keyUsage = critical, cRLSign, digitalSignature, keyCertSign -subjectKeyIdentifier = hash -authorityKeyIdentifier = keyid:always,issuer - -[ usr_cert ] -# Extensions for client certificates (`man x509v3_config`). -basicConstraints = CA:FALSE -nsCertType = client, email -nsComment = "ACME Generated" -subjectKeyIdentifier = hash -authorityKeyIdentifier = keyid,issuer -keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment -extendedKeyUsage = clientAuth, emailProtection - -[ server_cert ] -# Extensions for server certificates (`man x509v3_config`). -basicConstraints = CA:FALSE -nsCertType = server -nsComment = "ACME Generated" -subjectKeyIdentifier = hash -authorityKeyIdentifier = keyid,issuer:always -keyUsage = critical, digitalSignature, keyEncipherment -extendedKeyUsage = serverAuth -#subjectAltName = "192.168.123.129" - -[ crl_ext ] -# Extension for CRLs (`man x509v3_config`). -authorityKeyIdentifier=keyid:always - -[ ocsp ] -# Extension for OCSP signing certificates (`man ocsp`). -basicConstraints = CA:FALSE -subjectKeyIdentifier = hash -authorityKeyIdentifier = keyid,issuer -keyUsage = critical, digitalSignature -extendedKeyUsage = critical, OCSPSigning \ No newline at end of file diff --git a/src/pki_lifecycle/ca/cnf/skunkworks.acme.xyz.cnf b/src/pki_lifecycle/ca/cnf/skunkworks.acme.xyz.cnf deleted file mode 100644 index 9bf9706..0000000 --- a/src/pki_lifecycle/ca/cnf/skunkworks.acme.xyz.cnf +++ /dev/null @@ -1,55 +0,0 @@ -# -# -# IMPORTANT INFO -# -# -[ v3_server ] -# Extensions for server certificates (`man x509v3_config`). -basicConstraints = CA:FALSE -nsCertType = server -nsComment = "ACME Corp" -subjectKeyIdentifier = hash -authorityKeyIdentifier = keyid,issuer:always -keyUsage = critical, digitalSignature, keyEncipherment -extendedKeyUsage = serverAuth -subjectAltName = @alt_names -#subjectAltName = IP:192.168.123.129 - -[ alt_names ] -DNS.1 = "skunkworks.acme.xyz" - -# -# -# FORCED TO INCLUDE THIS JUNK -# -# -[ req ] -# Options for the `req` tool (`man req`). -default_bits = 4096 -distinguished_name = req_distinguished_name -string_mask = utf8only - -# SHA-1 is deprecated, so use SHA-2 instead. -default_md = sha256 - -# Extension to add when the -x509 option is used. -#x509_extensions = v3_ca - -[ req_distinguished_name ] -# See . -countryName = Country Name (2 letter code) -stateOrProvinceName = State or Province Name -localityName = Locality Name -0.organizationName = Organization Name -organizationalUnitName = Organizational Unit Name -commonName = Common Name -emailAddress = Email Address - -# Optionally, specify some defaults. -countryName_default = US -stateOrProvinceName_default = State51 -localityName_default = -0.organizationName_default = ACME R&D -organizationalUnitName_default = -emailAddress_default = - diff --git a/src/pki_lifecycle/ca/gen_ca.sh b/src/pki_lifecycle/ca/gen_ca.sh deleted file mode 100644 index cdbea88..0000000 --- a/src/pki_lifecycle/ca/gen_ca.sh +++ /dev/null @@ -1,116 +0,0 @@ -#!/bin/bash -# -# ACME Certificate Authority Generation v1.0 -# -# -PARAM1=$1 - -usage() { - echo - echo "This script will generate all the files necessary to build a certificate chain of trust" - echo "using a CA, CA Intermediate, Server, and Client certificates. After the bootstrap the other" - echo "helper scripts will generate new certificates" - echo - echo "Usage: cert_bootstrap <.cnf file (minus the .cnf)>" - echo - echo "Example: cert_bootstrap org.acme.xyz" - exit 1 -} - -echo_block() { - echo - echo - echo "***** ***** ***** *****" - echo $1 - echo "***** ***** ***** *****" -} - -# -# CA generation requires .cnf files -# create CA directory -# create bash variables to CA -# restore script back to original path -# -app_init() { - if [[ -n $PARAM1 ]]; then - # need to know the location of the configuration file (expected to be in same dir path as this script) - CA_CNF="$CD/ca.cnf" - - # handle the case of having the ".cnf" extension or not - if [[ ${PARAM1: -4} == .cnf ]]; then - ORG_URL=${PARAM1%.*} - S_CNF=${PARAM1} - echo "ASDF: ${ORG_URL}, ${S_CNF}" - else - ORG_URL=$PARAM1 - S_CNF="${PARAM1}.cnf" - echo "ZXCV: ${ORG_URL}, ${S_CNF}" - fi - - FQ_S_CNF="${CD}/${S_CNF}" - if [[ ! -f $FQ_S_CNF ]] || [[ ! -f $CA_CNF ]]; then - usage - fi - else - usage - fi - - # Organize - # - # create a unique path for the server certificate - UNIQ_DIR=`date +%Y-%m-%d.%H_%M_%S` - UNIQ_DIR="cert-chain_${UNIQ_DIR}" - mkdir -p "${UNIQ_DIR}" - cd "${UNIQ_DIR}" - # FQ_DIR="${CD}/${UNIQ_DIR}" -} - -# -# IN: UNIQ_ID_CA, SERIAL -# -one-time-ca() { - # params - SERIAL="101" - UNIQ_ID_CA="${SERIAL}.${ORG_URL}" - CA_DIR="ca_${UNIQ_ID_CA}" - mkdir $CA_DIR - cd $CA_DIR - generate_ca $UNIQ_ID_CA $SERIAL - FQ_CA_DIR=`pwd` - FQ_CA_CERT="${FQ_CA_DIR}/ca_${UNIQ_ID_CA}.crt.pem" - FQ_CA_KEYS="${FQ_CA_DIR}/ca_${UNIQ_ID_CA}.keys.pem" - cd .. -} - -# ***** ***** ***** ***** -# -# CERTIFICATE AUTHORITY -# -# ***** ***** ***** ***** -# This function will generate a CA Intermediate -# IN: UNIQ_ID_CA, SERIAL -# -generate_ca() { - # params - UNIQ_ID_CA=$1 - SERIAL=$2 - # encrypt the key - #openssl genrsa -aes256 -out ca.keys.pem 4096 - #openssl genrsa -aes256 -password "pass:password" -out ca.keys.pem 4096 - - # key un-protected - openssl genrsa -out "ca_${UNIQ_ID_CA}.keys.pem" 4096 - # - # Create Certificate (valid for 10 years, after the entire chain of trust expires) - openssl req -config $CA_CNF -new -x509 -sha256 -days 3650 -extensions v3_ca \ - -subj "/C=OO/O=ACME/CN=root.${UNIQ_ID_CA}" -set_serial ${SERIAL} \ - -key ca_${UNIQ_ID_CA}.keys.pem -out ca_${UNIQ_ID_CA}.crt.pem - - # verify certificate (output to text file for review) - openssl x509 -noout -text -in ca_${UNIQ_ID_CA}.crt.pem > ca_${UNIQ_ID_CA}_cert.info.txt -} - -main() { - -} -