Skip to content

Instantly share code, notes, and snippets.

@catchdave
Last active November 5, 2024 01:02
Show Gist options
  • Select an option

  • Save catchdave/ff9c7d7a396a3201cfb14f912d3e5cda to your computer and use it in GitHub Desktop.

Select an option

Save catchdave/ff9c7d7a396a3201cfb14f912d3e5cda to your computer and use it in GitHub Desktop.
Find all .PEM certificates on Synology
#!/bin/bash
#
# Finds all .pem certs on synology under /usr.
#
# Usage: ./find_all_certs.sh [--valid-only | --invalid-only]
# --valid-only - Only show valid certificates found
# --invalid-only - Only show invalid certificates found
if [ "$EUID" -ne 0 ]; then
echo "This script must be run as root or with sudo."
exit 1
fi
# Color codes
GREEN="\033[1;32m"
RED="\033[0;31m"
YELLOW="\033[0;33m"
BLUE="\033[0;95m"
NC="\033[0m" # No Color
BOLD="\033[1m"
HEAD_COL="\033[1;97m\033[1;100m"
# Initialize variables
NOW_TS=$(date +%s)
BASE_DIR=/usr/
prev_dir=""
valid_count=0
count=0
total_count=0
total_valid=0
total_invalid=0
total_dirs_no_valid=0
total_dirs=0
valid_status=
mode=all
parse_args() {
while [[ $# -gt 0 ]]; do
case "$1" in
--valid-only)
mode=valid_only
shift
;;
--invalid-only)
mode=invalid_only
shift
;;
*)
echo "Usage: $0 [--valid-only | --invalid-only]"
exit 1
;;
esac
done
}
main() {
parse_args "$@"
print_header
while read -r cert; do
cert_dir=$(dirname "$cert")
cert_file=$(basename "$cert")
check_valid_cert "$cert" || continue
# Print the directory heading if it's new
if [[ "$cert_dir" != "$prev_dir" ]]; then
process_dir_change
fi
((count++))
((total_count++))
parse_cert_info "$cert" # Sets the vars: $from, $to, $subject, $issuer, $validity_color & $valid_status
check_filter "$valid_status" || continue
print_cert_line "$validity_color" "$cert_file" "$from" "$to" "$subject" "$issuer"
done < <(find "$BASE_DIR" -type f -name "*.pem" -not -path "/volume*" 2>/dev/null)
print_dir_warn "$cert_dir"
print_summary
}
# Skip files that are not valid certificates
check_valid_cert() {
local cert=$1
if [[ ! "$(head -n 1 "$cert")" == "-----BEGIN CERTIFICATE-----" ]]; then
return 0
fi
return 1
}
# Execute filtering based on mode
check_filter() {
local valid_status=$1
if [[ "$mode" == "valid_only" && "$valid_status" == "invalid" ]]; then
return 1
elif [[ "$mode" == "invalid_only" && "$valid_status" == "valid" ]]; then
return 1
fi
return 0
}
print_cert_line() {
local color=$1
LINE_FORMAT="| %-44s | COLOR%-28s${NC} | COLOR%-28s${NC} | %-20s | %-30s |\n"
cur_format="${LINE_FORMAT//COLOR/${color}}"
printf "$cur_format" "$2" "$3" "$4" "$5" "$6"
}
print_dir_warn() {
if [[ "$count" == "0" ]]; then
return
fi
if [[ "$valid_count" == "0" ]]; then
echo -e "${RED}${BOLD}[WARN] No Valid Certs in: ${NC}${RED}$1/${NC}"
((total_dirs_no_valid++))
fi
}
print_header() {
LINE_FORMAT="${HEAD_COL}| %-44s | %-28s | %-28s | %-20s | %-30s |${NC}\n"
printf "$LINE_FORMAT" "Filename" "Valid From" "Valid To" "Domain" "Issuer"
}
process_dir_change() {
print_dir_warn "$prev_dir"
((total_dirs++))
valid_count=0
count=0
prev_dir="$cert_dir"
printf "| ${BLUE}%-163s${NC} |\n" "$cert_dir"
}
print_summary() {
local LINE_FORMAT="${HEAD_COL}%-28s${NC} | ${BOLD}%-10s${NC}\n"
echo ""
echo -e "${BOLD}=== Summary ===${NC}"
printf "$LINE_FORMAT" "Total Directories" "$total_dirs"
printf "$LINE_FORMAT" "Total Certificates" "$total_count"
printf "$LINE_FORMAT" "Total Dirs w/ no valid cert" "$total_dirs_no_valid"
printf "$LINE_FORMAT" "Total Valid Certs" "$total_valid"
printf "$LINE_FORMAT" "Total InValid Certs" "$total_invalid"
}
parse_cert_info() {
local cert="$1"
# Parse details from cert_info
local cert_info=$(openssl x509 -in "$cert" -noout -subject -issuer -startdate -enddate 2>/dev/null)
subject=$(echo "$cert_info" | sed -n '/^subject=/s/.*[Cc][Nn][ ]*=[ ]*\([^,]*\).*/\1/p')
issuer=$(echo "$cert_info" | sed -n '/^issuer=/s/.*[Oo][ ]*=[ ]*\([^,]*\).*/\1/p')
from=$(echo "$cert_info" | sed -n 's/^notBefore=//p')
to=$(echo "$cert_info" | sed -n 's/^notAfter=//p')
# Convert dates to Unix timestamps for comparison
local from_ts=$(date -d "$from" +%s)
local to_ts=$(date -d "$to" +%s)
# Determine validity of certs
valid_status="invalid"
if (( from_ts > NOW_TS )); then
validity_color=$YELLOW # Not reached
((total_invalid++))
elif (( to_ts < NOW_TS )); then
validity_color=$RED # Expired
((total_invalid++))
else
validity_color=$GREEN # Current
valid_status="valid"
((valid_count++))
((total_valid++))
fi
}
### Run main program ###
main "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment