-
-
Save AfroThundr3007730/ba99753dda66fc4abaf30fb5c0e5d012 to your computer and use it in GitHub Desktop.
#!/bin/bash | |
# Imports DoD root certificates into Linux CA store | |
# Version 0.4.2 updated 20250425 by AfroThundr | |
# SPDX-License-Identifier: GPL-3.0-or-later | |
# For issues or updated versions of this script, browse to the following URL: | |
# https://gist.github.com/AfroThundr3007730/ba99753dda66fc4abaf30fb5c0e5d012 | |
# Dependencies: curl gawk openssl unzip wget | |
set -euo pipefail | |
shopt -s extdebug nullglob | |
add_dod_certs() { | |
local bundle cert certdir file form tmpdir url update | |
trap '[[ -d ${tmpdir:-} ]] && rm -fr $tmpdir' EXIT INT TERM | |
# Location of bundle from DISA site | |
url='https://public.cyber.mil/pki-pke/pkipke-document-library/' | |
bundle=$(curl -s $url | awk -F '"' 'tolower($2) ~ /dod.zip/ {print $2}') | |
# Set cert directory and update command based on OS | |
[[ -f /etc/os-release ]] && source /etc/os-release | |
if [[ ${ID:-} =~ (fedora|rhel|centos) || | |
${ID_LIKE:-} =~ (fedora|rhel|centos) ]]; then | |
certdir=/etc/pki/ca-trust/source/anchors | |
update='update-ca-trust' | |
elif [[ ${ID:-} =~ (debian|ubuntu|mint) || | |
${ID_LIKE:-} =~ (debian|ubuntu|mint) ]]; then | |
certdir=/usr/local/share/ca-certificates | |
update='update-ca-certificates' | |
else | |
certdir=${1:-} && update=${2:-} | |
fi | |
[[ ${certdir:-} && ${update:-} ]] || { | |
printf 'Unable to autodetect OS using /etc/os-release.\n' | |
printf 'Please provide CA certificate directory and update command.\n' | |
printf 'Example: %s /cert/store/location update-cmd\n' "${0##*/}" | |
exit 1 | |
} | |
# Extract the bundle | |
wget -qP "${tmpdir:=$(mktemp -d)}" "$bundle" | |
unzip -qj "$tmpdir"/"${bundle##*/}" -d "$tmpdir" | |
# Check for existence of PEM or DER format p7b. | |
for file in "$tmpdir"/*_{DoD,dod}{.,_}{pem,der}.p7b; do | |
# Iterate over glob instead of testing directly (SC2144) | |
[[ -f ${file:-} ]] && | |
form=${file%.*} && form=${form##*_} && form=${form##*.} && break | |
done | |
[[ ${form:-} && ${file:-} ]] || { printf 'No bundles found!\n' && exit 1; } | |
# Convert the PKCS#7 bundle into individual PEM files | |
openssl pkcs7 -print_certs -inform "$form" -in "$file" | | |
awk -v d="$tmpdir" \ | |
'BEGIN {c=0} /subject=/ {c++} {print > d "/cert." c ".pem"}' | |
# Rename the files based on the CA name | |
for cert in "$tmpdir"/cert.*.pem; do | |
mv "$cert" "$certdir"/"$( | |
openssl x509 -noout -subject -in "$cert" | | |
awk -F '(=|= )' '{print gensub(/ /, "_", "g", $NF)}' | |
)".crt | |
done | |
# Remove temp files and update certificate stores | |
rm -fr "$tmpdir" && $update | |
} | |
# Only execute if not being sourced | |
[[ ${BASH_SOURCE[0]} == "$0" ]] || return 0 && add_dod_certs "$@" |
@R1ceAR0n1e - You need to execute with bash
. Either set execution bit with chmod
or execute as bash add-dod-certs.sh
. Also, need to ensure you have bash installed on your OS.
I've implemented add-dod-certs.sh in an Ansible playbook for Fedora/RHEL systems. It can be easily extended to support Ubuntu/Debian systems. Credit to AfroThundr for the original bash script that guided this.
# vim: ft=yaml.ansible
# ensure community.crypto collection is installed on control node
---
- name: Install DoD certificates system-wide
connection: local
hosts: 127.0.0.1
become: true
vars:
dod_certs_url: "https://dl.dod.cyber.mil/wp-content/uploads/pki-pke/zip/unclass-certificates_pkcs7_DoD.zip"
system_cert_dir: "/etc/pki/ca-trust/source/anchors"
tasks:
- name: Extract DoD certs zip
ansible.builtin.unarchive:
src: "{{ dod_certs_url }}"
dest: "/tmp"
list_files: true
remote_src: true
register: certs
- name: Locate DoD PKCS#7 cert bundle
ansible.builtin.set_fact:
pkcs7_bundle_path: >-
{{ "/tmp/" + (certs.files
| select('match', '.*(?i:dod)\.pem\.p7b$')
| first) }}
- name: Extract certificates from PKCS#7 bundle
ansible.builtin.command: >
openssl pkcs7 -print_certs -inform PEM -in {{ pkcs7_bundle_path }}
register: pkcs7_bundle_output
changed_when: false
- name: Split certs into individual PEMs
ansible.builtin.set_fact:
cert_list: "{{ pkcs7_bundle_output.stdout | community.crypto.split_pem }}"
- name: Get cert info
community.crypto.x509_certificate_info:
content: "{{ item }}"
loop: "{{ cert_list }}"
register: cert_info
- name: Build cert data structure
ansible.builtin.set_fact:
cert_data: >-
{{ cert_data | default([]) + [
{
'content': item.0,
'file_name': (item.1.subject.commonName
| replace(' ', '_')
| regex_replace('$', '.crt'))
}
]
}}
loop: "{{ cert_list | zip(cert_info.results) | list }}"
- name: Install certs to system trust store
ansible.builtin.copy:
content: "{{ item.content }}"
dest: "{{ system_cert_dir }}/{{ item.file_name }}"
mode: '0644'
owner: root
group: root
loop: "{{ cert_data }}"
register: cert_installation
- name: Update CA trust
ansible.builtin.command: update-ca-trust
changed_when: cert_installation.changed
when: cert_installation.changed
edit: improved the pkcs7 bundle regex
Just a heads up, the public.cyber.mil site went through some changes. Those changes are preventing the successful operation of the add-dod-certs.sh
. The process of "Locating the bundle..." on lines 18-20 is no longer working as expected. I believe they have disabled the directory listing capability to prevent cross-site scripting.
As a workaround, I have hardcoded my script with the following changes:
url='https://dl.dod.cyber.mil/wp-content/uploads/pki-pke/zip/'
bundle="${url}unclass-certificates_pkcs7_DoD.zip"
After incorporating those changes, the remainder of v0.4.2 script works properly.
I just now noticed @victor-almanzar Ansible playbook version has the new url value. Wish I had seen that earlier.
Thank You, All. Worked Perfectly with the hardcoded parameters above.
Just tried to run this on Linux Mint Cinnamon 22.1 (xia) using the instructions found here:
https://community.linuxmint.com/tutorial/view/313
When I attempt to execute the file in my terminal, I'm getting this error:
./add-dod-certs.sh: 11: set: Illegal option -o pipefail
What am I doing wrong?