github.com/nats-io/nats-server/v2@v2.11.0-preview.2/test/configs/certs/regenerate_rdns_svid.sh (about)

     1  #!/usr/bin/env bash
     2  set -euo pipefail
     3  #
     4  # regenerate_rnds_svid: just remake the certs in the rdns & svid dirs.
     5  #
     6  # We're getting the hard requirements down in scripts, can integrate all into
     7  # one all-singing all-dancing script later, so that anyone can regenerate
     8  # without having to read test source code.
     9  #
    10  
    11  progname="$(basename "$0" .sh)"
    12  note() { printf >&2 '%s: %s\n' "$progname" "$*"; }
    13  warn() { note "$@"; }
    14  die() { warn "$@"; exit 1; }
    15  
    16  readonly CERT_SUBDIR='test/configs/certs'
    17  readonly RDNS_SUBDIR='rdns'
    18  readonly SVID_SUBDIR='svid'
    19  
    20  # WARNING:
    21  # This data is hard-coded into tests such as TestTLSClientAuthWithRDNSequence
    22  # so do not "fix" it without editing the tests too!
    23  readonly COMMON_SUB_COUNTRY=US
    24  readonly COMMON_SUB_STATE=CA
    25  readonly COMMON_SUB_LOCALITY='Los Angeles'
    26  readonly COMMON_SUB_ORG=NATS
    27  readonly COMMON_SUB_ORGUNIT=NATS
    28  readonly COMMON_SUBJECT_OOU="/C=$COMMON_SUB_COUNTRY/ST=$COMMON_SUB_STATE/L=$COMMON_SUB_LOCALITY/O=$COMMON_SUB_ORG/OU=$COMMON_SUB_ORGUNIT"
    29  readonly COMMON_SUBJECT_OUO="/C=$COMMON_SUB_COUNTRY/ST=$COMMON_SUB_STATE/L=$COMMON_SUB_LOCALITY/OU=$COMMON_SUB_ORGUNIT/O=$COMMON_SUB_ORG"
    30  readonly RDNS_COMMON_SAN='subjectAltName=DNS:localhost,DNS:example.com,DNS:www.example.com'
    31  
    32  readonly CA_KEYFILE=ca.key CA_CERTFILE=ca.pem CA_NAME='NATS CA' CA_SERIAL_FILE='ca.srl'
    33  readonly RSA_SIZE=2048
    34  readonly DIGEST_ALG=sha256
    35  readonly CERT_DURATION=$((2 * 365))
    36  
    37  REPO_TOP="$(git rev-parse --show-toplevel)"
    38  CERT_ABSOLUTE_DIR="$REPO_TOP/$CERT_SUBDIR"
    39  readonly REPO_TOP CERT_ABSOLUTE_DIR
    40  
    41  okay=true
    42  for cmd in openssl ; do
    43    if command -v "$cmd" >/dev/null 2>&1; then
    44      continue
    45    fi
    46    okay=false
    47    warn "missing command: $cmd"
    48  done
    49  $okay || die "missing necessary commands"
    50  
    51  make_keyfile() {
    52    local keyfile="${1:?need a keyfile to create}"
    53    (umask 077; openssl genrsa "$RSA_SIZE" > "$keyfile")
    54  }
    55  
    56  ensure_keyfile() {
    57    local keyfile="${1:?need a keyfile to create}"
    58    local description="${2:?need a description}"
    59    if [ -f "$keyfile" ]; then
    60      note "reusing EXISTING $description file: $keyfile"
    61      return 0
    62    fi
    63    note "creating NEW $description file: $keyfile"
    64    make_keyfile "$keyfile"
    65  }
    66  
    67  o_req_newkey() { openssl req -newkey "rsa:$RSA_SIZE" -nodes "$@"; }
    68  
    69  o_x509_casign() {
    70    local extfile_contents="$1"
    71    shift
    72    openssl x509 -req -days "$CERT_DURATION" \
    73      -CA "$CA_CERTFILE" -CAkey "$CA_KEYFILE" -CAcreateserial \
    74      -sha256 \
    75      -extfile <(printf '%s\n' "$extfile_contents") \
    76      "$@"
    77  }
    78  
    79  o_new_cafile() {
    80    local keyfile="$1" cacertfile="$2"
    81    shift 2
    82    openssl req -x509 -new -key "$CA_KEYFILE" -out "$CA_CERTFILE" -outform pem \
    83      -days "$CERT_DURATION" -subj "/CN=$CA_NAME" \
    84      "$@"
    85  # We want these:
    86  #   -addext subjectKeyIdentifier=hash \
    87  #   -addext authorityKeyIdentifier=keyid:always,issuer \
    88  #   -addext basicConstraints=critical,CA:true \
    89  # but even without an extensions section, those seem to have been included anyway,
    90  # resulting in a doubling when I created them, and Go cert parsing did not like
    91  # the doubled X509v3 extensions data, leading to a panic.
    92  # So, removed.
    93  }
    94  
    95  # ########################################################################
    96  # RDNS
    97  
    98  note "Working on rdns files"
    99  cd "$CERT_ABSOLUTE_DIR/$RDNS_SUBDIR" || die "unable to chdir($CERT_ABSOLUTE_DIR/$RDNS_SUBDIR)"
   100  
   101  note "creating: CA"
   102  # This one is kept in-git, so we don't force-recreate.
   103  # TBD: should we delete, as we do in the parent dir?
   104  ensure_keyfile "$CA_KEYFILE" "rdns CA key"
   105  o_new_cafile "$CA_KEYFILE" "$CA_CERTFILE"
   106  
   107  make_rdns_client_pair() {
   108    local client_id="$1"
   109    local subject="$2"
   110    shift 2
   111    local prefix="client-$client_id"
   112    note "creating: $prefix"
   113    rm -fv -- "$prefix.key" "$prefix.csr" "$prefix.pem"
   114    # TBD: preserve the .key if it already exists?
   115    # For now, just using the same ultimate command as was documented in the tls_test.go comments,
   116    # so that we minimize moving parts to debug.  Key preservation is a future optimization.
   117    # The "$@" goes into the req invocation to let us specify -multivalue-rdn
   118    o_req_newkey -keyout "$prefix.key" -out "$prefix.csr" "$@" -subj "$subject" -addext extendedKeyUsage=clientAuth
   119    o_x509_casign "$RDNS_COMMON_SAN" -in "$prefix.csr" -out "$prefix.pem"
   120    rm -v -- "$prefix.csr"
   121    echo >&2
   122  }
   123  
   124  make_svid_rsa_pair() {
   125    local prefix="$1"
   126    local subject="$2"
   127    local san_addition="$3"
   128    shift 3
   129    note "creating: $prefix"
   130    rm -fv -- "$prefix.key" "$prefix.csr" "$prefix.pem"
   131    # TBD: preserve the .key if it already exists?
   132    # For now, just using the same ultimate command as was documented in the tls_test.go comments,
   133    # so that we minimize moving parts to debug.  Key preservation is a future optimization.
   134    o_req_newkey -keyout "$prefix.key" -out "$prefix.csr" -subj "$subject" -addext extendedKeyUsage=clientAuth
   135    o_x509_casign "$RDNS_COMMON_SAN${san_addition:+,}${san_addition:-}" -in "$prefix.csr" -out "$prefix.pem"
   136    rm -v -- "$prefix.csr"
   137    echo >&2
   138  }
   139  
   140  # KEEP DN STRINGS HERE MATCHING THOSE IN tls_test.go SO THAT IT's COPY/PASTE!
   141  
   142  # C = US, ST = CA, L = Los Angeles, O = NATS, OU = NATS, CN = localhost, DC = foo1, DC = foo2
   143  make_rdns_client_pair a "$COMMON_SUBJECT_OOU/CN=localhost/DC=foo1/DC=foo2"
   144  
   145  # C = US, ST = California, L = Los Angeles, O = NATS, OU = NATS, CN = localhost
   146  make_rdns_client_pair b "$COMMON_SUBJECT_OOU/CN=localhost"
   147  
   148  # C = US, ST = CA, L = Los Angeles, O = NATS, OU = NATS, CN = localhost, DC = foo3, DC = foo4
   149  make_rdns_client_pair c "$COMMON_SUBJECT_OOU/CN=localhost/DC=foo3/DC=foo4"
   150  
   151  # C = US, ST = CA, L = Los Angeles, OU = NATS, O = NATS, CN = *.example.com, DC = example, DC = com
   152  make_rdns_client_pair d "$COMMON_SUBJECT_OUO/CN=*.example.com/DC=example/DC=com"
   153  
   154  # OpenSSL: -subj "/CN=John Doe/CN=123456/CN=jdoe/OU=Users/OU=Organic Units/DC=acme/DC=com"
   155  make_rdns_client_pair e "/CN=John Doe/CN=123456/CN=jdoe/OU=Users/OU=Organic Units/DC=acme/DC=com"
   156  
   157  # OpenSSL: -subj "/DC=org/DC=OpenSSL/DC=DEV+O=users/CN=John Doe"
   158  # WITH -multivalue-rdn for the -req
   159  make_rdns_client_pair f "/DC=org/DC=OpenSSL/DC=DEV+O=users/CN=John Doe" -multivalue-rdn
   160  
   161  note "creating: server"
   162  rm -fv -- "server.key" "server.csr" "server.pem"
   163  o_req_newkey -keyout "server.key" -out "server.csr" -subj "/CN=localhost"
   164  o_x509_casign "$RDNS_COMMON_SAN" -in "server.csr" -out "server.pem"
   165  rm -v -- "server.csr"
   166  echo >&2
   167  
   168  rm -rfv "$CA_SERIAL_FILE"
   169  
   170  # ########################################################################
   171  # SVID
   172  
   173  note "Working on svid files"
   174  cd "$CERT_ABSOLUTE_DIR/$SVID_SUBDIR" || die "unable to chdir($CERT_ABSOLUTE_DIR/$SVID_SUBDIR)"
   175  
   176  note "creating: CA"
   177  ensure_keyfile "$CA_KEYFILE" "svid CA key"
   178  o_new_cafile "$CA_KEYFILE" "$CA_CERTFILE"
   179  
   180  make_svid_rsa_pair client-a "$COMMON_SUBJECT_OOU/CN=localhost/DC=foo1/DC=foo2" 'URI:spiffe://localhost/my-nats-service/user-a'
   181  
   182  make_svid_rsa_pair client-b "/C=US/O=SPIRE" 'URI:spiffe://localhost/my-nats-service/user-b'
   183  
   184  make_svid_rsa_pair server "/CN=localhost" ''
   185  
   186  rm -rfv "$CA_SERIAL_FILE"
   187  
   188  # FIXME: svid-user-a and svid-user-b are ECC certs, but not expiring at the
   189  # same time as the rest and with differing requirements, so not coding that up
   190  # now.