Skip to content

Commit a44be48

Browse files
update for signing a pre-generated csr.
1 parent fb305de commit a44be48

File tree

8 files changed

+521
-923
lines changed

8 files changed

+521
-923
lines changed

backend.go

Lines changed: 1 addition & 343 deletions
Original file line numberDiff line numberDiff line change
@@ -66,96 +66,6 @@ func Factory(ctx context.Context, conf *logical.BackendConfig) (logical.Backend,
6666
// Store certificates by serial number
6767
type backend struct {
6868
*framework.Backend
69-
//storage logical.Storage
70-
crlLifetime time.Duration
71-
//tidyCASGuard *uint32
72-
//store map[string][]byte
73-
}
74-
75-
// func (b *backend) paths() []*framework.Path {
76-
// return []*framework.Path{
77-
// {
78-
// Pattern: "issue/" + framework.GenericNameRegex("role"),
79-
80-
// Fields: addIssueAndSignCommonFields(map[string]*framework.FieldSchema{
81-
// "role": {
82-
// Type: framework.TypeLowerCaseString,
83-
// Description: "Name of the role",
84-
// Required: true,
85-
// },
86-
// }),
87-
88-
// Callbacks: map[logical.Operation]framework.OperationFunc{
89-
// logical.UpdateOperation: b.handleWrite,
90-
// logical.CreateOperation: b.handleWrite,
91-
// },
92-
93-
// ExistenceCheck: b.handleExistenceCheck,
94-
// },
95-
// {
96-
// Pattern: "revoke/",
97-
// Fields: map[string]*framework.FieldSchema{
98-
// "serial_number": {
99-
// Type: framework.TypeString,
100-
// Description: "The serial number of the certificate to revoke",
101-
// Required: true,
102-
// },
103-
// },
104-
// Callbacks: map[logical.Operation]framework.OperationFunc{
105-
// logical.UpdateOperation: b.handleRevoke,
106-
// },
107-
// },
108-
// {
109-
// Pattern: "sign/",
110-
// Fields: addIssueAndSignCommonFields(map[string]*framework.FieldSchema{}),
111-
// Callbacks: map[logical.Operation]framework.OperationFunc{
112-
// logical.UpdateOperation: b.handleSign,
113-
// },
114-
// },
115-
// {
116-
// Pattern: "ca/",
117-
// Fields: addIssueAndSignCommonFields(map[string]*framework.FieldSchema{}),
118-
// Callbacks: map[logical.Operation]framework.OperationFunc{
119-
// logical.ReadOperation: b.getCACert,
120-
// },
121-
// },
122-
// {
123-
// Pattern: "ca_chain/",
124-
// Fields: addIssueAndSignCommonFields(map[string]*framework.FieldSchema{}),
125-
// Callbacks: map[logical.Operation]framework.OperationFunc{
126-
// logical.ReadOperation: b.getCertChain,
127-
// },
128-
// },
129-
// {
130-
// Pattern: "certs/?$",
131-
// Fields: addIssueAndSignCommonFields(map[string]*framework.FieldSchema{}),
132-
// Callbacks: map[logical.Operation]framework.OperationFunc{
133-
// logical.ListOperation: b.handleList,
134-
// },
135-
// },
136-
// {
137-
// Pattern: `cert/(?P<serial>[0-9A-Fa-f-:]+)`,
138-
// Fields: map[string]*framework.FieldSchema{
139-
// "serial_number": {
140-
// Type: framework.TypeString,
141-
// Description: "The serial number of the certificate to read",
142-
// Required: true,
143-
// },
144-
// },
145-
// Callbacks: map[logical.Operation]framework.OperationFunc{
146-
// logical.ReadOperation: b.handleRead,
147-
// },
148-
// },
149-
// }
150-
// }
151-
152-
func (b *backend) handleExistenceCheck(ctx context.Context, req *logical.Request, data *framework.FieldData) (bool, error) {
153-
out, err := req.Storage.Get(ctx, req.Path)
154-
if err != nil {
155-
return false, errwrap.Wrapf("existence check failed: {{err}}", err)
156-
}
157-
158-
return out != nil, nil
15969
}
16070

16171
// Generate keypair and CSR
@@ -249,13 +159,7 @@ func (b *backend) submitCSR(ctx context.Context, req *logical.Request, csr strin
249159
}
250160
serial := inner["SerialNumber"].(string)
251161
kfId := inner["KeyfactorID"].(float64)
252-
//caId := inner["CertificateAuthorityId"].(float64)
253-
//b.Logger().Debug("CertificateAuthorityId = %d", caId)
254-
// b.Logger().Debug("Serial number: ", serial)
255-
// b.Logger().Debug("Keyfactor Id: ", kfId)
256-
//b.store[serial] = []byte(certs[0])
257-
// Retain the issuer cert for calls to "vault read keyfactor/cert/ca" - TODO Get via Keyfactor API
258-
//b.save(ctx, req, serial, []byte(certs[0]))
162+
259163
if err != nil {
260164
b.Logger().Error("unable to parse ca_chain response", err)
261165
}
@@ -287,255 +191,9 @@ func (b *backend) submitCSR(ctx context.Context, req *logical.Request, csr strin
287191
return nil, "", errwrap.Wrapf("unable to store the keyfactor ID for the certificate locally: {{err}}", err)
288192
}
289193

290-
// caIdEntry, err := logical.StorageEntryJSON("caId", caId)
291-
// if err != nil {
292-
// return nil, "", err
293-
// }
294-
295-
// err = req.Storage.Put(ctx, caIdEntry)
296-
// if err != nil {
297-
// return nil, "", errwrap.Wrapf("unable to store the CA ID for the certificate locally: {{err}}", err)
298-
// }
299-
300194
return certs, serial, nil
301195
}
302196

