fruffl icon

SSL certificate factory

fruffl | 11/12/15 11:22:16 PM UTC | 0 ⭐ | 356 👁️ | Never ⏰ | []
Bash |

5.63 KB

|

None

|

0 👍

/

0 👎

#!/bin/bash
 
export SCRIPT_PATH=$( cd "$(dirname "${BASH_SOURCE}")" ; pwd -P )
 
DEFAULT_DOMAIN='reverse.com'
DEFAULT_IP='123.123.123.123'
 
# create certificates
# $ make tls-server example.com ssl
# $ make tls-server sub.example.com ssl
# creates example.com.ssl.tls-server.crt:
# - request created with example.com.tls-server.cnf
# - signed by example.com.ca-tls.crt using config example.com.ca-tls.cnf
 
 
check_result()
{
    if [ $1 -ne 0 ]; then
        echo -e "\e[91m        Error\e[39m $2"
        exit $1
    fi
    echo -e "\e[92m        +\e[39m"
}
 
warn_result()
{
    if [ $1 -ne 0 ]; then
        echo -e "\e[93m        Warning\e[39m $2"
    fi
}
 
check_prompt()
{
    if [ $1 -ne 0 ]; then
        warn_result "$@"
        read -p 'Would you like to continue [y/n]: ' answer
        if [ "$answer" != 'y' ] && [ "$answer" != 'Y'  ]; then
            echo 'Goodbye'
            exit 1
        fi
    fi
}
    
domainPath()
{
    local domain=$1
    local lookup="$SCRIPT_PATH/$DEFAULT_DOMAIN/lookup"
    local path=$lookup/$domain
    
    if [ -e $path ]; then
        echo $(head -n 1 $path)
    fi
}
 
# type: for avail crt-types see crt-*/etc/*.cnf {email|tls-client|tls-server|code-signing}
# domain: a valid domain, stored in /lookup
# fileName: a unique filename. If the file exists, the last version will be revoked as affiliationChanged
#
# files will be stored in ./crt-*/$domain.$filename.$type.ext
# ---
# make tls-server example.com ssl
# ---
make()
{
    local type=$1
    local domain=$2
    local fileName=$3
    
    
    local path=$(domainPath $domain)
    if [ -z $path ]; then
        check_result 1 "domain $domain not found in $SCRIPT_PATH/$DEFAULT_DOMAIN"
    fi
    
    local baseType
    case "$type" in
            email)
                baseType='email'
                echo "create $baseType/$type"
                ;;
            tls-server|tls-client)
                baseType='tls'
                echo "create $baseType/$type"
                ;;
            code-signing)
                baseType='software'
                echo "create $baseType/$type"
                ;;
            *)
                check_result 1 "invalid request type $type; {email|tls-client|tls-server|code-signing}"
                exit 1
    esac
    
    local lvl=$(grep -o '/intermediate/' <<< "$path" | wc -l)
    case "$lvl" in
        0)
            export CA_0_SCRIPT_PATH="$path"
            ;;
        1)
            export CA_1_SCRIPT_PATH="$path"
            ;;
        2)
            export CA_2_SCRIPT_PATH="$path"
            ;;
    esac
    
    local caCrl="$path/ca-$baseType/db/$domain.ca-$baseType.crl"
    local caCnf="$path/ca-$baseType/etc/$domain.ca-$baseType.cnf"
    local caPwd="$path/ca-$baseType/private/$domain.ca-$baseType.pwd"
    local csrCnf="$path/crt-$baseType/etc/$domain.$type.cnf"
    local key="$path/crt-$baseType/private/$domain.$fileName.$type.key"
    local csr="$path/crt-$baseType/$domain.$fileName.$type.csr"
    local crt="$path/crt-$baseType/$domain.$fileName.$type.crt"
    local p12="$path/crt-$baseType/$domain.$fileName.$type.p12"
    local chain="$path/$domain.ca-$baseType.chain.pem"
    
    if [ -e $crt ]; then
        local lastSrl=$(openssl x509 -in $crt -serial -noout)
        local lastFnr=$(openssl x509 -in $crt -fingerprint -noout)
        
        check_prompt 1 "certificate $domain.$fileName.$type.crt exists as \n\t$lastSrl\n\t$lastFnr\nRevoke this version and create a new verion."
        
        echo 'Please set the revokation reason, type any other key to continue without setting the CRL reason.'
        echo '[1] unspecified'
        echo '[2] keyCompromise'
        echo '[3] CACompromise'
        echo '[4] affiliationChanged'
        echo '[5] superseded'
        echo '[6] cessationOfOperation'
        echo '[7] certificateHold'
        echo '[8] removeFromCRL'
        read -p 'Please set the revokation reason [1-8]: ' answer
        
        local revokationReason=no
        case "$answer" in
                1)
                    revokationReason=unspecified
                    ;;
                2)
                    revokationReason=keyCompromise
                    ;;
                3)
                    revokationReason=CACompromise
                    ;;
                4)
                    revokationReason=affiliationChanged
                    ;;
                5)
                    revokationReason=superseded
                    ;;
                6)
                    revokationReason=cessationOfOperation
                    ;;
                7)
                    revokationReason=certificateHold
                    ;;
                8)
                    revokationReason=removeFromCRL
                    ;;
                *)
                    warn_result 1 'Nothing matched. Continue without setting a reason.'
        esac
        
        if [ $revokationReason == 'no' ]; then
            openssl ca \
                -config $caCnf \
                -revoke $crt \
                -passin file:$caPwd
        else
            openssl ca \
                -config $caCnf \
                -revoke $crt \
                -passin file:$caPwd \
                -crl_reason $revokationReason
        fi
        
        openssl ca -gencrl \
            -config $caCnf \
            -out $caCrl \
            -passin file:$caPwd
    fi
    
    # note -subj
    # if you want to use multiple values you should remove the -subj and use the prompt.
    # /O/ST must match, see CA-configs.
    # I prefer to bypass the prompt for ~300 domains with ~2k subdomains.
    case "$type" in
            tls-server)
                export SAN="DNS:$domain,DNS:*.$domain"
                openssl req -new \
                    -config $csrCnf \
                    -out $csr \
                    -keyout $key \
                    -subj "/C=BE/ST=Antwerp/O=### Network $domain/CN=$domain"
                
                openssl ca \
                    -batch \
                    -config $caCnf \
                    -in $csr \
                    -out $crt \
                    -passin file:$caPwd \
                    -extensions server_ext
                
                openssl pkcs12 -export \
                    -name "$domain (TLS Network Component)" \
                    -inkey $key \
                    -passout pass:\
                    -in $crt \
                    -certfile $chain \
                    -out $p12
                        
                ;;
                
            *)
                check_result 1 "invalid request type $type; {email|tls-client|tls-server|code-signing}"
                exit 1
    esac
}

Comments