Skip to content

Instantly share code, notes, and snippets.

@BrianAker
Last active September 18, 2022 05:48
Show Gist options
  • Select an option

  • Save BrianAker/ba8e874ddb781c3c98d277aa9050b748 to your computer and use it in GitHub Desktop.

Select an option

Save BrianAker/ba8e874ddb781c3c98d277aa9050b748 to your computer and use it in GitHub Desktop.
This script produces a CA with a restraint that it can only create certificates under a specific domain.
#!/bin/bash
# This script produces a CA with a restraint that it can only create certificates under a specific domain.
# The last 5 lines install the CA where mkcert will make use of it as the root CA ( OSX specific at the moment )
gTLD="${gTLD:-localhost}"
declare -x HOST_COMMON_NAME
#export exampleIP=192.0.2.2
force=false
function printConfig() {
cat << EOF > "$gTLD".cfg
[ req ]
prompt=no
default_bits=4096
default_md=sha256
preserve=no
distinguished_name=req_distinguished_name
req_extensions=v3_req
x509_extensions=v3_ca
[ req_distinguished_name ]
CN=$gTLD trust CA
emailAddress=root@$gTLD
[ v3_ca ]
basicConstraints=critical,CA:TRUE,pathlen:1
nameConstraints=critical,permitted;DNS:.$gTLD
keyUsage=critical,cRLSign,digitalSignature,keyCertSign
#extendedKeyUsage=critical,serverAuth,clientAuth,emailProtection
subjectKeyIdentifier=hash
#authorityKeyIdentifier=keyid:always,issuer:always
[ v3_req_ca ]
basicConstraints=critical,CA:TRUE,pathlen:0
nameConstraints=critical,permitted;DNS:.$gTLD
keyUsage=critical,cRLSign,digitalSignature,keyCertSign
extendedKeyUsage=critical,serverAuth,clientAuth,emailProtection
subjectKeyIdentifier=hash
[ v3_req ]
basicConstraints=critical,CA:TRUE,pathlen:0
nameConstraints=critical,permitted;DNS:.$gTLD
keyUsage=critical,cRLSign,digitalSignature,keyCertSign
extendedKeyUsage=critical,serverAuth,clientAuth,emailProtection
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer:always
[ server_req ]
basicConstraints=critical,CA:FALSE
keyUsage=critical,digitalSignature
extendedKeyUsage=critical,serverAuth
subjectKeyIdentifier=hash
subjectAltName=@subjects
[ server_sign ]
basicConstraints=critical,CA:FALSE
keyUsage=critical,digitalSignature
extendedKeyUsage=critical,serverAuth
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer:always
subjectAltName=@subjects
[ subjects ]
EOF
#DNS.2=www.example.$gTLD
#IP.1=192.0.2.1
#IP.2=198.51.100.254
#IP.3=2001:DB8::1
}
die() { echo "$*" >&2; exit 2; } # complain to STDERR and exit with error
needs_arg() { if [ -z "$OPTARG" ]; then die "No arg for --$OPT option"; fi; }
function printConfigHosts() {
local argIndex="${#BASH_ARGV[@]}"
while [[ argIndex -gt 0 ]] ; do
argIndex=$((argIndex - 1))
echo -n "${BASH_ARGV[$argIndex]} "
if [[ "$argIndex" -eq '0' ]]; then
HOST_COMMON_NAME=${BASH_ARGV[$argIndex]}
fi
cat << EOF >> "$gTLD".cfg
DNS.$argIndex=${BASH_ARGV[$argIndex]}.$gTLD
EOF
done
}
while getopts fi:-: OPT; do
# support long options: https://stackoverflow.com/a/28466267/519360
if [ "$OPT" = "-" ]; then # long option: reformulate OPT and OPTARG
OPT="${OPTARG%%=*}" # extract long option name
OPTARG="${OPTARG#"$OPT"}" # extract long option argument (may be empty)
OPTARG="${OPTARG#=}" # if long option argument, remove assigning `=`
fi
case "$OPT" in
h | help )
echo "help"
exit 0
;;
f | force ) force=true ;;
i | install ) needs_arg; gTLD="$OPTARG" ;;
??* ) die "Illegal option --$OPT" ;; # bad long option
? ) exit 2 ;; # bad short option (error reported via getopts)
esac
done
shift $((OPTIND-1)) # remove parsed options and args from $@ list
if $force; then
echo "Remove files here";
fi
printConfig
printConfigHosts
if [ ! -r "root-ca.pem" ]; then
openssl req -nodes -x509 -days 3650 -newkey rsa:4096 -sha256 -out root-ca.pem -keyout root-ca.key -config "$gTLD".cfg -subj "/CN=Root CA for $gTLD"
openssl verify -CAfile root-ca.pem root-ca.pem
fi
if [ ! -r "$gTLD"-ca.pem ]; then
openssl req -nodes -new -newkey rsa:4096 -out "$gTLD"-ca.csr -sha256 -keyout "$gTLD"-ca.key -config "$gTLD".cfg -reqexts v3_req_ca -subj "/CN=Intermediate CA for $gTLD"
openssl req -in "$gTLD"-ca.csr -verify -noout
openssl x509 -req -days 365 -in "$gTLD"-ca.csr -CA root-ca.pem -CAkey root-ca.key -sha256 -set_serial 1 -out "$gTLD"-ca.pem -extensions v3_req -extfile "$gTLD".cfg
openssl verify -CAfile root-ca.pem "$gTLD"-ca.pem
cat root-ca.pem >> "$gTLD"-ca.pem
fi
#cat root-ca.pem "$gTLD"-ca.pem > ca.pem
if [ "$HOST_COMMON_NAME" ]; then
openssl req -nodes -new -newkey rsa:4096 -out "$HOST_COMMON_NAME"."$gTLD".csr -sha256 -keyout "$HOST_COMMON_NAME"."$gTLD".key -config "$gTLD".cfg -reqexts server_req -subj "/CN=$HOST_COMMON_NAME.$gTLD"
openssl req -in "$HOST_COMMON_NAME"."$gTLD".csr -verify -noout
openssl x509 -req -days 365 -in "$HOST_COMMON_NAME"."$gTLD".csr -CA "$gTLD"-ca.pem -CAkey "$gTLD"-ca.key -sha256 -out "$HOST_COMMON_NAME"."$gTLD".pem -extensions server_sign -extfile "$gTLD".cfg
#openssl verify -CAfile root-ca.pem "$HOST_COMMON_NAME"."$gTLD".pem
openssl verify -CAfile "$gTLD"-ca.pem "$HOST_COMMON_NAME"."$gTLD".pem
fi
#rm root-ca.key
#openssl pkcs8 -topk8 -in $gTLD-ca.key -out $gTLD-ca.pkcs8.key -nocrypt
#mkdir -p ~/.local/share/mkcert
#chmod 700 ~/.local/share/mkcert
#cat $gTLD-ca.pkcs8.key > ~/.local/share/mkcert/rootCA-key.pem
#cat $gTLD-ca.pem > ~/.local/share/mkcert/rootCA.pem
#chmod 400 ~/.local/share/mkcert/*
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment