Skip to content

Instantly share code, notes, and snippets.

@robcowie
Last active June 9, 2024 15:39
Show Gist options
  • Save robcowie/b8fdaa69072a521b78090965149327e3 to your computer and use it in GitHub Desktop.
Save robcowie/b8fdaa69072a521b78090965149327e3 to your computer and use it in GitHub Desktop.
Create IoT Edge device certificates

Device Certificate Creation

Procedure

  1. Download create_device_certs.sh and openssl_root_ca.cnf into the same directory

  2. Create a dir ROOTS and download the required root certificates into it. Search for IoT CA Certificates in 1Password and download all 3 attached files.

  3. Run the script with the device name for example sh create_device_certs.sh mssdaq01

  4. 4 files are needed on the device. Find them in certificates/deviceid-certificates/to-device. For example

    certificates/mssdaq01-certificates
    ├── device-ca-full-chain.cert.pem
    ├── device-ca.cert.pem
    ├── device-ca.csr
    ├── device-full-chain.cert.pem
    ├── device.cert.pem
    ├── device.csr
    ├── device.key.pem
    └── to-device
        ├── ca.crt
        ├── device-ca.crt
        ├── device.crt
        └── device.key
  5. Copy to the device with rsync, for example rsync -e "ssh -p 64637" -r certificates/mssdaq01-certificates/to-device/ r7e@localhost:/home/r7e/certs

Problems with OpenSSL 3.2.0

Creation of the CA certificate signing request fails with the follwing error

80A027F501000000:error:11000079:X509 V3 routines:v2i_AUTHORITY_KEYID:no issuer certificate:crypto/x509/v3_akid.c:156:
80A027F501000000:error:11000080:X509 V3 routines:X509V3_EXT_nconf_int:error in extension:crypto/x509/v3_conf.c:48:section=v3_intermediate_ca, name=authorityKeyIdentifier, value=keyid:always,issuer:always

This seems to be because we're doing something wrong. It is the authorityKeyIdentifier = keyid:always,issuer:always in the .cfg that now fails from this version of OpenSSL. Commenting it out in the config file solves the problem

See https://github.com/openssl/openssl/blob/openssl-3.2.0/CHANGES.md (search for authorityKeyIdentifier = none)

