summaryrefslogtreecommitdiff
path: root/bin/generate-key-graph
blob: 3c5063f1070a4ba42dfeffedd102b8c45890cb4a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#!/bin/bash

# shellcheck source=../lib/load-configuration
. "${0%/*}/../lib/load-configuration"

tmp_dir=$(mktemp -d 'tmp.generate-key-graph.XXXXXXXXXX')
trap 'rm -rf --one-file-system "${tmp_dir}"' EXIT

# shellcheck disable=SC2016
{
  printf 'SELECT DISTINCT '
  printf 'REPLACE(TO_BASE64(`gpg_keys`.`public_key`),"\\n",""),'
  printf '`gpg_keys`.`fingerprint`'
  printf ' FROM `gpg_keys`'
  mysql_join_gpg_keys_binary_packages
  mysql_join_binary_packages_binary_packages_in_repositories
  mysql_join_binary_packages_in_repositories_repositories
  printf ' AND `repositories`.`is_on_master_mirror`;\n'
} \
| mysql_run_query \
> "${tmp_dir}/packager-keys"

# shellcheck disable=SC2046
${master_mirror_rsync_command} $(
  ls_master_mirror pool \
  | grep '^archlinux32-keyring\(-transition\)\?\(-[^-]\+\)\{3\}\.pkg\.tar\.zst$' \
  | sed 's#^#'"${master_mirror_rsync_directory}"'/pool/#'
) "${tmp_dir}/"

GPG='gpg --quiet --batch --no-tty --no-permission-warning --homedir='"${tmp_dir}"'/gnupg'

get_user_info() {
  ${GPG} --with-colons --list-keys "0x${fp}" \
  | grep -m1 '^uid:' \
  | cut -d: -f 10 \
  | sed 's/^.*<\(\S\+\)>$/\1/'
}

expiration_color() {
  local expiration
  expiration=$(
    ${GPG} --with-colons --list-keys "0x${fp}" \
    | grep -m1 '^pub:' \
    | cut -d: -f 7
  )
  if [ -z "${expiration}" ]; then
    printf '#000000'
    return
  fi
  expiration=$((
    (expiration - $(date +%s))/60/60/24
  ))
  if [ ${expiration} -gt 100 ]; then
    printf '#000000'
  elif [ ${expiration} -gt 50 ]; then
    printf '#808000'
  elif [ ${expiration} -gt 25 ]; then
    printf '#ffff00'
  elif [ ${expiration} -gt 0 ]; then
    printf '#ff8000'
  else
    printf '#ff0000'
  fi
}

{
  printf 'digraph "key-graph" {\n'
  printf 'rankdir=LR;\n'

  mkdir "${tmp_dir}/gnupg"
  while read -r s _; do
    printf '%s\n' "${s}" \
    | base64 -w0 -d
  done \
  <"${tmp_dir}/packager-keys" \
  | ${GPG} --import
  while read -r _ fp; do
    printf '"%s"[label="packager key %s\\n%s",color="#0000ff",fontcolor="%s"];\n' \
      "${fp}" \
      "${fp: -8}" \
      "$(get_user_info "${fp}")" \
      "$(expiration_color "${fp}")"
  done \
  <"${tmp_dir}/packager-keys"

  rm -rf --one-file-system "${tmp_dir}/gnupg"

  find "${tmp_dir}" -type f -name 'archlinux32-*.pkg.tar*' \
  | while read -r keyring_package; do
    mkdir "${tmp_dir}/gnupg"

    kpf="${keyring_package##*/}"
    kpf="${kpf%.pkg.tar*}"

    {
      while read -r s _; do
        printf '%s\n' "${s}" \
        | base64 -w0 -d
      done \
      <"${tmp_dir}/packager-keys"
      bsdtar -Oxf "${keyring_package}" usr/share/pacman/keyrings/archlinux32.gpg
    } \
    | ${GPG} --import

    all_keys=$(
      cut -f2 \
      < "${tmp_dir}/packager-keys"
      bsdtar -Oxf "${keyring_package}" usr/share/pacman/keyrings/archlinux32-trusted \
      | cut -d: -f1
    )

    printf 'subgraph "cluster %s" {\n' \
      "${kpf}"
    printf 'label="%s";\n' \
      "${kpf}"

    bsdtar -Oxf "${keyring_package}" usr/share/pacman/keyrings/archlinux32-trusted \
    | while IFS=: read -r fp _; do
      printf '"%s-%s"[label="master key %s\\n%s",color="#00ff00",fontcolor="%s"];\n' \
        "${kpf}" \
        "${fp}" \
        "${fp: -8}" \
        "$(get_user_info "${fp}")" \
        "$(expiration_color "${fp}")"
    done

    printf '}\n'

    for key_id in ${all_keys}; do
      ${GPG} --list-sigs --with-colons "0x${key_id}" \
      | grep -wF "${all_keys}" \
      | grep '^sig:' \
      | cut -d : -f 13 \
      | grep -vxF "${key_id}" \
      | while read -r sig; do
        if cut -f2 \
        < "${tmp_dir}/packager-keys" \
        | grep -qxF "${sig}"; then
          print_sig="${sig}"
        else
          print_sig="${kpf}-${sig}"
        fi
        if cut -f2 \
        < "${tmp_dir}/packager-keys" \
        | grep -qxF "${key_id}"; then
          print_key="${key_id}"
        else
          print_key="${kpf}-${key_id}"
        fi
        printf '"%s" -> "%s";\n' \
          "${print_sig}" \
          "${print_key}"
      done
    done \
    | sort -u

    rm -rf --one-file-system "${tmp_dir}/gnupg"
  done
  printf '}\n'
} \
| dot -Tpng \
>"${webserver_directory}/key-graph.png"