-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtcra.sh
executable file
·236 lines (202 loc) · 8.85 KB
/
tcra.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
#!/usr/bin/env bash
# NAME: tcra.sh
# DECRIPTION: Custom regsitration authority client used with ISC RAMI API
# AUTHOR: Tony Cavella ([email protected])
# SOURCE: https://github.com/acavella/trustedcore-ra
## CONFIGURE DEFAULT ENVIRONMENT
set -o errexit
set -o pipefail
set -o nounset
#set -o xtrace
## VARIABLES
__dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
__bin="${__dir}/bin"
__conf="${__dir}/conf"
dtgf=$(date '+%Y%m%d-%H%M%S')
ver=$(<VERSION)
config="${__conf}""/local.conf"
log="${__dir}""/log/revoke-""${dtgf}"".log"
start=$(date +%s)
reqs=("openssl" "curl" "sed")
arg1=${1}
arg2=${2}
arg3=${3:-default}
is_command() {
# Checks to see if the given command (passed as a string argument) exists on the system.
# The function returns 0 (success) if the command exists, and 1 if it doesn't.
local check_command="$1"
command -v "${check_command}" >/dev/null 2>&1
}
make_temporary_log() {
# Create a random temporary file for the log
TEMPLOG=$(mktemp /tmp/tcra_temp.XXXXXX)
# Open handle 3 for templog
# https://stackoverflow.com/questions/18460186/writing-outputs-to-log-file-and-console
exec 3>${TEMPLOG}
# Delete templog, but allow for addressing via file handle
# This lets us write to the log without having a temporary file on the drive, which
# is meant to be a security measure so there is not a lingering file on the drive during the install process
rm ${TEMPLOG}
}
copy_to_run_log() {
# Copy the contents of file descriptor 3 into the log
cat /proc/$$/fd/3 > "${log}"
chmod 644 "${log}"
}
collect_certificate_password() {
# Check client certificate extension
if [[ ${clientcert} == *.p12 ]] || [[ ${clientcert} == *.pfx ]]; then
printf "%(%Y-%m-%dT%H:%M:%SZ)T $$ [info] %s\n" $(date +%s) "Client certificate extension detected as PKCS#12"
echo "Enter PKCS#12 decryption password : "
read -s -p "Enter client certificate decryption password: " p12pw
cert_type="p12"
elif [[ ${clientcert} == *.pem ]]; then
printf "%(%Y-%m-%dT%H:%M:%SZ)T $$ [info] %s\n" $(date +%s) "Client certificate extension detected as PEM"
cert_type="pem"
else
printf "%(%Y-%m-%dT%H:%M:%SZ)T $$ [error] %s\n" $(date +%s) "Unsupported certificate extension, exiting"
exit 1
fi
}
start() {
# Print startup and debug information
printf "%(%Y-%m-%dT%H:%M:%SZ)T $$ [info] %s\n" $(date +%s) "Trusted Core: RA v${ver} started"
# Load local configuration
if [ ! -e $config ]
then
printf "%(%Y-%m-%dT%H:%M:%SZ)T $$ [error] %s\n" $(date +%s) "Configuration file missing"
exit 1
else
source $config
printf "%(%Y-%m-%dT%H:%M:%SZ)T $$ [info] %s\n" $(date +%s) "Configuration file loaded sucessfully, ${config}"
fi
# Validate input file exists
if [ -f $arg1 ]
then
printf "%(%Y-%m-%dT%H:%M:%SZ)T $$ [info] %s\n" $(date +%s) "Input file is valid"
else
printf "%(%Y-%m-%dT%H:%M:%SZ)T $$ [error] %s\n" $(date +%s) "Input file not specified or invalid"
exit 1
fi
# Check for requirements, exit if not found
for req in ${reqs[@]}; do
if is_command ${req} ; then
printf "%(%Y-%m-%dT%H:%M:%SZ)T $$ [info] %s\n" $(date +%s) "Command ${req} was found"
else
printf "%(%Y-%m-%dT%H:%M:%SZ)T $$ [error] %s\n" $(date +%s) "Command ${req} was not found, exiting"
exit 1
fi
done
}
read_input() {
local filesize=$(stat -c %s "${arg1}")
subject=$(cat ${arg1})
printf "%(%Y-%m-%dT%H:%M:%SZ)T $$ [info] %s\n" $(date +%s) "Completed reading input file, ${filesize} bytes, ${arg1}"
}
make_output_directory() {
mkdir ${1}
printf "%(%Y-%m-%dT%H:%M:%SZ)T $$ [info] %s\n" $(date +%s) "Created the following directory, ${cn}"
}
generate_private_key() {
if [[ ${arg2} == "rsa" ]]; then
openssl genrsa -out ${pkey} 4096
printf "%(%Y-%m-%dT%H:%M:%SZ)T $$ [info] %s\n" $(date +%s) "Generated RSA private key, ${pkey} with a subject ${cn}"
elif [[ ${arg2} == "ecdsa" ]]; then
openssl ecparam -name secp384r1 -genkey -noout -out "${pkey}"
printf "%(%Y-%m-%dT%H:%M:%SZ)T $$ [info] %s\n" $(date +%s) "Generated ECC private key, ${pkey} with a subject ${cn}"
elif [[ ${arg2} == "ecdh" ]]; then
openssl ecparam -name secp384r1 -genkey -noout -out "${pkey}"
printf "%(%Y-%m-%dT%H:%M:%SZ)T $$ [info] %s\n" $(date +%s) "Generated ECC private key, ${pkey} with a subject ${cn}"
else
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [error] Unrecognized argument, ${arg2}, exiting."
printf "%(%Y-%m-%dT%H:%M:%SZ)T $$ [error] %s\n" $(date +%s) "Unrecognized argument, ${arg2}, in second position"
exit 1
fi
}
generate_csr() {
local str="PKCS#10 CSR generated, ${csr}"
if [[ ${arg2} == "rsa" ]]; then
sed -i -E "s/^(commonName[[:blank:]]*=[[:blank:]]*).*/\1${cn}/" ${__conf}/rsa.cnf
openssl req -new -key "${pkey}" -nodes -out "${csr}" -sha384 -config "${__conf}/rsa.cnf"
printf "%(%Y-%m-%dT%H:%M:%SZ)T $$ [info] %s\n" $(date +%s) "${str}"
elif [[ ${arg2} == "ecdsa" ]]; then
sed -i -E "s/^(commonName[[:blank:]]*=[[:blank:]]*).*/\1${cn}/" ${__conf}/ecdsa.cnf
openssl req -new -key "${pkey}" -nodes -out "${csr}" -sha384 -config "${__conf}/ecdsa.cnf"
printf "%(%Y-%m-%dT%H:%M:%SZ)T $$ [info] %s\n" $(date +%s) "${str}"
elif [[ ${arg2} == "ecdh" ]]; then
sed -i -E "s/^(commonName[[:blank:]]*=[[:blank:]]*).*/\1${cn}/" ${__conf}/ecdh.cnf
openssl req -new -key "${pkey}" -nodes -out "${csr}" -sha384 -config "${__conf}/ecdh.cnf"
printf "%(%Y-%m-%dT%H:%M:%SZ)T $$ [info] %s\n" $(date +%s) "${str}"
else
printf "%(%Y-%m-%dT%H:%M:%SZ)T $$ [error] %s\n" $(date +%s) "Unrecognized argument, ${arg2}, exiting."
exit 1
fi
}
generate_random_password() {
randpass=$(openssl rand -base64 14)
echo "${randpass}" > ${outputdir}/${cn}_pass.txt
printf "%(%Y-%m-%dT%H:%M:%SZ)T $$ [info] %s\n" $(date +%s) "Random password generated, >112bits entropy"
}
main() {
start
read_input
local counter=0
if [[ ${arg2} == "ecdsa" ]]; then
caprofile=${ecdsaprofile}
caurl=${caecc}
elif [[ ${arg2} == "ecdh" ]]; then
caprofile=${ecdhprofile}
caurl=${caecc}
elif [[ ${arg2} == "rsa" ]]; then
caprofile=${rsaprofile}
caurl=${carsa}
else
exit 1
fi
printf "%(%Y-%m-%dT%H:%M:%SZ)T $$ [info] %s\n" $(date +%s) "Generating private key and csr for each subject"
for cn in $subject; do
local outputdir="${__dir}/output/${cn}"
local csr="${outputdir}/${cn}.csr"
local pkey="${outputdir}/${cn}.key"
local p7b="${outputdir}/${cn}.p7b"
local p12="${outputdir}/${cn}.p12"
local tempreq=$(mktemp /tmp/temp.XXXXXXXXX)
local tempout=$(mktemp /tmp/temp.XXXXXXXXX)
local pre="-----BEGIN PKCS7-----"
local post="-----END PKCS7-----"
make_output_directory ${outputdir}
generate_private_key
generate_csr
if [[ $arg3 == "sign" ]]
then
printf "%(%Y-%m-%dT%H:%M:%SZ)T $$ [info] %s\n" $(date +%s) "Sending PKCS#10 request to RAMI API"
local p10request=$(sed -e '2,$!d' -e '$d' ${csr} | tr --delete '\n')
curl ${caurl} --cert ${clientcert} -v -o ${tempout} --cacert ${cacert} --data-urlencode "action=enrollKey" \
--data-urlencode "ca=${caprofile}" --data-urlencode "response.cert.format=1" --data-urlencode "request=${p10request}" --tlsv1.2
# Need logic to validate response
printf "%(%Y-%m-%dT%H:%M:%SZ)T $$ [info] %s\n" $(date +%s) "Valid response received from RAMI API"
echo -e ${pre} > ${p7b}
tr --delete '\n' < ${tempout} | sed -n -e 's/^.*base64CertChain=//p' | sed 's/\r$//' >> ${p7b}
echo -e "\n${post}" >> ${p7b}
printf "%(%Y-%m-%dT%H:%M:%SZ)T $$ [info] %s\n" $(date +%s) "PKCS#7 generated from RAMI response"
generate_random_password
local result=$(mktemp /tmp/temp.XXXXXXXXX)
openssl pkcs7 -print_certs -in ${p7b} -out ${result}
openssl pkcs12 -keypbe PBE-SHA1-3DES -certpbe PBE-SHA1-3DES -macalg SHA1 \
-export -inkey ${pkey} -in ${result} -out ${p12} -name "${cn}-${RANDOM}" \
-passout pass:${randpass}
rm -f ${result}
printf "%(%Y-%m-%dT%H:%M:%SZ)T $$ [info] %s\n" $(date +%s) "PKCS#12 generated"
fi
rm -f ${tempreq}
rm -f ${tempout}
printf "%(%Y-%m-%dT%H:%M:%SZ)T $$ [info] %s\n" $(date +%s) "Temporary files cleaned up"
counter=$(( counter + 1 ))
done
end=$(date +%s)
printf "%(%Y-%m-%dT%H:%M:%SZ)T $$ [info] %s\n" $(date +%s) "Completed generating ${counter} key pairs in $(($end-$start)) seconds"
}
make_temporary_log
main | tee -a /proc/$$/fd/3
copy_to_run_log
exit 0