303-
// func (b *backend) requestCert(ctx context.Context, req *logical.Request, data *framework.FieldData, role string) (*logical.Response, error) {
304-
// arg, _ := json.Marshal(req.Data)
305-
// b.Logger().Debug(string(arg))
306-
// cn := ""
307-
// var ip_sans []string
308-
// var dns_sans []string
309-
310-
// // Get and validate subject info from Vault command
311-
// if len(req.Data) == 0 {
312-
// return nil, fmt.Errorf("common_name must be provided to issue certificate")
313-
// }
314-
// for k, v := range req.Data {
315-
// if k == "common_name" {
316-
// cn = v.(string)
317-
// }
318-
// if k == "ip_sans" { // TODO - type switch
319-
// ip_sans = strings.Split(v.(string), ",")
320-
// }
321-
// if k == "dns_sans" { // TODO - type switch
322-
// dns_sans = strings.Split(v.(string), ",")
323-
// }
324-
// }
325-
// b.Logger().Debug("about to check role: " + role + " against domain " + cn)
326-
327-
// if !b.checkDomainAgainstRole(ctx, req, role, cn) { // <-- leaving off here.. fix this function
328-
// return nil, fmt.Errorf("common name not allowed for provided role")
329-
// }
330-
// for u := range dns_sans {
331-
// if !b.checkDomainAgainstRole(ctx, req, role, dns_sans[u]) {
332-
// return nil, fmt.Errorf("Subject Alternative Name " + dns_sans[u] + " not allowed for provided role")
333-
// }
334-
// }
335-
336-
// // Generate and submit the CSR
337-
// csr, key := b.generateCSR(cn, ip_sans, dns_sans)
338-
// certs, serial, err := b.submitCSR(ctx, req, csr)
339-
// if err != nil {
340-
// return nil, fmt.Errorf("could not enroll certificate: %s/", err)
341-
// }
342-
343-
// // Conform response to Vault PKI API
344-
// response := &logical.Response{
345-
// Data: map[string]interface{}{
346-
// "certificate": certs[0],
347-
// "issuing_ca": certs[1],
348-
// "private_key": "-----BEGIN RSA PRIVATE KEY-----\n" + base64.StdEncoding.EncodeToString(key) + "\n-----END RSA PRIVATE KEY-----",
349-
// "private_key_type": "rsa",
350-
// "revocation_time": 0,
351-
// "serial_number": serial,
352-
// },
353-
// }
354-
355-
// return response, nil
356-
// }
357-
358-
// func (b *backend) getCACert(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
359-
// if len(issuer_chain) == 0 {
360-
// return nil, fmt.Errorf("CA certificate unknown")
361-
// }
362-
// b.Logger().Debug("issuer: " + issuer_chain[0])
363-
// response := &logical.Response{
364-
// Data: map[string]interface{}{
365-
// "certificate": issuer_chain[0],
366-
// },
367-
// }
368-
// return response, nil
369-
// }
370-
371-
// func (b *backend) getCertChain(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
372-
// chain := ""
373-
// for c := range issuer_chain {
374-
// chain += issuer_chain[c]
375-
// }
376-
// b.Logger().Debug("issuer chain: " + chain)
377-
// response := &logical.Response{
378-
// Data: map[string]interface{}{
379-
// "certificate": chain,
380-
// },
381-
// }
382-
// return response, nil
383-
// }
384-
385-
// Check if a domain is allowed for a given role based on allowed domains and whether subdomains are allowed
386-
func (b *backend) checkDomainAgainstRole(ctx context.Context, req *logical.Request, role string, domain string) bool {
387-
b.Logger().Debug("checking role: " + role + " against domain " + domain)
388-
389-
roleEntry, err := b.getRole(ctx, req.Storage, role)
390-
if err != nil {
391-
b.Logger().Error("Error retrieving role " + role)
392-
return false
393-
}
394-
395-
if roleEntry.AllowedBaseDomain == domain {
396-
return true
397-
}
398-
399-
if strings.Contains(domain, roleEntry.AllowedBaseDomain) && roleEntry.AllowSubdomains {
400-
return true
401-
}
402-
403-
return false
404-
}
405-
406-
// Add role or enroll certificate
407-
// func (b *backend) handleWrite(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
408-
// b.load(ctx, req)
409-
// role := data.Get("role").(string)
410-
411-
// b.Logger().Debug("parsing role: " + role)
412-
413-
// // look up role then request certificate
414-
415-
// entry, err := req.Storage.Get(ctx, "role/"+role)
416-
// if err != nil || entry == nil {
417-
// return nil, fmt.Errorf("cannot find provided role")
418-
// }
419-
420-
// return b.requestCert(ctx, req, data, role)
421-
// }
422-
423-
// func (b *backend) handleRevoke(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
424-
// sn := data.Get("serial_number").(string)
425-
426-
// if sn == "" {
427-
// return nil, fmt.Errorf("must supply serial_number parameter to revoke")
428-
// }
429-
430-
// return b.revoke(ctx, req, data, sn)
431-
// }
432-
433-
func (b *backend) handleSign(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
434-
role := data.Get("role").(string)
435-
csr := data.Get("csr").(string)
436-
if csr == "" {
437-
return nil, fmt.Errorf("must supply csr parameter to sign")
438-
}
439-
return b.sign(ctx, req, csr, role)
440-
}
441-
442-
func (b *backend) sign(ctx context.Context, req *logical.Request, csrString string, role string) (*logical.Response, error) {
443-
// TODO - Get CSR to parse from CLI
444-
// csr, err := x509.ParseCertificateRequest([]byte(csrString))
445-
// if err != nil {
446-
// return nil, fmt.Errorf("Could not parse CSR: {{err}}",err)
447-
// }
448-
// cn := csr.Subject.CommonName
449-
// b.Logger().Debug("Got CSR with CN="+cn)
450-
// if !b.checkDomainAgainstRole(role, cn) {
451-
// return nil, fmt.Errorf("Common name {{cn}} is not allowed for provided role", cn)
452-
// }
453-
// TODO - check SANs
454-
455-
certs, serial, err := b.submitCSR(ctx, req, csrString)
456-
457-
if err != nil {
458-
b.Logger().Info("Error signing certificate: {{err}}", err)
459-
return nil, err
460-
}
461-
462-
response := &logical.Response{
463-
Data: map[string]interface{}{
464-
"certificate": certs[0],
465-
"issuing_ca": certs[1],
466-
"ca_chain": certs[1:],
467-
"serial_number": serial,
468-
"revocation_time": 0,
469-
},
470-
}
471-
// err = req.Storage.Put(ctx, &logical.StorageEntry{
472-
// Key: "certs/" + normalizeSerial(serial),
473-
// Value: certs[0],
474-
// })
475-
// if err != nil {
476-
// return nil, errwrap.Wrapf("unable to store certificate locally: {{err}}", err)
477-
// }
478-
return response, nil
479-
480-
}
481-
482-
// Revoke certificate.
483-
// func (b *backend) revoke(ctx context.Context, req *logical.Request, data *framework.FieldData, serial string) (*logical.Response, error) {
484-
// serial = strings.ReplaceAll(serial, "-", "")
485-
// serial = strings.ReplaceAll(serial, ":", "")
486-
// fmt.Println("Revoking serial number " + serial)
487-
488-
// //b.Logger().Info(string(b.store[path]))
489-
490-
// // set up keyfactor api request
491-
// url := config["protocol"] + "://" + config["host"] + "/CMSAPI/Certificates/3/Revoke"
492-
// payload := `{"Lookup":{"Type":"Serial","SerialNumber":"` + serial + `","IssuerDN":"CN=jdk-CA1,DC=jdk,DC=cms"},"Details":{"Reason":4, "EffectiveDate": "2020-5-5", "Comment":"" }}`
493-
494-
// httpReq, _ := http.NewRequest("POST", url, strings.NewReader(payload))
495-
496-
// httpReq.Header.Add("content-type", "application/json")
497-
// httpReq.Header.Add("authorization", "Basic "+config["creds"])
498-
499-
// res, err := http.DefaultClient.Do(httpReq)
500-
// if err != nil {
501-
// b.Logger().Error("Revoke failed: {{err}}", err)
502-
// }
503-
504-
// defer res.Body.Close()
505-
// _, _ = ioutil.ReadAll(res.Body)
506-
507-
// // Remove entry for specified path
508-
// //delete(b.store, path)
509-
// certEntry, err := fetchCertBySerial(ctx, req, "certs/", serial)
510-
// var revInfo revocationInfo
511-
// revEntry, err := fetchCertBySerial(ctx, req, "revoked/", serial)
512-
// if err != nil {
513-
// switch err.(type) {
514-
// case errutil.UserError:
515-
// return logical.ErrorResponse(err.Error()), nil
516-
// case errutil.InternalError:
517-
// return nil, err
518-
// }
519-
// }
520-
521-
// currTime := time.Now()
522-
// revInfo.CertificateBytes = certEntry.Value
523-
// revInfo.RevocationTime = currTime.Unix()
524-
// revInfo.RevocationTimeUTC = currTime.UTC()
525-
526-
// revEntry, err = logical.StorageEntryJSON("revoked/"+normalizeSerial(serial), revInfo)
527-
// if err != nil {
528-
// return nil, fmt.Errorf("error creating revocation entry")
529-
// }
530-
531-
// err = req.Storage.Put(ctx, revEntry)
532-
// if err != nil {
533-
// return nil, fmt.Errorf("error saving revoked certificate to new location")
534-
// }
535-
536-
// return nil, nil
537-
// }
538-
539197
const keyfactorHelp = `
540198
The Keyfactor backend is a pki service that issues and manages certificates.
541199
`

0 commit comments

Comments
 (0)