Zack Williams | ec61381 | 2020-11-09 15:49:29 -0700 | [diff] [blame^] | 1 | # onfca Makefile |
| 2 | # |
| 3 | # SPDX-FileCopyrightText: © 2022 Open Networking Foundation <support@opennetworking.org> |
| 4 | # SPDX-License-Identifier: Apache-2.0 |
| 5 | |
| 6 | # openssl onfiguration is also given in pki.cnf |
| 7 | # |
| 8 | # NOTE: This makefile makes heavy use of Automatic Variables |
| 9 | # https://www.gnu.org/software/make/manual/html_node/Automatic-Variables.html |
| 10 | |
| 11 | SHELL = bash -eu -o pipefail |
| 12 | |
| 13 | # see bottom for help generation |
| 14 | .DEFAULT_GOAL := help |
| 15 | .PHONY: test license help |
| 16 | |
| 17 | # common parameters for all options |
| 18 | KEY_SIZE ?= 2048 |
| 19 | OPENSSL_CNF ?= pki.cnf |
| 20 | |
| 21 | # base dir |
| 22 | BASE_DIR ?= onf_pki |
| 23 | |
| 24 | # default CA to use when verifying leaf certs, by default the IM CA |
| 25 | DEFAULT_CA ?= im_ca |
| 26 | |
| 27 | # root CA |
| 28 | ROOT_CA_NAME ?= root_ca |
| 29 | ROOT_CA_PASSPHRASE ?= "TestingRootCAPassPhrase" |
| 30 | ROOT_CA_SUBJECT ?= /C=US/ST=California/L=Menlo Park/O=ONF/OU=Infra/CN=ONF Test Root CA |
| 31 | |
| 32 | # intermediate CA |
| 33 | IM_CA_NAME ?= im_ca |
| 34 | IM_CA_PASSPHRASE ?= "TestingIMCAPassPhrase" |
| 35 | IM_CA_SUBJECT ?= /C=US/ST=California/L=Menlo Park/O=ONF/OU=Infra/CN=ONF Test IM CA |
| 36 | IM_EXPIRATION_DAYS ?= 1095 |
| 37 | IM_REVOKE_REASON ?= CACompromise |
| 38 | |
| 39 | # leaf certs |
| 40 | LEAF_EXPIRATION_DAYS ?= 730 |
| 41 | LEAF_PURPOSE ?= server_cert_ext # alternatively, use client_cert_ext |
| 42 | LEAF_SUBJECT_PARTIAL ?= /C=US/ST=California/L=Menlo Park/O=ONF/OU=Infra/CN= |
| 43 | LEAF_KEYPAIR ?= core |
| 44 | LEAF_SAN ?= DNS:core.example.com,DNS:core.example.net |
| 45 | LEAF_REVOKE_REASON ?= keyCompromise |
| 46 | |
| 47 | # utility/validation targets |
| 48 | valid_server: ## Check Server Cert validity (set LEAF_KEYPAIR, DEFAULT_CA) |
| 49 | openssl verify -verbose -x509_strict -show_chain \ |
| 50 | -purpose sslserver \ |
| 51 | -CAfile $(BASE_DIR)/$(DEFAULT_CA)/chain.pem \ |
| 52 | -CRLfile $(BASE_DIR)/$(DEFAULT_CA)/ca.crl -crl_check \ |
| 53 | $(BASE_DIR)/certout/$(LEAF_KEYPAIR).pem |
| 54 | |
| 55 | valid_client: ## Check Client Cert validity (set LEAF_KEYPAIR, DEFAULT_CA) |
| 56 | openssl verify -verbose -x509_strict -show_chain \ |
| 57 | -purpose sslclient \ |
| 58 | -CAfile $(BASE_DIR)/$(DEFAULT_CA)/chain.pem \ |
| 59 | -CRLfile $(BASE_DIR)/$(DEFAULT_CA)/ca.crl -crl_check \ |
| 60 | $(BASE_DIR)/certout/$(LEAF_KEYPAIR).pem |
| 61 | |
| 62 | valid_im: ## Check IM CA validity (set IM_CA_NAME, ROOT_CA_NAME) |
| 63 | openssl verify -verbose -x509_strict -purpose any \ |
| 64 | -CAfile $(BASE_DIR)/$(ROOT_CA_NAME)/ca.pem \ |
| 65 | -CRLfile $(BASE_DIR)/$(ROOT_CA_NAME)/ca.crl -crl_check_all \ |
| 66 | $(BASE_DIR)/$(IM_CA_NAME)/ca.pem |
| 67 | |
| 68 | printca: $(BASE_DIR)/$(DEFAULT_CA)/ca.pem ## Print CA Public Key (PEM) for DEFAULT_CA |
| 69 | openssl x509 -in $< -text -noout |
| 70 | |
| 71 | printcrl: $(BASE_DIR)/$(DEFAULT_CA)/ca.crl ## Print CRL (Revoke List) for DEFAULT_CA |
| 72 | openssl crl -in $< -text -noout |
| 73 | |
| 74 | printkey: ## Print KEY (Private Key) for LEAF_KEYPAIR |
| 75 | openssl rsa -in $(BASE_DIR)/certout/$(LEAF_KEYPAIR).key -text -noout -check |
| 76 | |
| 77 | printcsr: ## Print CSR (Sign Request) for LEAF_KEYPAIR |
| 78 | openssl req -in $(BASE_DIR)/certout/$(LEAF_KEYPAIR).csr -text -noout -verify |
| 79 | |
| 80 | printpem: ## Print PEM (Public Key) for LEAF_KEYPAIR |
| 81 | openssl x509 -in $(BASE_DIR)/certout/$(LEAF_KEYPAIR).pem -text -noout |
| 82 | |
| 83 | revoke_leaf: ## Revoke Leaf Cert (set IM_CA_NAME, LEAF_KEYPAIR, LEAF_REVOKE_REASON) |
| 84 | BASE_DIR=$(BASE_DIR) CA_NAME=$(IM_CA_NAME) openssl ca \ |
| 85 | -config $(OPENSSL_CNF) \ |
| 86 | -passin file:$(BASE_DIR)/$(IM_CA_NAME)/private/ca_passphrase \ |
| 87 | -revoke $(BASE_DIR)/certout/$(LEAF_KEYPAIR).pem \ |
| 88 | -crl_reason $(LEAF_REVOKE_REASON) |
| 89 | BASE_DIR=$(BASE_DIR) CA_NAME=$(IM_CA_NAME) openssl ca -gencrl \ |
| 90 | -config $(OPENSSL_CNF) \ |
| 91 | -passin file:$(BASE_DIR)/$(IM_CA_NAME)/private/ca_passphrase \ |
| 92 | -out $(BASE_DIR)/$(IM_CA_NAME)/ca.crl |
| 93 | |
| 94 | revoke_im: ## Revoke Intermediate CA Cert (set IM_CA_NAME, IM_REVOKE_REASON, ROOT_CA_NAME) |
| 95 | BASE_DIR=$(BASE_DIR) CA_NAME=$(ROOT_CA_NAME) openssl ca \ |
| 96 | -config $(OPENSSL_CNF) \ |
| 97 | -passin file:$(BASE_DIR)/$(ROOT_CA_NAME)/private/ca_passphrase \ |
| 98 | -revoke $(BASE_DIR)/$(IM_CA_NAME)/ca.pem \ |
| 99 | -crl_reason $(IM_REVOKE_REASON) |
| 100 | BASE_DIR=$(BASE_DIR) CA_NAME=$(ROOT_CA_NAME) openssl ca -gencrl \ |
| 101 | -config $(OPENSSL_CNF) \ |
| 102 | -passin file:$(BASE_DIR)/$(ROOT_CA_NAME)/private/ca_passphrase \ |
| 103 | -out $(BASE_DIR)/$(ROOT_CA_NAME)/ca.crl |
| 104 | |
| 105 | destroy: ## Delete all certificates and data |
| 106 | rm -rf $(BASE_DIR) |
| 107 | |
| 108 | # don't delete intermediate files |
| 109 | .PRECIOUS: ca_passphrase $(BASE_DIR)/certout/%.csr $(BASE_DIR)/certout/%.key |
| 110 | |
| 111 | # Generic CA directory creation |
| 112 | $(BASE_DIR)/%_ca: |
| 113 | mkdir -p $@/private $@/db $@/crl/db $@/certs |
| 114 | chmod 700 $@/private |
| 115 | touch $@/db/ca.db |
| 116 | printf "unique_subject = no\ncopy_extensions = copy\n" > $@/db/ca.db.attr |
| 117 | echo 01 > $@/db/ca.srl |
| 118 | echo 01 > $@/crl/db/ca.crl.srl |
| 119 | touch $@/index.txt |
| 120 | |
| 121 | # Root CA creation |
| 122 | $(BASE_DIR)/$(ROOT_CA_NAME)/private/ca_passphrase: | $(BASE_DIR)/$(ROOT_CA_NAME) |
| 123 | @echo $(ROOT_CA_PASSPHRASE) > $@ |
| 124 | |
| 125 | $(BASE_DIR)/$(ROOT_CA_NAME)/private/ca_key.pem: | $(BASE_DIR)/$(ROOT_CA_NAME)/private/ca_passphrase |
| 126 | @echo "## Creating root CA private key, $@" |
| 127 | BASE_DIR=$(BASE_DIR) CA_NAME=$(ROOT_CA_NAME) openssl genrsa -aes256 \ |
| 128 | -passout file:$(BASE_DIR)/$(ROOT_CA_NAME)/private/ca_passphrase \ |
| 129 | -out $@ $(KEY_SIZE) |
| 130 | |
| 131 | # validity time on root CA is set in the .cnf file |
| 132 | $(BASE_DIR)/$(ROOT_CA_NAME)/ca.pem: $(BASE_DIR)/$(ROOT_CA_NAME)/private/ca_key.pem |
| 133 | @echo "## Creating self-signed root CA cert: $@" |
| 134 | BASE_DIR=$(BASE_DIR) CA_NAME=$(ROOT_CA_NAME) openssl req -config $(OPENSSL_CNF) \ |
| 135 | -extensions root_ca_ext \ |
| 136 | -new -x509 -sha256 \ |
| 137 | -key $< \ |
| 138 | -passin file:$(BASE_DIR)/$(ROOT_CA_NAME)/private/ca_passphrase \ |
| 139 | -subj "$(ROOT_CA_SUBJECT)" \ |
| 140 | -out $@ |
| 141 | @echo "## Creating root CA revocation list: $(@D)/ca.crl" |
| 142 | BASE_DIR=$(BASE_DIR) CA_NAME=$(ROOT_CA_NAME) openssl ca -gencrl \ |
| 143 | -config $(OPENSSL_CNF) \ |
| 144 | -passin file:$(BASE_DIR)/$(ROOT_CA_NAME)/private/ca_passphrase \ |
| 145 | -out $(@D)/ca.crl |
| 146 | |
| 147 | # Intermediate CA creation |
| 148 | $(BASE_DIR)/$(IM_CA_NAME)/private/ca_passphrase: | $(BASE_DIR)/$(IM_CA_NAME) |
| 149 | @echo $(IM_CA_PASSPHRASE) > $@ |
| 150 | |
| 151 | $(BASE_DIR)/$(IM_CA_NAME)/private/ca_key.pem: $(BASE_DIR)/$(IM_CA_NAME)/private/ca_passphrase |
| 152 | @echo "## Creating intermediate CA private key: $@" |
| 153 | BASE_DIR=$(BASE_DIR) CA_NAME=$(IM_CA_NAME) openssl genrsa -aes256 \ |
| 154 | -passout file:$(@D)/ca_passphrase \ |
| 155 | -out $@ $(KEY_SIZE) |
| 156 | |
| 157 | $(BASE_DIR)/$(IM_CA_NAME)/private/im_ca.csr: $(BASE_DIR)/$(IM_CA_NAME)/private/ca_key.pem |
| 158 | @echo "## Creating intermediate CA signing request $@ from $<" |
| 159 | BASE_DIR=$(BASE_DIR) CA_NAME=$(IM_CA_NAME) openssl req -config $(OPENSSL_CNF) \ |
| 160 | -new -sha256 \ |
| 161 | -key $< \ |
| 162 | -passin file:$(@D)/ca_passphrase \ |
| 163 | -subj "$(IM_CA_SUBJECT)" \ |
| 164 | -out $@ |
| 165 | |
| 166 | $(BASE_DIR)/$(IM_CA_NAME)/ca.pem: $(BASE_DIR)/$(IM_CA_NAME)/private/im_ca.csr | $(BASE_DIR)/$(ROOT_CA_NAME)/ca.pem |
| 167 | @echo "## Signing $< with root CA key to create intermediate CA cert: $@" |
| 168 | BASE_DIR=$(BASE_DIR) CA_NAME=$(ROOT_CA_NAME) openssl ca -config $(OPENSSL_CNF) \ |
| 169 | -extensions im_ca_ext \ |
| 170 | -notext -batch -md sha256 \ |
| 171 | -days $(IM_EXPIRATION_DAYS) \ |
| 172 | -passin file:$(BASE_DIR)/$(ROOT_CA_NAME)/private/ca_passphrase \ |
| 173 | -in $< \ |
| 174 | -out $@ |
| 175 | @echo "## Creating chain with Root CA and IM CA: $@" |
| 176 | cat $@ $(BASE_DIR)/$(ROOT_CA_NAME)/ca.pem > $(@D)/chain.pem |
| 177 | openssl crl2pkcs7 -nocrl -certfile $(@D)/chain.pem | openssl pkcs7 -print_certs -noout |
| 178 | @echo "## Creating IM CA revocation list: $(@D)/ca.crl" |
| 179 | BASE_DIR=$(BASE_DIR) CA_NAME=$(IM_CA_NAME) openssl ca -gencrl \ |
| 180 | -config $(OPENSSL_CNF) \ |
| 181 | -passin file:$(BASE_DIR)/$(IM_CA_NAME)/private/ca_passphrase \ |
| 182 | -out $(@D)/ca.crl |
| 183 | |
| 184 | # Leaf cert creation |
| 185 | $(BASE_DIR)/certout: |
| 186 | mkdir -p $@ |
| 187 | |
| 188 | $(BASE_DIR)/certout/%.key: $(BASE_DIR)/certout |
| 189 | @echo "## Creating leaf private key: $@" |
| 190 | openssl genrsa -out $@ $(KEY_SIZE) |
| 191 | |
| 192 | $(BASE_DIR)/certout/%.csr: $(BASE_DIR)/certout/%.key |
| 193 | @echo "## Creating signing request $@ from $<" |
| 194 | BASE_DIR=$(BASE_DIR) CA_NAME=$(IM_CA_NAME) openssl req -config $(OPENSSL_CNF) \ |
| 195 | -new -sha256 \ |
| 196 | -key $< \ |
| 197 | -subj "$(LEAF_SUBJECT_PARTIAL)$*" \ |
| 198 | -addext "subjectAltName = $(LEAF_SAN)" \ |
| 199 | -out $@ |
| 200 | |
| 201 | $(BASE_DIR)/certout/%.pem: $(BASE_DIR)/certout/%.csr | $(BASE_DIR)/$(IM_CA_NAME)/ca.pem |
| 202 | @echo "## Signing $< with IM CA key to create signed leaf cert: $@" |
| 203 | BASE_DIR=$(BASE_DIR) CA_NAME=$(IM_CA_NAME) openssl ca -config $(OPENSSL_CNF) \ |
| 204 | -extensions $(LEAF_PURPOSE) \ |
| 205 | -policy any_pol \ |
| 206 | -notext -batch -md sha256 \ |
| 207 | -days $(LEAF_EXPIRATION_DAYS) \ |
| 208 | -passin file:$(BASE_DIR)/$(IM_CA_NAME)/private/ca_passphrase \ |
| 209 | -in $< \ |
| 210 | -out $@ |
| 211 | @echo "## Creating bundle with IM CA and Leaf: $(basename $@)_bundle.pem" |
| 212 | cat $@ $(BASE_DIR)/$(IM_CA_NAME)/ca.pem > $(basename $@)_bundle.pem |
| 213 | openssl crl2pkcs7 -nocrl -certfile $(basename $@)_bundle.pem | openssl pkcs7 -print_certs -noout |
| 214 | |
| 215 | # testing and license tasks |
| 216 | test: license |
| 217 | |
| 218 | license: $(VENV_NAME) ## Check license with the reuse tool |
| 219 | reuse --version ;\ |
| 220 | reuse --root . lint |
| 221 | |
| 222 | help: ## Print help for each target |
| 223 | @echo onfca make targets |
| 224 | @echo See README.md for more detailed instructions |
| 225 | @echo |
| 226 | @grep '^[[:alnum:]_-]*:.* ##' $(MAKEFILE_LIST) \ |
| 227 | | sort | awk 'BEGIN {FS=":.* ## "}; {printf "%-25s %s\n", $$1, $$2};' |