-
Notifications
You must be signed in to change notification settings - Fork 0
/
cert_controller.go
221 lines (202 loc) · 7.78 KB
/
cert_controller.go
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
package api
import (
"encoding/json"
"net/http"
"github.com/gorilla/context"
"github.com/gorilla/mux"
"github.com/infamousjoeg/cyberark-aam-pkiaas/internal/backend"
"github.com/infamousjoeg/cyberark-aam-pkiaas/internal/httperror"
"github.com/infamousjoeg/cyberark-aam-pkiaas/internal/pki"
"github.com/infamousjoeg/cyberark-aam-pkiaas/internal/types"
)
// SignCertHandler -------------------------------------------------------------
// Handler method to read a CSR from HTTP request and generate a CA-signed certificate
// from it. Before being signed, the CSR's properties and extensions are compared
// against a template
func SignCertHandler(w http.ResponseWriter, r *http.Request) {
if !pki.ValidateContentType(r.Header, "application/json") {
httpErr := httperror.InvalidContentType()
http.Error(w, httpErr.JSON(), httpErr.HTTPResponse)
return
}
// Ensure that the requesting entity can both authenticate to the PKI service, as well as
// has authorization to access the Sign Certificate endpoint using the requested template
storage := context.Get(r, "Storage").(backend.Storage)
authHeader := r.Header.Get("Authorization")
err := storage.GetAccessControl().Authenticate(authHeader)
if err != nil {
httpErr := httperror.InvalidAuthn(err.Error())
http.Error(w, httpErr.JSON(), httpErr.HTTPResponse)
return
}
var signReq types.SignRequest
decoder := json.NewDecoder(r.Body)
decoder.DisallowUnknownFields()
err = decoder.Decode(&signReq)
if err != nil {
httpErr := httperror.RequestDecodeFail(err.Error())
http.Error(w, httpErr.JSON(), httpErr.HTTPResponse)
return
}
err = storage.GetAccessControl().SignCertificate(authHeader, signReq.TemplateName)
if err != nil {
httpErr := httperror.InvalidAuthz(err.Error())
http.Error(w, httpErr.JSON(), httpErr.HTTPResponse)
return
}
response, httpErr := pki.SignCert(signReq, storage)
if httpErr != (httperror.HTTPError{}) {
http.Error(w, httpErr.JSON(), httpErr.HTTPResponse)
return
}
w.Header().Set("Content-Type", "application/json")
err = json.NewEncoder(w).Encode(response)
if err != nil {
httpErr := httperror.ResponseWriteError(err.Error())
http.Error(w, httpErr.JSON(), httpErr.HTTPResponse)
return
}
}
// CreateCertHandler -----------------------------------------------------------
// Handler method used to build a new certificate with the provided common name
// based upon the provided template
func CreateCertHandler(w http.ResponseWriter, r *http.Request) {
if !pki.ValidateContentType(r.Header, "application/json") {
httpErr := httperror.InvalidContentType()
http.Error(w, httpErr.JSON(), httpErr.HTTPResponse)
return
}
// Ensure that the requesting entity can both authenticate to the PKI service, as well as
// has authorization to access the Create Certificate endpoint using the requested template
storage := context.Get(r, "Storage").(backend.Storage)
authHeader := r.Header.Get("Authorization")
err := storage.GetAccessControl().Authenticate(authHeader)
if err != nil {
httpErr := httperror.InvalidAuthn(err.Error())
http.Error(w, httpErr.JSON(), httpErr.HTTPResponse)
return
}
var certReq types.CreateCertReq
decoder := json.NewDecoder(r.Body)
decoder.DisallowUnknownFields()
err = decoder.Decode(&certReq)
if err != nil {
httpErr := httperror.RequestDecodeFail(err.Error())
http.Error(w, httpErr.JSON(), httpErr.HTTPResponse)
return
}
err = storage.GetAccessControl().CreateCertificate(authHeader, certReq.TemplateName)
if err != nil {
httpErr := httperror.InvalidAuthz(err.Error())
http.Error(w, httpErr.JSON(), httpErr.HTTPResponse)
return
}
response, httpErr := pki.CreateCert(certReq, storage)
if httpErr != (httperror.HTTPError{}) {
http.Error(w, httpErr.JSON(), httpErr.HTTPResponse)
return
}
w.Header().Set("Content-Type", "application/json")
err = json.NewEncoder(w).Encode(response)
if err != nil {
httpErr := httperror.ResponseWriteError(err.Error())
http.Error(w, httpErr.JSON(), httpErr.HTTPResponse)
return
}
}
// GetCertHandler --------------------------------------------------------------------
func GetCertHandler(w http.ResponseWriter, r *http.Request) {
authHeader := r.Header.Get("Authorization")
serialNumber := mux.Vars(r)["serialNumber"]
// Ensure that the requesting entity can both authenticate to the PKI service, but there
// is no need for an authorization check as all authenticated entities will be allowed
// to retrieve public certificate data
storage := context.Get(r, "Storage").(backend.Storage)
err := storage.GetAccessControl().Authenticate(authHeader)
if err != nil {
httpErr := httperror.InvalidAuthn(err.Error())
http.Error(w, httpErr.JSON(), httpErr.HTTPResponse)
return
}
response, httpErr := pki.GetCert(serialNumber, storage)
if httpErr != (httperror.HTTPError{}) {
http.Error(w, httpErr.JSON(), httpErr.HTTPResponse)
return
}
w.Header().Set("Content-Type", "application/json")
err = json.NewEncoder(w).Encode(response)
if err != nil {
httpErr := httperror.ResponseEncodeError(err.Error())
http.Error(w, httpErr.JSON(), httpErr.HTTPResponse)
return
}
}
// ListCertsHandler ------------------------------------------------------------------
// Handler method used to retrieve the serial number of all certificates currently
// in the backend storage repository and return them
func ListCertsHandler(w http.ResponseWriter, r *http.Request) {
authHeader := r.Header.Get("Authorization")
// Ensure that the requesting entity can both authenticate to the PKI service, but there
// is no need for an authorization check as all authenticated entities will be allowed
// to retrieve public certificate data
storage := context.Get(r, "Storage").(backend.Storage)
err := storage.GetAccessControl().Authenticate(authHeader)
if err != nil {
httpErr := httperror.InvalidAuthn(err.Error())
http.Error(w, httpErr.JSON(), httpErr.HTTPResponse)
return
}
response, httpErr := pki.ListCerts(storage)
if httpErr != (httperror.HTTPError{}) {
http.Error(w, httpErr.JSON(), httpErr.HTTPResponse)
return
}
w.Header().Set("Content-Type", "application/json")
err = json.NewEncoder(w).Encode(response)
if err != nil {
httpErr := httperror.ResponseEncodeError(err.Error())
http.Error(w, httpErr.JSON(), httpErr.HTTPResponse)
return
}
}
// RevokeCertHandler -----------------------------------------------------------------
// Handler method that updates to revoke a certificate for a specified, but optional,
// reason code. Updates the certificate object in the storage backend as well as generates
// a new CRL
func RevokeCertHandler(w http.ResponseWriter, r *http.Request) {
if !pki.ValidateContentType(r.Header, "application/json") {
httpErr := httperror.InvalidContentType()
http.Error(w, httpErr.JSON(), httpErr.HTTPResponse)
return
}
// Ensure that the requesting entity can both authenticate to the PKI service, as well as
// has authorization to access the Revoke Certificate endpoint for the specified serial number
storage := context.Get(r, "Storage").(backend.Storage)
authHeader := r.Header.Get("Authorization")
err := storage.GetAccessControl().Authenticate(authHeader)
if err != nil {
httpErr := httperror.InvalidAuthn(err.Error())
http.Error(w, httpErr.JSON(), httpErr.HTTPResponse)
return
}
var crlReq = types.RevokeRequest{}
decoder := json.NewDecoder(r.Body)
decoder.DisallowUnknownFields()
err = decoder.Decode(&crlReq)
if err != nil {
httpErr := httperror.RequestDecodeFail(err.Error())
http.Error(w, httpErr.JSON(), httpErr.HTTPResponse)
return
}
err = storage.GetAccessControl().RevokeCertificate(authHeader, crlReq.SerialNumber)
if err != nil {
httpErr := httperror.InvalidAuthz(err.Error())
http.Error(w, httpErr.JSON(), httpErr.HTTPResponse)
return
}
httpErr := pki.RevokeCert(crlReq, storage)
if httpErr != (httperror.HTTPError{}) {
http.Error(w, httpErr.JSON(), httpErr.HTTPResponse)
return
}
}