Skip to content

Instantly share code, notes, and snippets.

@obscurerichard
Last active August 29, 2015 14:06
Show Gist options
  • Save obscurerichard/1b144e78aae3ca2f0813 to your computer and use it in GitHub Desktop.
Save obscurerichard/1b144e78aae3ca2f0813 to your computer and use it in GitHub Desktop.
CA Certificate Bundle De-Duplication script
#!/bin/bash
# dedupe-cacerts.sh
#
# De-duplicates a certificate authority bundle, such as cacerts.pem
# or ca-bundle.crt. This will emit CA certificates in the order they
# appeared, annotating them with full info on each certificate,
# omitting any duplicate certificates.
#
# Usage:
#
# dedupe-cacerts.sh <name-of-cacerts-file>
# dedupe-cacerts.sh - # read from stdin
# dedupe-cacerts.sh # also read from stdin
#
# Example:
# dedupe-cacerts.sh /etc/pki/tls/certs/ca-bundle.crt > bundle.crt
#
# License:
#
# Copyright (c) 2014 Richard Bullington-McGuire
# Copyright (c) 2014 The Obscure Organization
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
# Use unofficial bash strict mode
# http://redsymbol.net/articles/unofficial-bash-strict-mode/
#
set -euo pipefail
IFS=$'\n\t'
debug="/bin/false"
# Uncomment to enable debug output
#debug="/bin/true"
if "$debug"; then
debug_out=/dev/stdout
else
debug_out=/dev/null
fi
scratch_dir=$(mktemp -d -t tmp.XXXXXXXXXX)
function finish {
"$debug" && echo removing "$scratch_dir"
rm -rf "$scratch_dir"
}
trap finish EXIT
"$debug" && echo scratch_dir is "$scratch_dir"
# Credit to http://stackoverflow.com/a/13087801
function abspath {
if [[ -d "$1" ]]
then
pushd "$1" >/dev/null
pwd
popd >/dev/null
elif [[ -e "$1" ]]
then
pushd "$(dirname "$1")" >/dev/null
echo "$(pwd)/$(basename "$1")"
popd >/dev/null
else
echo "$1 does not exist!" >&2
return 127
fi
}
# Parse optional command line argument
cacert=${1:-}
if [ -z "$cacert" -o "$cacert" = "-" ]; then
# Use stdin for certificate input file
cacert="-"
else
# Use full path to certificate file since we are going to cd next
# Credit to http://stackoverflow.com/a/7126780
cacert=$(abspath "$cacert")
fi
cd "$scratch_dir"
csplit -s -n 6 -f cert "$cacert" '/--*BEGIN CERTIFICATE.*$/' '{*}'
for cert in *; do
scratch_file=$(mktemp -t tmp.XXXXXXXXXX)
# Output the full x509 text information header
if openssl x509 -in "$cert" -text > "$scratch_file" 2>"$debug_out"; then
mv "$scratch_file" "$cert"
else
# Remove any files that don't contain valid cert509 certificates
rm "$cert" "$scratch_file"
fi
done
# Delete any duplicate certificates
"$debug" && echo Duplicate certificates are:
fdupes -d -N -q . > "$debug_out"
"$debug" && echo Remaining files:
"$debug" && ls
cat cert*
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment