-
Notifications
You must be signed in to change notification settings - Fork 33
/
simple.clj
173 lines (151 loc) · 6.42 KB
/
simple.clj
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
(ns puppetlabs.ssl-utils.simple
(:import (java.util Date)
(java.security PublicKey PrivateKey)
(java.security.cert X509Certificate X509CRL))
(:require [puppetlabs.ssl-utils.core :as ssl-utils]
[clj-time.core :as time]
[schema.core :as schema]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Schemas
(def SSLKeyPair
"A schema for the map used to describe an SSL KeyPair internally."
{:public-key PublicKey
:private-key PrivateKey
:x500-name ssl-utils/ValidX500Name
:certname schema/Str})
(def SSLCert
"A schema for the map used to describe an SSL Certificate internally."
(assoc SSLKeyPair
:cert X509Certificate))
(def SSLOptions
"A schema for the SSL Options that can be used with the cert and key
generation functions."
{(schema/optional-key :extensions) [Object]
(schema/optional-key :keylength) schema/Int})
(def SSLValidDateRange
"A schema for the map representing a valid date range for an SSL certificate."
{:not-before Date
:not-after Date})
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Predicates - no longer used internally now that there are schemas
(defn validity-date-range?
"Returns true if the given map contains all the fields required to define a
validity date range for a certificate."
[x]
(and (map? x)
(instance? Date (:not-before x))
(instance? Date (:not-after x))))
(defn ssl-keys?
"Returns true if the given map contains all the fields required to define an
SSL keypair and associated certname info."
[x]
(and (map? x)
(ssl-utils/public-key? (:public-key x))
(ssl-utils/private-key? (:private-key x))
(ssl-utils/valid-x500-name? (:x500-name x))
(string? (:certname x))))
(defn ssl-cert?
"Returns true if the given map contains all the fields required to define a
certificate, keypair, and associated certname info."
[x]
(and (ssl-keys? x)
(ssl-utils/certificate? (:cert x))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Public
(schema/defn ^:always-validate cert-validity-dates :- SSLValidDateRange
"Calculate the not-before & not-after dates that define a certificate's
period of validity. The value of `ca-ttl` is expected to be in seconds,
and the dates will be based on the current time. Returns a map in the
form {:not-before Date :not-after Date}."
[ca-ttl :- schema/Int]
(let [now (time/now)
not-before (time/minus now (time/days 1))
not-after (time/plus now (time/seconds ca-ttl))]
{:not-before (.toDate not-before)
:not-after (.toDate not-after)}))
(def default-keylength
"The default bit length to use when generating keys.
Note that all API functions accept an `options' map which may
have a :keylength for specifying this value."
4096)
(schema/defn ^:always-validate gen-keys :- SSLKeyPair
"Generate public and private keys and the X500 name for the given `certname'.
An optional map may be provided to specify:
* :keylength Bit length to use for the public/private keys;
defaults to 4096."
([certname] (gen-keys certname {}))
([certname :- schema/Str
options :- SSLOptions]
(let [keylength (get options :keylength default-keylength)
keypair (ssl-utils/generate-key-pair keylength)]
{:public-key (ssl-utils/get-public-key keypair)
:private-key (ssl-utils/get-private-key keypair)
:x500-name (ssl-utils/cn certname)
:certname certname})))
(schema/defn ^:always-validate gen-cert* :- X509Certificate
"Internal helper function to generate a certificate; see `gen-cert' for the
public version of this function.
An optional map may be provided to specify:
* :extensions List of certificate extensions to include on the certificate;
defaults to []."
([ca-keys host-keys serial] (gen-cert* ca-keys host-keys serial {}))
([ca-keys host-keys serial options] (gen-cert* ca-keys host-keys serial options false))
([ca-keys :- (schema/conditional
(fn [cert] (some #(= :cert %) (keys cert))) SSLCert
:else SSLKeyPair)
host-keys :- SSLKeyPair
serial :- schema/Int
options :- SSLOptions
ca? :- schema/Bool]
(let [validity (cert-validity-dates (* 5 60 60 24 365))
extensions (if ca?
(ssl-utils/create-ca-extensions
(:x500-name host-keys)
serial
(:public-key host-keys))
(get options :extensions []))]
(ssl-utils/sign-certificate
(:x500-name ca-keys)
(:private-key ca-keys)
serial
(:not-before validity)
(:not-after validity)
(:x500-name host-keys)
(:public-key host-keys)
extensions))))
(schema/defn ^:always-validate gen-cert :- SSLCert
"Generate a certificate. An optional map may be provided to specify:
* :keylength Bit length to use for the public/private keys;
defaults to 4096.
* :extensions List of certificate extensions to include on the certificate;
defaults to []."
([certname ca-cert serial] (gen-cert certname ca-cert serial {}))
([certname ca-cert serial options] (gen-cert certname ca-cert serial options false))
([certname :- schema/Str
ca-cert :- SSLCert
serial :- schema/Int
options :- SSLOptions
ca? :- schema/Bool]
(let [cert-keys (gen-keys certname options)]
(assoc cert-keys :cert (gen-cert* ca-cert cert-keys serial options ca?)))))
(schema/defn ^:always-validate gen-self-signed-cert :- SSLCert
"Generate a self-signed certificate.
An optional map may be provided to specify:
* :keylength Bit length to use for the public/private keys;
defaults to 4096.
* :extensions List of certificate extensions to include on the certificate;
defaults to []."
([certname serial] (gen-self-signed-cert certname serial {}))
([certname serial options] (gen-self-signed-cert certname serial options false))
([certname :- schema/Str
serial :- schema/Int
options :- SSLOptions
ca? :- schema/Bool]
(let [cert-keys (gen-keys certname options)]
(assoc cert-keys :cert (gen-cert* cert-keys cert-keys serial options ca?)))))
(schema/defn ^:always-validate gen-crl :- X509CRL
[ca-cert :- SSLCert]
(ssl-utils/generate-crl
(.getIssuerX500Principal (:cert ca-cert))
(:private-key ca-cert)
(:public-key ca-cert)))