Skip to content

Commit 00a5008

Browse files
authored
Update generate-p12.sh
1. Added Option to parse in the npm value (I.E. npm-10) as a required variable which is the npm value that the certificate files are stored in (I.E. '/etc/letsencrypt/live/npm-10/' and '/etc/letsencrypt/archive/npm-10/' ) 2. Added the option to parse a password into the script to be used as the p12 password for securing the private key within the generated PKCS12 file. 3. Added Variable in script to allow the user to keep the root certificate that the script generates ($KEEP_ROOT_CERTIFICATE which it is set to true by default). 4. Added Simlinks for the .p12 file (follows the current convention) 5. Added Simlink for the root certificate, if the user chooses to keep the root certificate by setting the variable $KEEP_ROOT_CERTIFICATE to true (follows the current convention) 4. Added automatic cleanup for temporary files as well as the root file when the variable $KEEP_ROOT_CERTIFICATE is set to false.
1 parent ee2072b commit 00a5008

File tree

1 file changed

+169
-24
lines changed

1 file changed

+169
-24
lines changed

backend/scripts/generate-p12.sh

Lines changed: 169 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,95 @@
11
#!/bin/bash
22
#
33
#
4+
5+
SCRIPT_NAME="$(basename "$0")"
6+
7+
print_help() {
8+
cat <<EOF
9+
Usage: $SCRIPT_NAME --npm <name> [--password <password>]
10+
11+
Options:
12+
--npm <name> Required. Name or identifier used for the certificate. Must be in the form "npm-#"
13+
--password <string> Optional. Password to secure the PKCS#12 (.p12) file. If not provided the scipt will use the script default.
14+
-h, --help Show this help message and exit.
15+
16+
Example:
17+
./$SCRIPT_NAME --npm npm-123
18+
./$SCRIPT_NAME --npm npm-123 --password secret123
19+
EOF
20+
}
21+
22+
# Initialize Required Input variables
23+
NPM_NAME=""
24+
PKCS12_PASSWORD=""
25+
26+
# Exit early and show help if no arguments were provided
27+
if [[ $# -eq 0 ]]; then
28+
echo -e "\nERROR - No arguments provided.\n"
29+
print_help
30+
exit 1
31+
fi
32+
33+
# Parse arguments
34+
while [[ $# -gt 0 ]]; do
35+
case "$1" in
36+
--npm)
37+
NPM_NAME="$2"
38+
NPM_NAME="${NPM_NAME,,}"
39+
REGEX_FOR_NPM_MATCH='^(N|n)(P|p)(M|m)\-[0-9]+$'
40+
VALIDATE_NPM_NAME=$(echo "$NPM_NAME" | grep -P "$REGEX_FOR_NPM_MATCH")
41+
42+
#Validate the NPM_NAME
43+
if [[ -z "$2" || "$2" == --* ]]
44+
then
45+
echo -e "\nERROR: --npm requires a value."
46+
exit 1
47+
fi
48+
if [[ -z "$NPM_NAME" ]]
49+
then
50+
echo -e "\nERROR: --npm requires a value."
51+
exit 1
52+
elif [[ -z "$VALIDATE_NPM_NAME" ]]
53+
then
54+
echo -e "\nERROR: --npm input must be in the form npm-#\n"
55+
exit 1
56+
fi
57+
58+
shift 2
59+
;;
60+
--password)
61+
#Verify the argument data was not passed in as password instead if the user did not supply a password.
62+
if [[ -z "$2" || "$2" == --* ]]
63+
then
64+
echo -e "\nERROR: --password requires a value."
65+
exit 1
66+
fi
67+
PKCS12_PASSWORD="$2"
68+
shift 2
69+
;;
70+
-h|--help)
71+
print_help
72+
exit 0
73+
;;
74+
*)
75+
echo -e "\nError: Unsupported argument: $1\n"
76+
print_help
77+
exit 1
78+
;;
79+
esac
80+
done
81+
82+
83+
#Use the default password if the user did not supply one.
84+
#If the Password Variable is passed in this script will use it for encrypting the p12 private key when generating the p12.
85+
#If the password was not provided then the default password (below) will be used.
86+
if [[ -z "$PKCS12_PASSWORD" ]]
87+
then
88+
#The Password Provided by the user (Default: password)
89+
PKCS12_PASSWORD="password"
90+
fi
91+
92+
493
# Selected Cipher would be passed in from the GUI but this is an example of what the GUI could provide for a selected CIPHER
594
SELECTED_CIPHER="aes-256-cbc"
695
SELECTED_CIPHER="${SELECTED_CIPHER^^}"
@@ -17,7 +106,7 @@ PATH_TO_ARCHIVE="/etc/letsencrypt/archive"
17106

