File list-apt-key-days-to-expiry of Package kimi-utils-ubuntu
#!/usr/bin/env bash
# Exit non-zero if any APT key has < THRESH_DAYS days until expiry.
set -euo pipefail
IFS=$'\n\t'
export LANG=C
export LC_ALL=C
# Default directory list to check
KEYRING_DIRS=(/etc/apt/trusted.gpg.d /etc/apt/keyrings /usr/share/keyrings)
THRESH_DAYS=30 # Set the threshold days to 30
# Check for arguments to set THRESH_DAYS
if [[ $# -gt 0 ]]; then
if [[ "$1" =~ ^[0-9]+$ ]]; then
THRESH_DAYS="$1"
else
echo "Error: THRESH_DAYS must be a positive integer." >&2
exit 1
fi
fi
# Check if output is a terminal
if [[ -t 1 ]]; then
RED=$(tput setaf 1) # Red color
GREEN=$(tput setaf 2) # Green color
NC=$(tput sgr0) # Reset to default color
else
RED=""
GREEN=""
NC=""
fi
shopt -s nullglob
current_sec=$(date +%s)
threshold_sec=$(( THRESH_DAYS * 86400 ))
found_alert=false
# Gather files from all keyring dirs
key_files=()
for d in "${KEYRING_DIRS[@]}"; do
if [[ -d "$d" ]]; then
for f in "$d"/*.gpg; do
# nullglob ensures non-matching pattern doesn't return literal pattern
if [[ -f "$f" ]]; then
key_files+=("$f")
fi
done
fi
done
shopt -u nullglob
if [[ ${#key_files[@]} -eq 0 ]]; then
printf 'No .gpg key files found in: %s\n' "${KEYRING_DIRS[*]}" >&2
exit 2
fi
for key_file in "${key_files[@]}"; do
# parse pub lines from gpg output
while IFS= read -r line; do
if [[ $line == pub* ]]; then
expiry_date=''
# Try to capture explicit "expires: YYYY-MM-DD" patterns first
if [[ $line =~ [Ee]xpires[[:space:]]*:[[:space:]]*([0-9]{4}-[0-9]{2}-[0-9]{2}) ]]; then
expiry_date="${BASH_REMATCH[1]}"
else
# Try to extract any YYYY-MM-DD token on the line if it contains 'expire' text
if [[ $line =~ ([Ee]xpire|[Ee]xpires|[Ee]xpired) ]] && grep -qE '[0-9]{4}-[0-9]{2}-[0-9]{2}' <<< "$line"; then
expiry_date=$(grep -oE '[0-9]{4}-[0-9]{2}-[0-9]{2}' <<< "$line" | tail -n1)
fi
fi
if [[ -z $expiry_date ]]; then
continue
fi
target_sec=$(date -d "$expiry_date" +%s 2>/dev/null || true)
if [[ -z $target_sec ]]; then
normalized=$(sed 's/[^0-9]//g' <<< "$expiry_date")
if [[ $normalized =~ ^([0-9]{4})([0-9]{2})([0-9]{2})$ ]]; then
normalized="${BASH_REMATCH[1]}-${BASH_REMATCH[2]}-${BASH_REMATCH[3]}"
target_sec=$(date -d "$normalized" +%s 2>/dev/null || true)
fi
fi
if [[ -z $target_sec ]]; then
printf 'Could not parse expiry date for %s: %s\n' "$key_file" "$expiry_date" >&2
continue
fi
diff_sec=$(( target_sec - current_sec ))
if (( diff_sec >= 0 && diff_sec < threshold_sec )); then
days_left=$(( (diff_sec + 86399) / 86400 ))
printf '%s: %sexpires%s %s (%s%d day(s)%s left)\n' "$key_file" "$GREEN" "$NC" "$expiry_date" "$GREEN" "$days_left" "$NC"
found_alert=true
elif (( diff_sec < 0 )); then
days_overdue=$(( (-diff_sec + 86399) / 86400 ))
printf '%s: %sexpired%s %s (%s%d day(s)%s overdue)\n' "$key_file" "$RED" "$NC" "$expiry_date" "$RED" "$days_overdue" "$NC"
found_alert=true
fi
fi
done < <(LANG=C gpg --show-key "$key_file" 2>/dev/null || true)
done
if $found_alert; then
exit 1
else
exit 0
fi