#!/usr/bin/env bash
set -e
# Setup
DEVICE_ID="$1"
CONFIG_FILE="openssl_root_ca.cnf"
# Existing Intermediate CA Certificate & Key
# CA_INTERMEDIATE_CERT="ROOTS/Recycleye_IOT_Intermediate_CA.crt.pem"
CA_INTERMEDIATE_CERT_FULL="ROOTS/Recycleye_IOT_Intermediate_CA_full_chain.crt.pem"
CA_INTERMEDIATE_KEY="ROOTS/Recycleye_IOT_Intermediate_CA.key.pem"
CA_ROOT_CERT="ROOTS/Recycleye_IOT_CA.pem"
OUTDIR="certificates/${DEVICE_ID}-certificates"
CONFIG_FILE_TEMP="${OUTDIR}/${CONFIG_FILE}.tmp"
mkdir -p "$OUTDIR"
# Add the device id as commonName to the config file
# Should be able to use CN = $ENV::DEVICE_ID in the conf file but it doesn't work
sed "s/DEVICE_ID/${DEVICE_ID}/g" ${CONFIG_FILE} >"${CONFIG_FILE_TEMP}"
# 1. Generate the device private key
echo "--> Generate device private key"
openssl genrsa -out "${OUTDIR}/device.key.pem" 4096 &>/dev/null
chmod 444 "${OUTDIR}/device.key.pem"
echo " ... ${OUTDIR}/device.key.pem"
# 2. Generate a certificate signing request for the device identity certificate
echo "--> Generate certificate signing request for device identity certificate"
openssl req -new \
-config "${CONFIG_FILE_TEMP}" \
-key "${OUTDIR}/device.key.pem" \
-out "${OUTDIR}/device.csr" &>/dev/null
echo " ... ${OUTDIR}/device.csr"
# view the CSR with
# openssl req -noout -text -in "${OUTDIR}/device.csr"
# 3. Create the device certificate using the CSR
echo "--> Generate the device identity certificate using our intermediate ca cert"
openssl x509 -req \
-days 3650 \
-in "${OUTDIR}/device.csr" \
-CA "${CA_INTERMEDIATE_CERT_FULL}" \
-CAkey "${CA_INTERMEDIATE_KEY}" \
-CAcreateserial \
-out "${OUTDIR}/device.cert.pem" \
-extfile "${CONFIG_FILE_TEMP}" \
-extensions user_crt &>/dev/null
echo " ... ${OUTDIR}/device.cert.pem"
# Look at a certificate Subject (in sensible format) with
# openssl x509 -in "${OUTDIR}/device.cert.pem" -noout -subject -nameopt oneline,-esc_msb
# 4. Create full chain device certificate
echo "--> Generate a full chain device certificate (with ca intermediate full chain cert)"
cat "${OUTDIR}/device.cert.pem" "${CA_INTERMEDIATE_CERT_FULL}" >"${OUTDIR}/device-full-chain.cert.pem"
echo " ... ${OUTDIR}/device-full-chain.cert.pem"
# 5. Create device CA certificate CSR
echo "--> Generate certificate signing request for device ca certificate"
openssl req -new \
-config "${CONFIG_FILE_TEMP}" \
-key "${OUTDIR}/device.key.pem" \
-extensions v3_intermediate_ca \
-out "${OUTDIR}/device-ca.csr" &>/dev/null
echo " ... ${OUTDIR}/device-ca.csr"
# 6. Create device CA certifiate
echo "--> Generate the device ca certificate using our intermediate ca cert"
openssl x509 -req \
-days 3650 \
-in "${OUTDIR}/device-ca.csr" \
-CA "${CA_INTERMEDIATE_CERT_FULL}" \
-CAkey "${CA_INTERMEDIATE_KEY}" \
-CAcreateserial \
-out "${OUTDIR}/device-ca.cert.pem" \
-extfile "${CONFIG_FILE_TEMP}" \
-extensions v3_intermediate_ca &>/dev/null
echo " ... ${OUTDIR}/device-ca.cert.pem"
# 7. Create full chain device CA certificate
echo "--> Generate a full chain device ca certificate (with ca intermediate full chain cert)"
cat "${OUTDIR}/device-ca.cert.pem" "${CA_INTERMEDIATE_CERT_FULL}" >"${OUTDIR}/device-ca-full-chain.cert.pem"
echo " ... ${OUTDIR}/device-ca-full-chain.cert.pem"
# 8. Copy & rename certs for device
echo "--> Copy & rename certificates to copy to device"
mkdir -p "$OUTDIR/to-device"
cp "${OUTDIR}/device-ca-full-chain.cert.pem" "$OUTDIR/to-device/device-ca.crt"
cp "${OUTDIR}/device-full-chain.cert.pem" "${OUTDIR}/to-device/device.crt"
cp "${OUTDIR}/device.key.pem" "${OUTDIR}/to-device/device.key"
cp "${CA_ROOT_CERT}" "${OUTDIR}/to-device/ca.crt"
echo " ... ${OUTDIR}/to-device"
rm -f "${CONFIG_FILE_TEMP}"
[req]
default_bits = 4096
distinguished_name = req_distinguished_name
string_mask = utf8only
default_md = sha256
prompt = no
# add extentions to CA certificates
#x509_extensions = v3_ca
# add extensions to certificate signing requests (CSRs)
x509_extensions = user_crt
req_extensions = v3_req
[req_distinguished_name]
# See https://en.wikipedia.org/wiki/Certificate_signing_request
C = UK
O = Recycleye
#CN = ${ENV::DEVICE_ID}
CN = DEVICE_ID
emailAddress = security@recycleye.com
# [v3_ca]
# # x509v3 extensions for CA certificates
# subjectKeyIdentifier = hash
# authorityKeyIdentifier = keyid:always,issuer
# basicConstraints = critical,CA:true
# nsComment = "OpenSSL Generated Certificate"
[v3_req]
# x509v3 extensions for CA certificates
basicConstraints = CA:FALSE
extendedKeyUsage = clientAuth, emailProtection
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
[user_crt]
# Extensions for client (device) certificates
subjectKeyIdentifier = hash
basicConstraints = CA:FALSE
extendedKeyUsage = clientAuth, emailProtection
nsCertType = client, email
authorityKeyIdentifier = keyid:always,issuer:always
nsComment = "OpenSSL Generated Client Certificate"
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
[v3_intermediate_ca]
# Extensions for a typical intermediate CA
basicConstraints = critical, CA:true
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment