summaryrefslogtreecommitdiffstats
path: root/src/test/ssl/sslfiles.mk
blob: 5d5e1376ad5aa37631d1a8623befe07f3059fe80 (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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
#-------------------------------------------------------------------------
#
# Makefile for sslfiles
#
#   The SSL test files are completely disjoint from the rest of the build; they
#   don't rely on other targets or on Makefile.global. Since these recipes rely
#   on some default Make behavior that's disabled in the main build tree, such
#   as intermediate cleanup, they've been moved into their own separate file.
#   The main Makefile in this directory defers to this helper file when
#   building the sslfiles-related targets.
#
# Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
# Portions Copyright (c) 1994, Regents of the University of California
#
# src/test/ssl/sslfiles.mk
#
#-------------------------------------------------------------------------

#
# To add a new server or client certificate, add a new <name>.config file in
# the conf/ directory, then add <name> to either SERVERS or CLIENTS below. A
# key/certificate pair will be generated for you, signed by the appropriate CA.
#
SERVERS := server-cn-and-alt-names \
	server-cn-and-ip-alt-names \
	server-cn-only \
	server-ip-alt-names \
	server-ip-cn-only \
	server-ip-cn-and-alt-names \
	server-ip-cn-and-dns-alt-names \
	server-ip-in-dnsname \
	server-single-alt-name \
	server-multiple-alt-names \
	server-no-names \
	server-revoked
CLIENTS := client client-dn client-revoked client_ext

#
# To add a new non-standard certificate, add it to SPECIAL_CERTS and then add
# a recipe for creating it to the "Special-case certificates" section below.
#
SPECIAL_CERTS := ssl/server-rsapss.crt

# Likewise for non-standard keys
SPECIAL_KEYS := ssl/server-password.key \
	ssl/client-der.key \
	ssl/client-encrypted-pem.key \
	ssl/client-encrypted-der.key \
	ssl/server-rsapss.key

#
# These files are just concatenations of other files. You can add new ones to
# COMBINATIONS here, then declare the constituent files as dependencies in the
# "Combined files" section below.
#
COMBINATIONS := \
	ssl/both-cas-1.crt \
	ssl/both-cas-2.crt \
	ssl/root+server_ca.crt \
	ssl/root+server.crl \
	ssl/root+client_ca.crt \
	ssl/root+client.crl \
	ssl/client+client_ca.crt

CERTIFICATES := root_ca server_ca client_ca $(SERVERS) $(CLIENTS)
STANDARD_CERTS := $(CERTIFICATES:%=ssl/%.crt)
STANDARD_KEYS := $(CERTIFICATES:%=ssl/%.key)
CRLS := ssl/root.crl \
	ssl/client.crl \
	ssl/server.crl

SSLFILES := \
	$(STANDARD_CERTS) \
	$(STANDARD_KEYS) \
	$(SPECIAL_CERTS) \
	$(SPECIAL_KEYS) \
	$(COMBINATIONS) \
	$(CRLS)
SSLDIRS := ssl/client-crldir \
	ssl/server-crldir \
	ssl/root+client-crldir \
	ssl/root+server-crldir

# This target re-generates all the key and certificate files. Usually we just
# use the ones that are committed to the tree without rebuilding them.
#
.PHONY: sslfiles
sslfiles: $(SSLFILES) $(SSLDIRS)

#
# Special-case certificates
#

# Root CA is self-signed.
ssl/root_ca.crt: ssl/root_ca.key conf/root_ca.config
	openssl req -new -x509 -config conf/root_ca.config -days 10000 -key $< -out $@

# Certificate using RSA-PSS algorithm. Also self-signed.
ssl/server-rsapss.crt: ssl/server-rsapss.key conf/server-rsapss.config
	$(OPENSSL) req -new -x509 -config conf/server-rsapss.config -key $< -out $@

#
# Special-case keys
#
# All targets here are contained in $(SPECIAL_KEYS).
#

# Password-protected version of server-cn-only.key
ssl/server-password.key: ssl/server-cn-only.key
	openssl rsa -aes256 -in $< -out $@ -passout 'pass:secret1'

# Key that uses the RSA-PSS algorithm
ssl/server-rsapss.key:
	$(OPENSSL) genpkey -algorithm rsa-pss -out $@

# DER-encoded version of client.key
ssl/client-der.key: ssl/client.key
	openssl rsa -in $< -outform DER -out $@

# Convert client.key to encrypted PEM (X.509 text) and DER (X.509 ASN.1)
# formats to test libpq's support for the sslpassword= option.
ssl/client-encrypted-pem.key: ssl/client.key
	openssl rsa -in $< -outform PEM -aes128 -passout 'pass:dUmmyP^#+' -out $@
# TODO Explicitly choosing -aes128 generates a key unusable to PostgreSQL with
# OpenSSL 3.0.0, so fall back on the default for now.
ssl/client-encrypted-der.key: ssl/client.key
	openssl rsa -in $< -outform DER -passout 'pass:dUmmyP^#+' -out $@

#
# Combined files
#
# All targets in $(COMBINATIONS) share a single recipe; just declare the
# necessary dependencies and they'll be smashed together.
#

# Root certificate file that contains both CA certificates, for testing
# that multiple certificates can be used.
ssl/both-cas-1.crt: ssl/root_ca.crt ssl/client_ca.crt ssl/server_ca.crt

# The same, but the certs are in different order
ssl/both-cas-2.crt: ssl/root_ca.crt ssl/server_ca.crt ssl/client_ca.crt

# A root certificate file for the client, to validate server certs.
ssl/root+server_ca.crt: ssl/root_ca.crt ssl/server_ca.crt

# and for the server, to validate client certs
ssl/root+client_ca.crt: ssl/root_ca.crt ssl/client_ca.crt

# and for the client, to present to the server
ssl/client+client_ca.crt: ssl/client.crt ssl/client_ca.crt

# If a CRL is used, OpenSSL requires a CRL file for *all* the CAs in the
# chain, even if some of them are empty.
ssl/root+server.crl: ssl/root.crl ssl/server.crl
ssl/root+client.crl: ssl/root.crl ssl/client.crl

$(COMBINATIONS):
	cat $^ > $@

#
# Standard keys
#

$(STANDARD_KEYS):
	openssl genrsa -out $@ 2048
	chmod 0600 $@

#
# Standard certificates
#

CA_CERTS     := ssl/server_ca.crt ssl/client_ca.crt
SERVER_CERTS := $(SERVERS:%=ssl/%.crt)
CLIENT_CERTS := $(CLIENTS:%=ssl/%.crt)

# See the "CA State" section below.
root_ca_state_files := ssl/root_ca-certindex ssl/root_ca-certindex.attr ssl/root_ca.srl
server_ca_state_files := ssl/server_ca-certindex ssl/server_ca-certindex.attr ssl/server_ca.srl
client_ca_state_files := ssl/client_ca-certindex ssl/client_ca-certindex.attr ssl/client_ca.srl

# These are the workhorse recipes. `openssl ca` can't be safely run from
# parallel processes, so we must mark the entire Makefile .NOTPARALLEL.
.NOTPARALLEL:
$(CA_CERTS): ssl/%.crt: ssl/%.csr conf/%.config conf/cas.config ssl/root_ca.crt | ssl/new_certs_dir $(root_ca_state_files)
	openssl ca -batch -config conf/cas.config -name root_ca   -notext -in $< -out $@

$(SERVER_CERTS): ssl/%.crt: ssl/%.csr conf/%.config conf/cas.config ssl/server_ca.crt | ssl/new_certs_dir $(server_ca_state_files)
	openssl ca -batch -config conf/cas.config -name server_ca -notext -in $< -out $@

$(CLIENT_CERTS): ssl/%.crt: ssl/%.csr conf/%.config conf/cas.config ssl/client_ca.crt | ssl/new_certs_dir $(client_ca_state_files)
	openssl ca -batch -config conf/cas.config -name client_ca -notext -in $< -out $@

# The CSRs don't need to persist after a build.
.INTERMEDIATE: $(CERTIFICATES:%=ssl/%.csr)
ssl/%.csr: ssl/%.key conf/%.config
	openssl req -new -key $< -out $@ -config conf/$*.config

#
# CA State
#
# All of these are intended to be order-only dependencies; additionally, the
# pattern recipes are marked as explicit intermediates. The goal is for Make to
# create the state files once for each CA, allow them to accumulate whatever
# state is needed, and then automatically remove them at the end of the run.
#

.INTERMEDIATE: $(root_ca_state_files) $(server_ca_state_files) $(client_ca_state_files)

# OpenSSL requires a directory to put all generated certificates in. We don't
# use this for anything, but we need a location.
ssl/new_certs_dir:
	mkdir $@

ssl/%-certindex:
	touch $@

ssl/%-certindex.attr:
	echo "unique_subject=no" > $@

# The first serial number for each CA is based on the current timestamp, to
# avoid collisions across Make runs.
ssl/%.srl:
	date +%Y%m%d%H%M%S00 > $@

#
# CRLs
#

ssl/root.crl: ssl/root_ca.crt | $(root_ca_state_files)
	openssl ca -config conf/cas.config -name root_ca   -gencrl -out $@

ssl/server.crl: ssl/server-revoked.crt ssl/server_ca.crt | $(server_ca_state_files)
	openssl ca -config conf/cas.config -name server_ca -revoke $<
	openssl ca -config conf/cas.config -name server_ca -gencrl -out $@

ssl/client.crl: ssl/client-revoked.crt ssl/client_ca.crt | $(client_ca_state_files)
	openssl ca -config conf/cas.config -name client_ca -revoke $<
	openssl ca -config conf/cas.config -name client_ca -gencrl -out $@

#
# CRL hash directories
#

ssl/root+server-crldir: ssl/server.crl ssl/root.crl
ssl/root+client-crldir: ssl/client.crl ssl/root.crl
ssl/server-crldir: ssl/server.crl
ssl/client-crldir: ssl/client.crl

crlhashfile = $(shell openssl crl -hash -noout -in $(1)).r0

ssl/%-crldir:
	mkdir -p $@
	rm -f $@/*.r0
	$(foreach crl,$^,cp $(crl) $@/$(call crlhashfile,$(crl)) &&) true
	touch $@

.PHONY: sslfiles-clean
sslfiles-clean:
	rm -f $(SSLFILES) ssl/*.old ssl/*.csr ssl/*.srl ssl/*-certindex*
	rm -rf $(SSLDIRS) ssl/new_certs_dir

# The difference between the below clean targets and sslfiles-clean is that the
# clean targets will be run during a "standard" recursive clean run from the
# main build tree. The sslfiles-clean target must be run explicitly from this
# directory.
.PHONY: clean distclean maintainer-clean
clean distclean maintainer-clean:
	rm -rf ssl/*.old ssl/new_certs_dir ssl/client*_tmp.key