18107

19108
#The Specific Folder Name for the NPM cert, Should be the text "npm" followe by a hyphen and numbers (I.E. npm-3)
20-
NPM_FOLDER="npm-10"
109+
NPM_FOLDER="$NPM_NAME"
21110

22111
#The Directory containing the certificate and privcate key for a npm configuration
23112
NPM_PATH="$PATH_TO_LIVE/$NPM_FOLDER"
@@ -59,11 +148,16 @@ then
59148
#The Name to give the PKCS12 file generated by the script (with extension). It will be placd in the same file as the private key file.
60149
PKCS12_FILE_NAME="fullpkcs12-$INCREMENT_NUMBER.p12"
61150
echo "PKCS12 FILE NAME: $PKCS12_FILE_NAME"
151+
ROOT_CERTIFICATE_FILENAME="root$INCREMENT_NUMBER.pem"
62152
PKCS12_SIMLINK_NAME="fullpkcs12.p12"
153+
ROOT_CERTIFICATE_SIMLINK_NAME="root.pem"
63154
else
64155
#The Name to give the PKCS12 file generated by the script (with extension). It will be placd in the same file as the private key file.
65156
PKCS12_FILE_NAME="fullpkcs12.p12"
66157
echo "PKCS12 FILE NAME: $PKCS12_FILE_NAME"
158+
ROOT_CERTIFICATE_FILENAME="root$INCREMENT_NUMBER.pem"
159+
PKCS12_SIMLINK_NAME="fullpkcs12.p12"
160+
ROOT_CERTIFICATE_SIMLINK_NAME="root.pem"
67161
fi
68162

69163

@@ -74,13 +168,13 @@ echo "PKCS12 FULL PATH: $PKCS12_FULL_PATH"
74168
PKCS12_SIMLINK_PATH="$NPM_PATH/$PKCS12_SIMLINK_NAME"
75169
echo "PKCS12 SIMLINK PATH: $PKCS12_SIMLINK_PATH"
76170

77-
#Root Certificate File Name (with extension) the root file does not exist so will need to create it later from the fullchain
78-
ROOT_CERTIFICATE="root$INCREMENT_NUMBER.pem"
79-
ROOT_FULL_PATH=$(dirname "$GET_PATH")"/$ROOT_CERTIFICATE"
80-
echo "ROOT_FULL_PATH: $ROOT_FULL_PATH"
81171

82-
#The Password Provided by the user (Default: password)
83-
PKCS12_PASSWORD="password"
172+
#Root Certificate File Name (with extension) the root file does not exist so will need to create it later from the fullchain
173+
#ROOT_CERTIFICATE_FILENAME="root$INCREMENT_NUMBER.pem"
174+
ROOT_FULL_PATH=$(dirname "$GET_PATH")"/$ROOT_CERTIFICATE_FILENAME"
175+
echo "ROOT FULL PATH: $ROOT_FULL_PATH"
176+
ROOT_CERTIFICATE_SIMLINK_PATH="$NPM_PATH/$ROOT_CERTIFICATE_SIMLINK_NAME"
177+
echo "ROOT CERTIFICATE SIMLINK PATH: $ROOT_CERTIFICATE_SIMLINK_PATH"
84178

