How to import multiple certificates in a single file with keytool [to cert store]?
keytool -importcert only imports the first one.
How to import multiple certificates in a single file with keytool [to cert store]?
keytool -importcert only imports the first one.
A bash script that will import all certificates from a PEM file:
#!/bin/bash
PEM_FILE=$1
PASSWORD=$2
KEYSTORE=$3
# number of certs in the PEM file
CERTS=$(grep 'END CERTIFICATE' $PEM_FILE| wc -l)
# For every cert in the PEM file, extract it and import into the JKS keystore
# awk command: step 1, if line is in the desired cert, print the line
# step 2, increment counter when last line of cert is found
for N in $(seq 0 $(($CERTS - 1))); do
ALIAS="${PEM_FILE%.*}-$N"
cat $PEM_FILE |
awk "n==$N { print }; /END CERTIFICATE/ { n++ }" |
keytool -noprompt -import -trustcacerts \
-alias $ALIAS -keystore $KEYSTORE -storepass $PASSWORD
done
For example:
./jks_import_pem TrustedCAs.PEM changeit truststore.jks
If you want to include the CA certificates you should add the -trustcacerts
option.
If you have multiple certificate chains in one PEM file you will have to split the file.
I wanted to do the same thing, but apparently it's only possible if you're importing the key as well:
There are two types of entries- key entries and trusted cert entries, and only the key entry can contain a "chain" of certificates, attached to it. The trusted cert entries are all single cert entries.
(https://www.java.net/node/674524#comment-709695)
I even tried converting to PKCS#7 format first, but it didn't work, either because of the above reason or because my version of keytool was too old.
So had to first split the file into separate certs:
cat certchain.pem | awk 'split_after==1{n++;split_after=0} /-----END CERTIFICATE-----/ {split_after=1} {print > ("cert" n ".pem")}'
(https://serverfault.com/q/391396/58568)
Then import each one individually.
You can simply use the free and easy to use GUI Tool Keystore Explorer to import and manage multiple certificates.
You can use the p11-kit tool that can does this very quicky. The only constraint is that it reads the certificates from /etc/pki/ca-trust/source/
/usr/bin/p11-kit extract --format=java-cacerts --filter=ca-anchors \
--overwrite --purpose server-auth $DEST/java/cacerts
Importing certs with proper key alias name:
#!/bin/bash
PEM_FILE=$1
PASSWORD=$2
KEYSTORE=$3
# number of certs in the PEM file
CERTS=$(grep 'END CERTIFICATE' $PEM_FILE| wc -l)
# For every cert in the PEM file, extract it and import into the JKS keystore
# awk command: step 1, if line is in the desired cert, print the line
# step 2, increment counter when last line of cert is found
for N in $(seq 0 $(($CERTS - 1))); do
rm -f tmp.pem
cat $PEM_FILE |
awk "n==$N { print }; /END CERTIFICATE/ { n++ }" > tmp.pem
ALIAS=$(openssl x509 -in tmp.pem -noout -text | grep Subject: | sed 's/.*CN=//')
#Optional: adding index to alias name
ALIAS=$(echo "${N}_${ALIAS}")
echo $ALIAS
cat $PEM_FILE |
awk "n==$N { print }; /END CERTIFICATE/ { n++ }" |
keytool -noprompt -import -trustcacerts \
-alias "${ALIAS}" -keystore $KEYSTORE -storepass $PASSWORD
done
I slightly improved the top answer to retain the alias names:
#!/bin/bash
PEM_FILE=$1
PASSWORD=$2
KEYSTORE=$3
# number of certs in the PEM file
CERTS=$(grep 'END CERTIFICATE' $PEM_FILE| wc -l)
# For every cert in the PEM file, extract it and import into the JKS keystore
# awk command: step 1, if line is in the desired cert, print the line
# step 2, increment counter when last line of cert is found
for N in $(seq 0 $(($CERTS - 1))); do
ALIAS=`cat $PEM_FILE | awk "n==$N { print }; /END CERTIFICATE/ { n++ }" | grep '#' | cut -c3-`
# echo "$ALIAS"
cat $PEM_FILE |
awk "n==$N { print }; /END CERTIFICATE/ { n++ }" |
keytool -noprompt -import -trustcacerts \
-alias "$ALIAS" -keystore $KEYSTORE -storepass $PASSWORD
done
You can import multiple CA certificates within one pem file. Ensure the root CA is first, followed by the rest.
The given answers are not really Ansible solutions, more like alternatives.
What i wrote below works for the 1st certificate, but it's not looping. Any ideas?
java_install_keystore_cert: true
java_keystore_certs: "{{ apps.jira.keystore_certs }}"
java_keystore_cert_alias: test
apps:
jira:
keystore_certs:
- certName: xyz.xxx.com
certFileName: xyz.xxx.com.pem
- certName: xxx.com
certFileName: xxx.com.pem
- name: Copy SSL certificate to remote server
copy:
src: "{{ java_keystore_certs[0].certFileName }}"
#src: "{{ java_keystore_cert_file }}"
dest: /tmp/
when: java_install_keystore_cert|default(false)
- name: Determine Java cacerts keystore location
find:
paths: "{{ java_home }}/"
patterns: 'cacerts'
recurse: yes
register: cacerts_file
when: java_install_keystore_cert|default(false)
- name: Import SSL certificate to Java cacerts keystore
java_cert:
cert_alias: "{{ java_keystore_cert_alias }}"
#cert_path: "/tmp/{{ java_keystore_cert_file }}"
cert_path: "/tmp/{{ java_keystore_certs[0].certFileName }}"
keystore_path: "{{ cacerts_file.files[0].path }}"
keystore_pass: changeit
executable: "{{ java_home }}/bin/keytool"
state: present
when: java_install_keystore_cert|default(false) and cacerts_file is defined
I also switched to a not-just Ansible solution....
copy:
src: "{{ java_keystore_cert_file }}"
dest: /tmp/
when: java_install_keystore_cert|default(false)
- name: Determine Java keystore (cacerts) location
find:
paths: "{{ java_home }}/"
patterns: 'cacerts'
recurse: yes
register: cacerts_file
when: java_install_keystore_cert|default(false)
# Not using the java_cert module (anymore) since that imports the first certificate only
# Always use .pem (simply rename .crt or .cert to .pem if needed)
# The .pem file should contain one or more public certificates, no private key(s) or chain
- name: Transfer the import certificate script
copy:
src: files/scripts/importcert.sh
dest: /tmp/importcert.sh
mode: 0700
when: java_install_keystore_cert|default(false) and cacerts_file is defined
- name: Import certificate to Java keystore
command: sh /tmp/importcert.sh "/tmp/{{ java_keystore_cert_file }}" "{{ java_home }}/bin/keytool" changeit "{{ cacerts_file.files[0].path }}"
when: java_install_keystore_cert|default(false) and cacerts_file is defined
#!/bin/bash
PEM_FILE=$1
KEYTOOL=$2
PASSWORD=$3
KEYSTORE=$4
# number of certs in the PEM file
CERTS=$(grep 'END CERTIFICATE' $PEM_FILE| wc -l)
# For every cert in the PEM file, extract it and import into the JKS keystore
# awk command: step 1, if line is in the desired cert, print the line
# step 2, increment counter when last line of cert is found
for N in $(seq 0 $(($CERTS - 1))); do
ALIAS="${PEM_FILE%.*}-$N"
cat $PEM_FILE |
awk "n==$N { print }; /END CERTIFICATE/ { n++ }" |
$KEYTOOL -noprompt -import -trustcacerts \
-alias $ALIAS -keystore $KEYSTORE -storepass $PASSWORD
done