├── .gitignore ├── LICENSE ├── README.md ├── client_cert.sh ├── keystore.sh ├── lan_server.sh ├── openssl.cnf ├── revoke_cert.sh ├── rotate_homeassistant.sh ├── server_cert.sh └── setup_ca.sh /.gitignore: -------------------------------------------------------------------------------- 1 | myCA 2 | *.swp 3 | .env 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014-2017 Sam Gleske 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # My Internal Certificate Authority 2 | 3 | I use this lightweight set of scripts to manage my own internal certificate 4 | authority. I share them with you. My scripts are based off of 5 | [Be your own CA][yourca_tut] and [Docker CA][docker_ca]. 6 | 7 | Features: 8 | 9 | * Manage a personal certificate authority. 10 | * Server SAN certificates ([Subject Alternative Name][wiki_san]). 11 | * Client certificates for TLS [mutual authentication][wiki_ma]. 12 | * Create Java keystores from the X.509 certificates. 13 | 14 | # How to set up 15 | 16 | System requirements 17 | 18 | * GNU/Linux (other platforms untested) 19 | * openssl tools installed 20 | 21 | ### Create the CA 22 | 23 | Execute `setup_ca.sh` from the current directory of the repository. When 24 | executed this will do a few things. It will create the openssl `myCA` directory 25 | structure for a managed certificate authority. All certificate authority 26 | information and management will be located within the `myCA` directory. 27 | 28 | ./setup_ca.sh 29 | 30 | Customize the subject. 31 | 32 | ./setup_ca.sh -subj '/C=US/ST=Pennsylvania/L=Philadelphia/O=Example Domain/OU=Systems/CN=Super Root CA' 33 | 34 | ### Environment variables 35 | 36 | * `CERT_DIR` - the directory where the certificate authority certificates and 37 | other client/server certificates are output. 38 | * `REQ_OPTS` - additional opts to pass to the `openssl req` command in a script. 39 | 40 | e.g. 41 | 42 | CERT_DIR="/tmp/myCA" ./setup_ca.sh 43 | 44 | ### Sign new certificates 45 | 46 | #server certificates 47 | ./server_cert.sh example.com 48 | #client certificates 49 | ./client_cert.sh me@example.com 50 | 51 | A new signed certificate will be placed in `./myCA/certs/` and the private key 52 | will be in `./myCA/private/`. 53 | 54 | Issue a wildcard certificate. 55 | 56 | bash -f ./server_cert.sh '*.example.com' 57 | 58 | ### Revoke certificates 59 | 60 | ./revoke_cert.sh example.com 61 | 62 | A new certificate revocation list (crl) will be generated. The latest is stored 63 | in `./myCA/crl.pem` and any previously published CRLs can be viewed at 64 | `./myCA/crl/crl_*.pem`. A backup of the certificate and key will be maintained 65 | in `./myCA/backup` which is autocreated. The revoked certificate will be 66 | removed from `./myCA/certs` and the key will be removed from `./myCA/private`. 67 | 68 | ### Generate a java keystore from certificates 69 | 70 | ./keystore.sh example.com 71 | 72 | You will be prompted for a password by the script. That password will set the 73 | java keystore password. 74 | 75 | # Customization via .env file 76 | 77 | You can populate a `.env` file to customize some of the options. You can change 78 | the behavior of scripts based environment variables set. The following is an 79 | example. 80 | 81 | ```bash 82 | # lan_server.sh 83 | LAN=192.168.1 84 | 85 | # server_cert.sh 86 | SERVER_EXPIRE_DAYS=397 87 | 88 | # setup_ca.sh 89 | CA_CERT_NAME="Local Certificate Authority" 90 | CA_CERT_ORG="Gleske Internal" 91 | CA_CERT_ORG_UNIT=Systems 92 | CA_CERT_CITY="Garden Grove" 93 | CA_CERT_STATE=California 94 | CA_CERT_COUNTRY=US 95 | # 20 years 96 | CA_CERT_EXPIRE_DAYS=7300 97 | 98 | # all scripts 99 | REQ_OPTS="-batch -nodes" 100 | CERT_DIR=./myCA 101 | ``` 102 | 103 | # Security recommendations 104 | 105 | Here's a few security tips if you've not managed a personal certificate 106 | authority before. 107 | 108 | * Keep your certificate authority offline. For example, store it on an 109 | encrypted flash drive and disconnect it from your computer when you don't need 110 | to create certificates. 111 | * If nobody else is accessing a service except you, then a personal certificate 112 | authority is arguably more trustworthy than a third party. Install your 113 | personal CA in your browsers and devices to use. 114 | * Publish your certificate revocation list in a place where your browsers and 115 | devices can access it. 116 | * Do not issue certificates longer than 398 days otherwise Apple devices will 117 | not recognize the certificate as valid. The default issuance has been 118 | reduced from 2 years down to 397 days. The expiration is configurable. 119 | 120 | # Additional information and alternatives 121 | 122 | ### Private CA Alternatives 123 | 124 | Using self signed certificates is always a bad idea. It's far more secure to 125 | self manage a certificate authority than it is to use self signed certificates. 126 | Running a certificate authority is easy. 127 | 128 | In addition to the scripts in this repository, here is a short recommended list 129 | of scripts and resources for managing a certificate authority. 130 | 131 | 1. The [xca project][xca] provides a graphical front end to certificate 132 | authority management in openssl. It is available for Windows, Linux, and Mac 133 | OS. 134 | 2. The OpenVPN project provides a nice [set of scripts][ovpn_scripts] for 135 | managing a certificate authority as well. 136 | 3. [Be your own CA][yourca_tut] tutorial provides a more manual method of 137 | certificate authority management outside of scripts or UI. It provides 138 | openssl commands for certificate authority management. Additionaly, one can 139 | read up on certificate management in the [SSL Certificates HOWTO][tldp_certs] 140 | at The Linux Documentation Project. 141 | 4. Use my scripts in this repository which is based on option `3` in this list. 142 | Supports server certs only. 143 | 5. Use [certificate-automation][cert_auto] which is similar to these scripts 144 | organized slightly differently. Supports client certs as well. 145 | 146 | Once a certificate authority is self managed simply add the CA certificate to 147 | all browsers and mobile devices. Enjoy secure and validated certificates 148 | everywhere. 149 | 150 | ### Public CA Alternatives 151 | 152 | If a service you manage is designated for public access then self managing a 153 | certificate authority may not be the best option. Signed Domain Validated (DV) 154 | certificates should still be the preferred method to secure your public service. 155 | 156 | 1. [CAcert.org][cacert] is a community driven certificate authority which 157 | provides free SSL certificates. Note: See the [inclusion 158 | page][cacert_inclusion] to see which applications and distros 159 | include the cacert.org root certificates. 160 | 2. [Let's Encrypt][lets_encrypt] is a free, automated, and open Certificate 161 | Authority. 162 | 163 | [cacert]: http://www.cacert.org/ 164 | [cacert_inclusion]: http://wiki.cacert.org/InclusionStatus 165 | [cert_auto]: https://github.com/berico-rclayton/certificate-automation 166 | [docker_ca]: https://docs.docker.com/engine/security/https/ 167 | [lets_encrypt]: https://letsencrypt.org/ 168 | [ovpn_scripts]: http://openvpn.net/index.php/open-source/documentation/howto.html#pki 169 | [tldp_certs]: http://www.tldp.org/HOWTO/SSL-Certificates-HOWTO/x195.html 170 | [wiki_ma]: https://en.wikipedia.org/wiki/Mutual_authentication 171 | [wiki_san]: https://en.wikipedia.org/wiki/Subject_Alternative_Name 172 | [xca]: http://sourceforge.net/projects/xca/ 173 | [yourca_tut]: http://www.g-loaded.eu/2005/11/10/be-your-own-ca/ 174 | -------------------------------------------------------------------------------- /client_cert.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | #Script by Sam Gleske 3 | #Tue Jan 26 19:23:21 PST 2016 4 | #Ubuntu 16.04.1 LTS 5 | #Linux 4.4.0-51-generic x86_64 6 | #GNU bash, version 4.3.46(1)-release (x86_64-pc-linux-gnu) 7 | #Setup script has been adapted from instructions 8 | #http://www.g-loaded.eu/2005/11/10/be-your-own-ca/ 9 | #https://docs.docker.com/engine/security/https/ 10 | 11 | if [ -f .env ]; then 12 | source .env 13 | fi 14 | 15 | CERT_DIR="${CERT_DIR:-./myCA}" 16 | REQ_OPTS="${REQ_OPTS:--batch}" 17 | CERT_DIR="${CERT_DIR%/}" 18 | 19 | function usage() { 20 | cat <&2 48 | else 49 | break 50 | fi 51 | done 52 | client_password="$pass1" 53 | } 54 | 55 | #common name 56 | client="" 57 | while [ "$#" -gt '0' ]; do 58 | case $1 in 59 | -h|--help) 60 | usage 1>&2 61 | exit 1 62 | ;; 63 | -p|--password-prompt) 64 | set_password 65 | shift 66 | ;; 67 | *) 68 | if [ -z "${client}" ]; then 69 | client="$1" 70 | fi 71 | shift 72 | ;; 73 | esac 74 | done 75 | 76 | if [ -z "$client" ];then 77 | echo "Error: missing common-name which is used to identify client." 1>&2 78 | usage 1>&2 79 | exit 1 80 | fi 81 | 82 | #configuration for openssl 83 | opensslcnf="basicConstraints=CA:FALSE 84 | subjectKeyIdentifier=hash 85 | authorityKeyIdentifier=keyid,issuer 86 | keyUsage=critical,nonRepudiation,digitalSignature,keyEncipherment 87 | extendedKeyUsage=critical,clientAuth" 88 | 89 | cd "${CERT_DIR}" 90 | 91 | if [ -e "certs/${client}.crt" ]; then 92 | echo "Client certificate exists. Must revoke existing certificate." 1>&2 93 | echo "revoke_cert.sh ${client}" 1>&2 94 | exit 1 95 | fi 96 | 97 | #create the password or plain text private key? 98 | keygen_args=( -newkey rsa:4096 ) 99 | if [ ! "x${client_password:-}" = x ]; then 100 | keygen_args+=( -passout env:client_password ) 101 | export client_password 102 | else 103 | keygen_args+=( -nodes ) 104 | fi 105 | 106 | # generate private key and CSR 107 | openssl req -config openssl.cnf -new -sha256 "${keygen_args[@]}" \ 108 | -keyout "private/${client}.key" -subj "/CN=${client}" -text \ 109 | -out "newcerts/${client}.csr" ${REQ_OPTS} 110 | 111 | #sign the CSR 112 | openssl ca -config openssl.cnf -extfile <( echo "${opensslcnf}" ) \ 113 | -in "newcerts/${client}.csr" -out "certs/${client}.crt" -batch 114 | 115 | #change appropriate permissions 116 | chmod 0600 "private/${client}.key" 117 | chmod 0644 "certs/${client}.crt" 118 | -------------------------------------------------------------------------------- /keystore.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #Sam Gleske 3 | #Wed Oct 1 23:09:28 EDT 2014 4 | #Ubuntu 16.04.1 LTS 5 | #Linux 4.4.0-51-generic x86_64 6 | #GNU bash, version 4.3.46(1)-release (x86_64-pc-linux-gnu) 7 | #DESCRIPTION 8 | # Generate a java keystore from generated certificates 9 | #USAGE 10 | # ./keystore.sh yourserver.com 11 | 12 | CERT_DIR="${CERT_DIR:-./myCA}" 13 | CERT_DIR="${CERT_DIR%/}" 14 | 15 | function usage() { 16 | cat <&2 43 | exit 1 44 | ;; 45 | --changeit) 46 | use_changeit_pass=true 47 | shift 48 | ;; 49 | *) 50 | if [ -z "${server}" ]; then 51 | server="$1" 52 | fi 53 | shift 54 | ;; 55 | esac 56 | done 57 | 58 | if [ -z "${server}" ]; then 59 | echo "No common-name supplied." 1>&2 60 | usage 1>&2 61 | exit 1 62 | fi 63 | 64 | cd "${CERT_DIR}" 65 | 66 | if [ ! -f "certs/${server}.crt" -o ! -f "private/${server}.key" ]; then 67 | echo "Error: no certificate or private key found for ${server}." 1>&2 68 | echo "CERT_DIR=${CERT_DIR}" 1>&2 69 | exit 1 70 | fi 71 | 72 | if [ ! -d "./keystores" ]; then 73 | mkdir keystores 74 | fi 75 | if [ ! -r "./keystores/.gitignore" ]; then 76 | cat > ./keystores/.gitignore <&2 83 | echo "CERT_DIR=${CERT_DIR}" 1>&2 84 | exit 1 85 | fi 86 | 87 | #grab a password to use 88 | pass="${KEYSTORE_PASS:-changeit}" 89 | 90 | if ! ${use_changeit_pass}; then 91 | confirmpass="match" 92 | while [ ! "${pass}" = "${confirmpass}" ]; do 93 | echo -n "Type a password: " 94 | read -s pass 95 | echo "" 96 | echo -n "Verify password: " 97 | read -s confirmpass 98 | echo "" 99 | if [ ! "${pass}" = "${confirmpass}" ]; then 100 | echo "Passwords do not match. Try again." 1>&2 101 | fi 102 | done 103 | fi 104 | 105 | #aliases are stored by hostname 106 | #first convert certificates to pkcs12 107 | openssl pkcs12 -export \ 108 | -out "keystores/${server}.p12" \ 109 | -passout "pass:${pass}" \ 110 | -inkey "private/${server}.key" \ 111 | -in "certs/${server}.crt" \ 112 | -certfile "certs/myca.crt" \ 113 | -name "${server}" 114 | #then convert pkcs12 to a java keystore 115 | keytool -importkeystore \ 116 | -srckeystore "keystores/${server}.p12" \ 117 | -srcstorepass "${pass}" \ 118 | -srcstoretype PKCS12 \ 119 | -srcalias "${server}" \ 120 | -deststoretype JKS \ 121 | -destkeystore "keystores/${server}.keystore" \ 122 | -deststorepass "${pass}" \ 123 | -destalias "${server}" 124 | -------------------------------------------------------------------------------- /lan_server.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ -f .env ]; then 4 | source .env 5 | fi 6 | 7 | LAN=${LAN:-192.168.1} 8 | args=( ) 9 | 10 | showhelp() { 11 | cat < /dev/null; then 45 | echo 'Not a valid LAN address' >&2 46 | echo 'Example: --lan 192.168.1' >&2 47 | exit 1 48 | fi 49 | 50 | lan_ips="${LAN}.1" 51 | for x in $(seq 2 254); do 52 | lan_ips="${lan_ips} ${LAN}.${x}" 53 | done 54 | 55 | ./server_cert.sh --ip-alts "${lan_ips}" "${args[@]}" 56 | -------------------------------------------------------------------------------- /openssl.cnf: -------------------------------------------------------------------------------- 1 | [ ca ] 2 | default_ca = CA_default 3 | 4 | [ CA_default ] 5 | dir = . 6 | certs = $dir/certs 7 | crl_dir = $dir/crl 8 | database = $dir/index.txt 9 | unique_subject = yes 10 | new_certs_dir = $dir/newcerts 11 | certificate = $dir/certs/myca.crt 12 | serial = $dir/serial 13 | crl = $dir/crl.pem 14 | private_key = $dir/private/myca.key 15 | x509_extensions = usr_cert 16 | default_days = 397 17 | default_crl_days = 30 18 | default_md = sha256 19 | preserve = no 20 | policy = policy_optional 21 | 22 | [ policy_optional ] 23 | countryName = optional 24 | stateOrProvinceName = optional 25 | organizationName = optional 26 | organizationalUnitName = optional 27 | commonName = supplied 28 | emailAddress = optional 29 | 30 | [ usr_cert ] 31 | basicConstraints=CA:FALSE 32 | subjectKeyIdentifier=hash 33 | authorityKeyIdentifier=keyid,issuer 34 | 35 | [ req ] 36 | distinguished_name = req_distinguished_name 37 | 38 | [ req_distinguished_name ] 39 | -------------------------------------------------------------------------------- /revoke_cert.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | #Script by Sam Gleske 3 | #Tue Jan 26 19:36:08 PST 2016 4 | #Ubuntu 16.04.1 LTS 5 | #Linux 4.4.0-51-generic x86_64 6 | #GNU bash, version 4.3.46(1)-release (x86_64-pc-linux-gnu) 7 | #Setup script has been adapted from instructions 8 | #http://www.g-loaded.eu/2005/11/10/be-your-own-ca/ 9 | #https://docs.docker.com/engine/security/https/ 10 | 11 | CERT_DIR="${CERT_DIR:-./myCA}" 12 | CERT_DIR="${CERT_DIR%/}" 13 | 14 | function usage() { 15 | cat <&2 46 | exit 1 47 | ;; 48 | --crl) 49 | do_revoke=false 50 | shift 51 | ;; 52 | *) 53 | if [ -z "${cname}" ]; then 54 | cname="$1" 55 | fi 56 | shift 57 | ;; 58 | esac 59 | done 60 | 61 | cd "${CERT_DIR}" 62 | DATE="$(date +%Y-%m-%d-%s)" 63 | 64 | if ${do_revoke}; then 65 | if [ -z "$cname" ];then 66 | echo "Error: missing common-name which is used to identify client." 1>&2 67 | usage 1>&2 68 | exit 1 69 | fi 70 | 71 | if [ ! -e "certs/${cname}.crt" ]; then 72 | echo "Certificate ${cname} does not exist. Nothing to revoke." 1>&2 73 | exit 1 74 | fi 75 | 76 | echo "Revoking certificate for ${cname}." 1>&2 77 | 78 | openssl ca -config openssl.cnf -revoke "./certs/${cname}.crt" 79 | 80 | #make a backup directory to store revoked certificates and keys 81 | if [ ! -d "./backup" ];then 82 | mkdir "./backup" 83 | fi 84 | 85 | #back up the old certificate and key so it is no longer tracked for renewel but can still be referenced if necessary. 86 | echo "Backup old certificate and key." 1>&2 87 | mv "./certs/${cname}.crt" "./backup/${cname}_${DATE}.crt" 88 | mv "./private/${cname}.key" "./backup/${cname}_${DATE}.key" 89 | fi 90 | 91 | #generate the current certificate revokation list 92 | echo "Generate a new certificate revocation list." 1>&2 93 | openssl ca -config openssl.cnf -gencrl | openssl crl -text > ./crl.pem 94 | cp "./crl.pem" "./crl/crl_${DATE}.pem" 95 | echo "Finished revoking ${cname}. The latest ./crl.pem has been generated and ./crl/crl_${DATE}.pem has been created." 1>&2 96 | -------------------------------------------------------------------------------- /rotate_homeassistant.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd /root/my_internal_ca 3 | ./revoke_cert.sh homeassistant 4 | ./lan_server.sh homeassistant 5 | cp -af myCA/private/homeassistant.key /etc/nginx/certs/homeassistant.key 6 | cp -af myCA/certs/homeassistant.crt /etc/nginx/certs/homeassistant.crt 7 | systemctl reload nginx 8 | -------------------------------------------------------------------------------- /server_cert.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | #Script by Sam Gleske 3 | #Tue Jan 26 17:21:21 PST 2016 4 | #Ubuntu 16.04.1 LTS 5 | #Linux 4.4.0-51-generic x86_64 6 | #GNU bash, version 4.3.46(1)-release (x86_64-pc-linux-gnu) 7 | #Setup script has been adapted from instructions 8 | #http://www.g-loaded.eu/2005/11/10/be-your-own-ca/ 9 | #https://docs.docker.com/engine/security/https/ 10 | 11 | if [ -f .env ]; then 12 | source .env 13 | fi 14 | 15 | CERT_DIR="${CERT_DIR:-./myCA}" 16 | REQ_OPTS="${REQ_OPTS:--batch -nodes}" 17 | CERT_DIR="${CERT_DIR%/}" 18 | SERVER_EXPIRE_DAYS="${SERVER_EXPIRE_DAYS:-397}" 19 | 20 | function usage() { 21 | cat <&2 60 | exit 1 61 | ;; 62 | --localhost) 63 | use_localhost=true 64 | shift 65 | ;; 66 | --ip-alts) 67 | shift 68 | ip_alts="$1" 69 | shift 70 | ;; 71 | --dns-alts) 72 | shift 73 | dns_alts="$1" 74 | shift 75 | ;; 76 | --auth) 77 | enable_auth=true 78 | shift 79 | ;; 80 | *) 81 | if [ -z "${server}" ]; then 82 | server="$1" 83 | fi 84 | shift 85 | ;; 86 | esac 87 | done 88 | 89 | if [ -z "$server" ];then 90 | echo "Error: missing common-name which is typically a DNS name." 1>&2 91 | usage 1>&2 92 | exit 1 93 | fi 94 | 95 | #start alternative names for openssl cnf 96 | if ${use_localhost}; then 97 | dns_alts_cnf="DNS:${server},DNS:localhost" 98 | #::1 is IPv6 loopback 99 | ip_alts_cnf="IP:127.0.0.1,IP:::1" 100 | else 101 | dns_alts_cnf="DNS:${server}" 102 | ip_alts_cnf="" 103 | fi 104 | if [ ! -z "${ip_alts}" ]; then 105 | for x in ${ip_alts}; do 106 | ip_alts_cnf="${ip_alts_cnf},IP:${x}" 107 | done 108 | fi 109 | ip_alts_cnf="${ip_alts_cnf#,}" 110 | if [ ! -z "${dns_alts}" ]; then 111 | for x in ${dns_alts}; do 112 | dns_alts_cnf="${dns_alts_cnf},DNS:${x}" 113 | done 114 | fi 115 | all_alts="${dns_alts_cnf},${ip_alts_cnf}" 116 | all_alts="${all_alts%,}" 117 | 118 | #configuration for openssl 119 | opensslcnf="basicConstraints=CA:FALSE 120 | subjectKeyIdentifier=hash 121 | authorityKeyIdentifier=keyid,issuer 122 | subjectAltName = ${all_alts}" 123 | 124 | if [ "$enable_auth" = true ]; then 125 | opensslcnf="${opensslcnf} 126 | keyUsage=critical,nonRepudiation,digitalSignature,keyEncipherment,keyAgreement 127 | extendedKeyUsage=critical,serverAuth 128 | " 129 | fi 130 | 131 | cd "${CERT_DIR}" 132 | 133 | if [ -e "certs/${server}.crt" ]; then 134 | echo "Server certificate exists. Must revoke existing certificate." 1>&2 135 | echo "revoke_cert.sh ${server}" 1>&2 136 | exit 1 137 | fi 138 | 139 | #create the key and CSR 140 | openssl req -config openssl.cnf -new -newkey rsa:4096 -sha256 \ 141 | -keyout "private/${server}.key" -subj "/CN=${server}" \ 142 | -text -out "newcerts/${server}.csr" ${REQ_OPTS} 143 | 144 | #sign the CSR 145 | openssl ca -config openssl.cnf -extfile <( echo "${opensslcnf}" ) \ 146 | -in "newcerts/${server}.csr" -out "certs/${server}.crt" -days "${SERVER_EXPIRE_DAYS}" -batch 147 | 148 | #change appropriate permissions 149 | chmod 0600 private/${server}.key 150 | chmod 0644 certs/${server}.crt 151 | -------------------------------------------------------------------------------- /setup_ca.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | #Script by Sam Gleske 3 | #Thu Mar 6 23:14:29 EST 2014 4 | #Ubuntu 16.04.1 LTS 5 | #Linux 4.4.0-51-generic x86_64 6 | #GNU bash, version 4.3.46(1)-release (x86_64-pc-linux-gnu) 7 | #Setup script has been adapted from instructions 8 | #http://www.g-loaded.eu/2005/11/10/be-your-own-ca/ 9 | #https://docs.docker.com/engine/security/https/ 10 | 11 | #DESCRIPTION 12 | # Generate a certificate authority for private use. This can be used on 13 | # personal servers or for a docker server. This CA will be used to sign both 14 | # client and server sertificates for mutual authentication via TLS. 15 | 16 | if [ -f .env ]; then 17 | source .env 18 | fi 19 | 20 | CERT_DIR="${CERT_DIR:-./myCA}" 21 | REQ_OPTS="${REQ_OPTS:--batch -nodes}" 22 | CERT_DIR="${CERT_DIR%/}" 23 | 24 | if [ ! -d "${CERT_DIR}" ]; then 25 | mkdir -p "${CERT_DIR}" 26 | fi 27 | 28 | #don't overwrite our existing CA 29 | if [ -e "${CERT_DIR}/certs/myca.crt" ]; then 30 | echo "Error: Certificate authority already exists." 1>&2 31 | echo "CERT_DIR=${CERT_DIR}" 1>&2 32 | exit 1 33 | fi 34 | 35 | 36 | #openssl.cnf for generating a certificate authority 37 | opensslcnf=" 38 | [ req ] 39 | distinguished_name = req_distinguished_name 40 | x509_extensions = v3_ca 41 | [ req_distinguished_name ] 42 | countryName = 43 | countryName_default = ${CA_CERT_COUNTRY:-US} 44 | stateOrProvinceName = 45 | stateOrProvinceName_default = ${CA_CERT_STATE:-California} 46 | localityName = 47 | localityName_default = ${CA_CERT_CITY:-Garden Grove} 48 | organizationName = 49 | organizationName_default = ${CA_CERT_ORG:-Gleske Internal} 50 | organizationalUnitName = 51 | organizationalUnitName_default = ${CA_CERT_ORG_UNIT:-Systems} 52 | commonName = 53 | commonName_default = ${CA_CERT_NAME:-Local Certificate Authority} 54 | emailAddress = 55 | #emailAddress_default = none@example.com 56 | [ v3_ca ] 57 | subjectKeyIdentifier = hash 58 | authorityKeyIdentifier = keyid:always,issuer 59 | basicConstraints = CA:true 60 | " 61 | 62 | if [ ! -e "${CERT_DIR}/openssl.cnf" ]; then 63 | cp openssl.cnf "${CERT_DIR}/" 64 | chmod 0600 "${CERT_DIR}/openssl.cnf" 65 | fi 66 | 67 | cd "${CERT_DIR}" 68 | 69 | #Prepare the certificate authority for git 70 | for x in certs crl private newcerts;do 71 | if [ ! -d "${x}" ];then 72 | mkdir -p "${x}" 73 | touch "${x}/.gitignore" 74 | fi 75 | done 76 | chmod 0700 private 77 | echo -e '*\n!.gitignore' > ./newcerts/.gitignore 78 | 79 | #Generate a CA good for 20 years. 80 | #If you make it longer and you could run into compatibility issues. 81 | openssl req -config <( echo "${opensslcnf}" ) -new -newkey rsa:4096 -sha256 \ 82 | -keyout private/myca.key -x509 -days "${CA_CERT_EXPIRE_DAYS:-7300}" -text \ 83 | -out certs/myca.crt ${REQ_OPTS} "$@" 84 | 85 | #change appropriate permissions 86 | chmod 0600 private/myca.key 87 | chmod 0644 certs/myca.crt 88 | 89 | #configure some additional files 90 | touch index.txt 91 | echo '01' > serial 92 | --------------------------------------------------------------------------------