85179
#Create an Array of CIPHER ALGORITHMS
86180
#Remove the lines "Legacy:" and "Provided:" from the created List of Cipher Algorithms
@@ -94,6 +188,13 @@ ARRAY_OF_DIGEST_ALGORITHMS=($(echo "${LIST_OF_DIGEST_ALGORITHMS}" | sed -E '/^Le
94188
#ARRAY of Temp files that are generated by the script. At the end they will be removed
95189
declare -a TEMP_FILES_ARRAY=()
96190

191+
#owner, used when running chown
192+
OWNER="npm"
193+
#Group, used when running chown
194+
GROUP="npm"
195+
196+
#Keep the root Certificate generated by this script, or delete it after using it temporarily
197+
KEEP_ROOT_CERTIFICATE=true
97198

98199
#Start This script only if The Certificate Chain File exist, and the private key exist, and both are also readable.
99200
if [[ -z "$CERTIFICATE_CHAIN_FILE_FULL_PATH" ]] && [[ -f "$CERTIFICATE_CHAIN_FILE_FULL_PATH" ]] && [[ -r "$CERTIFICATE_CHAIN_FILE_FULL_PATH" ]]
@@ -119,7 +220,7 @@ then
119220
TEMP_FILES_ARRAY+=("cert_temp_01.pem")
120221
TEMP_FILES_ARRAY+=("cert_temp_02.pem")
121222

122-
FOUND_ROOT_CERTIFICATE=false
223+
FOUND_ROOT_CERTIFICATE_FILENAME=false
123224
# Loop through each extracted certificate
124225
for cert_temp_file in cert_temp_*.pem
125226
do
@@ -137,15 +238,15 @@ then
137238
if [[ "$subject" == "$issuer" ]]
138239
then
139240
echo -e "\n Found root certificate: $cert_temp_file"
140-
FOUND_ROOT_CERTIFICATE=true
241+
FOUND_ROOT_CERTIFICATE_FILENAME=true
141242
#Save the certificate file in the same directory as the private key file
142243
cp "$cert_temp_file" "$CERTIFICATE_FILE_FULL_PATH"
143244
break
144245
fi
145246
done
146247

147248
#If the root certificate was not found in the certificate chain
148-
if [[ "$FOUND_ROOT_CERTIFICATE" == false ]]
249+
if [[ "$FOUND_ROOT_CERTIFICATE_FILENAME" == false ]]
149250
then
150251
#If the Root Certificate was not found within the certificate chain then obtain it from the intermediate chain
151252
# Extract each certificate into its own file
@@ -196,7 +297,7 @@ then
196297
TEMP_FILES_ARRAY+=("issuer_cert_temp.der")
197298
fi
198299

199-
echo -e "\nProcessing $ROOT_CERTIFICATE ..."
300+
echo -e "\nProcessing $ROOT_CERTIFICATE_FILENAME ..."
200301

201302
# Get subject and issuer
202303
issuer_subject=$(openssl x509 -noout -subject -issuer -in "$ROOT_FULL_PATH" 2>/dev/null)
@@ -301,14 +402,14 @@ then
301402
echo -e "\nSuccessfully generated PKCS12"
302403
echo -e "\nPKCS12 Full Path: $PKCS12_FULL_PATH"
303404

304-
#Change the ownership to npm:npm
305-
chown npm:npm "$PKCS12_FULL_PATH"
405+
#Change the ownership to "$OWNER:$GROUP"
406+
chown "$OWNER:$GROUP" "$PKCS12_FULL_PATH"
306407

307408
if [[ $? -eq 0 ]]
308409
then
309-
echo -e "\nSuccessfully changed $PKCS12_FULL_PATH User and Group ownership to npm"
410+
echo -e "\nSuccessfully changed $PKCS12_FULL_PATH User and Group ownership to $OWNER:$GROUP"
310411
else
311-
echo "\nERROR - Unable to change $PKCS12_FULL_PATH User and Group ownership to npm"
412+
echo "\nERROR - Unable to change $PKCS12_FULL_PATH User and Group ownership to $OWNER:$GROUP"
312413
exit 1
313414
fi
314415

@@ -329,33 +430,35 @@ then
329430
then
330431
echo -e "\nERROR - Relative Path variable is empty."
331432
fi
332-
333-
433+
334434
#ln -s "to-here" <- "from-here". The from-here should not exist yet, it is to be created, while the to-here should already exist.
335435
#Create the links relative to the path
336436
ln -sf "$RELATIVE_SOURCE" "$SYMLINK_DIR/$SYMLINK_NAME"
337437

338438
if [[ $? -eq 0 ]]
339439
then
340-
echo -e "\nSuccessfully created SimLink"
440+
echo " Successfully created SimLink"
341441
else
342442
echo "\nERROR - Unable to create SimLink"
343443
exit 1
344444
fi
345445

346-
#Change the ownership to npm:npm for SimLink
347-
chown -h npm:npm "$PKCS12_SIMLINK_PATH"
446+
#Change the ownership to "$OWNER:$GROUP" for SimLink
447+
chown -h "$OWNER:$GROUP" "$PKCS12_SIMLINK_PATH"
348448

349449
if [[ $? -eq 0 ]]
350450
then
351-
echo -e "\nSuccessfully changed $PKCS12_SIMLINK_PATH User and Group ownership to npm"
451+
echo " Successfully changed $PKCS12_SIMLINK_PATH User and Group ownership to $OWNER:$GROUP"
352452
else
353-
echo "\nERROR - Unable to change $PKCS12_SIMLINK_PATH User and Group ownership to npm"
453+
echo "\nERROR - Unable to change $PKCS12_SIMLINK_PATH User and Group ownership to $OWNER:$GROUP"
354454
exit 1
355455
fi
356456

357-
#The Root Certificate that was created by this script is no longer needed after generating the .p12 file so add it to the array of temporary files to delete
358-
TEMP_FILES_ARRAY+=("$ROOT_FULL_PATH") # Comment out if you want to keep the Root Certificate geenrated by this script (Generated from downloaing the root from the Intermediate CA Certificate).
457+
if [[ "$KEEP_ROOT_CERTIFICATE" == false ]]
458+
then
459+
#The Root Certificate that was created by this script is no longer needed after generating the .p12 file so add it to the array of temporary files to delete
460+
TEMP_FILES_ARRAY+=("$ROOT_FULL_PATH") # When $KEEP_ROOT_CERTIFICATE is set to true the script will keep the file and create a simlink for it as well
461+
fi
359462

360463
echo -e "\n\nCleaning up temporary files..."
361464
for temp_file in "${TEMP_FILES_ARRAY[@]}"
@@ -370,6 +473,48 @@ then
370473
echo -e " Successfully deleted '$temp_file'"
371474
fi
372475
done
476+
477+
#If the Root Path still exist then the user must have comented out the deletion of the root.pem file. So generate a simlink for it as well.
478+
if [[ -f "$ROOT_FULL_PATH" ]]
479+
then
480+
echo -e "\nCreating SimLink for root certificate..."
481+
#Change the ownership to "$OWNER:$GROUP"
482+
chown "$OWNER:$GROUP" "$ROOT_FULL_PATH"
483+
484+
# Get the directory where the symlink will be created
485+
SYMLINK_DIR="$(dirname "$ROOT_CERTIFICATE_SIMLINK_PATH")"
486+
487+
# Get the relative path from the symlink destination to the source file
488+
RELATIVE_SOURCE="$(realpath --relative-to="$SYMLINK_DIR" "$ROOT_FULL_PATH")"
489+
490+
if [[ -z "$RELATIVE_SOURCE" ]]
491+
then
492+
echo -e "\nERROR - Relative Path variable is empty."
493+
fi
494+
495+
#ln -s "to-here" <- "from-here". The from-here should not exist yet, it is to be created, while the to-here should already exist.
496+
#Create the links relative to the path
497+
ln -sf "$RELATIVE_SOURCE" "$SYMLINK_DIR/$ROOT_CERTIFICATE_SIMLINK_NAME"
498+
499+
if [[ $? -eq 0 ]]
500+
then
501+
echo " Successfully created SimLink"
502+
else
503+
echo "\nERROR - Unable to create SimLink"
504+
exit 1
505+
fi
506+
507+
#Change the ownership to "$OWNER:$GROUP" for SimLink
508+
chown -h "$OWNER:$GROUP" "$ROOT_CERTIFICATE_SIMLINK_PATH"
509+
510+
if [[ $? -eq 0 ]]
511+
then
512+
echo " Successfully changed $ROOT_CERTIFICATE_SIMLINK_PATH User and Group ownership to $OWNER:$GROUP"
513+
else
514+
echo "\nERROR - Unable to change $ROOT_CERTIFICATE_SIMLINK_PATH User and Group ownership to $OWNER:$GROUP"
515+
exit 1
516+
fi
517+
fi
373518
echo ""
374519
else
375520
echo -e "\nERROR - Unable to Generate PKCS12 '$PKCS12_FULL_PATH'\n"

0 commit comments

Comments
 (0)