#!/bin/bash -ue
# Copyright (c) Meta Platforms, Inc. and affiliates.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
CERT_LIFETIME_DAYS=${CERT_LIFETIME_DAYS:-36500}
extensions() {
cat << EOF
[ca]
basicConstraints = critical, CA:TRUE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always, issuer:always
keyUsage = critical, cRLSign, digitalSignature, keyCertSign
[client]
basicConstraints = critical, CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = critical, clientAuth
[server]
basicConstraints = critical, CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment, keyAgreement
extendedKeyUsage = critical, serverAuth
subjectAltName = IP:127.0.0.1,IP:::1
[client_and_server]
basicConstraints = critical, CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment, keyAgreement
extendedKeyUsage = critical, serverAuth, clientAuth
subjectAltName = IP:127.0.0.1,IP:::1
EOF
}
die() {
echo "$@" >&2
exit 1
}
generate_key() {
keytype="$1"
modulus_bits="$2"
outfile="$3"
[ "$keytype" != "rsa" ] && die "unsupported key type"
openssl genrsa -out "$outfile" "$modulus_bits" 2>/dev/null
}
mkcsr() {
local key="$1"
local name="$2"
local output="$3"
openssl req -new \
-sha256 \
-key "$key" \
-keyform PEM \
-subj "/CN=$name/" \
-outform PEM \
-out "$output" \
}
selfsign() {
local incsr="$1"
local inkey="$2"
local outfile="$3"
openssl x509 \
-req \
-set_serial 1 \
-signkey "$inkey" \
-inform PEM \
-in "$incsr" \
-outform PEM \
-out "$outfile" \
-days "$CERT_LIFETIME_DAYS" \
-extfile <(extensions) \
-extensions "ca" \
}
sign() {
csr="$1"
cacert="$2"
cakey="$3"
serial="$4"
extensions="$5"
outfile="$6"
openssl x509 \
-req \
-set_serial "$serial" \
-CA "$cacert" \
-CAkey "$cakey" \
-inform PEM \
-in "$csr" \
-outform PEM \
-out "$outfile" \
-days "$CERT_LIFETIME_DAYS" \
-extfile <(extensions) \
-extensions "$extensions" \
}
# Client CA
generate_key rsa 2048 client_ca_key.pem
mkcsr client_ca_key.pem "Asox Certification Authority" client_ca.csr.pem
selfsign client_ca.csr.pem client_ca_key.pem client_ca_cert.pem
# Client Intermediate CA
generate_key rsa 2048 client_intermediate_ca_key.pem
mkcsr client_intermediate_ca_key.pem "Intermediate CA" client_intermediate_ca.csr.pem
sign client_intermediate_ca.csr.pem client_ca_cert.pem client_ca_key.pem 2 ca client_intermediate_ca.pem
# Directly signed client cert (client_key.pem)
generate_key rsa 2048 client_key.pem
mkcsr client_key.pem "testuser1" client.csr.pem
sign client.csr.pem client_ca_cert.pem client_ca_key.pem 100 client client_cert.pem
# Client signed by an intermediate
generate_key rsa 2048 clienti_key.pem
mkcsr clienti_key.pem "Leaf Certificate" clienti.csr.pem
sign clienti.csr.pem client_intermediate_ca.pem client_intermediate_ca_key.pem 200 client clienti_cert.pem
cat clienti_cert.pem client_intermediate_ca.pem > client_chain.pem
# Server CA "Thrift Certificate Authority"
generate_key rsa 2048 ca-key.pem
mkcsr ca-key.pem "Thrift Certificate Authority" ca.csr.pem
selfsign ca.csr.pem ca-key.pem ca-cert.pem
# Server cert "Asox Company"
generate_key rsa 2048 tests-key.pem
mkcsr tests-key.pem "Asox Company" tests.csr.pem
sign tests.csr.pem ca-cert.pem ca-key.pem 300 client_and_server tests-cert.pem
# Remove all of the CSRs but leave the keys in case you need to regenerate a
# different cert with the same key.
rm ./*.csr.pem