Skip to content

Commit dfb955e

Browse files
updated get cert method to use Keyfactor SDK
1 parent 9883659 commit dfb955e

2 files changed

Lines changed: 47 additions & 73 deletions

File tree

cert_util.go

Lines changed: 47 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,7 @@ import (
2222
"encoding/pem"
2323
"errors"
2424
"fmt"
25-
"io"
2625
"net"
27-
"net/http"
2826
"strings"
2927
"time"
3028

@@ -238,20 +236,18 @@ func fetchCAInfo(ctx context.Context, req *logical.Request, b *keyfactorBackend,
238236
// it hasn't been stored locally, we we need to retreive a certificate issued by the CA
239237
// and then extract the chain
240238

241-
issued_certs, err := fetchCertIssuedByCA(ctx, req, b, caName) // we get the ID of a cert issued by the CA
239+
issued_cert, err := fetchCertIssuedByCA(ctx, req, b, caName) // we get the ID of a cert issued by the CA
242240

243241
if err != nil {
244242
return nil, errutil.InternalError{Err: fmt.Sprintf("failed to retreive any cert issued by the CA: %s", err)}
245243
}
246244

247-
if len(issued_certs) == 0 {
245+
if issued_cert == nil {
248246
return nil, fmt.Errorf("no certificates issued by %s were found", caName)
249247
}
250248

251-
issued_cert := issued_certs[0]
252-
253249
b.Logger().Trace("extracting the CA and Chain from the retreived cert.")
254-
ca_chain, ca_cert, err := fetchChainAndCAForCert(ctx, req, b, issued_cert.ID) // we download the full cert and chain
250+
ca_chain, ca_cert, err := fetchChainAndCAForCert(ctx, req, b, int(*issued_cert.Id)) // we download the full cert and chain
255251
if err != nil {
256252
b.Logger().Error("error getting full chain and CA for cert: %s", err)
257253
return nil, err
@@ -362,7 +358,7 @@ func fetchCertBySerial(ctx context.Context, req *logical.Request, prefix, serial
362358
return certEntry, nil
363359
}
364360

365-
func fetchCertIssuedByCA(ctx context.Context, req *logical.Request, b *keyfactorBackend, caName string) (KeyfactorCertResponse, error) {
361+
func fetchCertIssuedByCA(ctx context.Context, req *logical.Request, b *keyfactorBackend, caName string) (*v1.CertificatesCertificateRetrievalResponse, error) {
366362
// call certificates endpoint, limit results to 1, filter by CA name
367363
config, err := b.fetchConfig(ctx, req.Storage)
368364
if err != nil {
@@ -377,54 +373,38 @@ func fetchCertIssuedByCA(ctx context.Context, req *logical.Request, b *keyfactor
377373
if err != nil {
378374
b.Logger().Error("unable to create the http client")
379375
}
380-
// This is only needed when running as a vault extension
381-
b.Logger().Debug("Closing idle connections")
382-
client.httpClient.CloseIdleConnections()
383-
caName = strings.Replace(caName, " ", "%20", -1)
384-
reqUrl := config.KeyfactorUrl + "/" + config.CommandAPIPath + "/Certificates?pq.queryString=CA%20-eq%20%22" + caName + "%20%22&ReturnLimit=1"
385376

386-
b.Logger().Debug("url: " + reqUrl)
387-
388-
httpReq, err := http.NewRequest("GET", reqUrl, nil)
389-
if err != nil {
390-
b.Logger().Info("Error forming request: {{err}}", err)
391-
}
377+
//caName = strings.Replace(caName, " ", "%20", -1)
392378

393-
httpReq.Header.Add("x-keyfactor-requested-with", "APIClient")
394-
httpReq.Header.Add("content-type", "application/json")
379+
getCertRequest := v1.ApiGetCertificatesRequest{}
380+
getCertRequest.QueryString("CA -eq " + caName)
381+
getCertRequest.ReturnLimit(1)
395382

396383
// Send request and check status
397-
b.Logger().Debug("About to connect to " + reqUrl + "for cert retrieval")
398-
res, err := client.httpClient.Do(httpReq)
384+
b.Logger().Debug("calling API with query string %s for cert retrieval", getCertRequest.QueryString)
385+
386+
apiRequest := client.V1.CertificateApi.NewGetCertificatesRequest(ctx)
387+
388+
certs, httpResponse, err := apiRequest.ApiService.GetCertificatesExecute(getCertRequest)
389+
399390
if err != nil {
400391
b.Logger().Info("failed getting cert: {{err}}", err)
401392
return nil, err
402393
}
403-
if res.StatusCode != 200 {
404-
b.Logger().Error("request failed: server returned" + fmt.Sprint(res.StatusCode))
405-
b.Logger().Error("Error response = " + fmt.Sprint(res.Body))
406-
return nil, fmt.Errorf("error downloading certificate. returned status = %d\n ", res.StatusCode)
407-
}
408-
409-
// Read response and return certificate and key
410-
defer res.Body.Close()
411394

412-
body, err := io.ReadAll(res.Body)
413-
if err != nil {
414-
b.Logger().Info("Error reading response: {{err}}", err)
415-
return nil, err
395+
if httpResponse.StatusCode != 200 {
396+
b.Logger().Error("request failed: server returned" + fmt.Sprint(httpResponse.StatusCode))
397+
b.Logger().Error("Error response = " + fmt.Sprint(httpResponse.Body))
398+
return nil, fmt.Errorf("error downloading certificate. returned status = %d\n ", httpResponse.StatusCode)
416399
}
417400

418-
// Parse response
419-
var r KeyfactorCertResponse
420-
json.Unmarshal(body, &r)
421-
b.Logger().Debug("response = ", r)
401+
b.Logger().Debug("response = ", certs)
422402

423-
if len(r) == 0 {
403+
if len(certs) == 0 {
424404
return nil, fmt.Errorf("no certificates issued by CA %s found in Command. At least 1 must exist in order to retreive the CA or CA chain certificate(s)", caName)
425405
}
426406

427-
return r, nil
407+
return &certs[0], nil
428408
}
429409

430410
func fetchChainAndCAForCert(ctx context.Context, req *logical.Request, b *keyfactorBackend, kfCertId int) ([]string, string, error) {
@@ -443,49 +423,44 @@ func fetchChainAndCAForCert(ctx context.Context, req *logical.Request, b *keyfac
443423
}
444424
// This is only needed when running as a vault extension
445425
b.Logger().Debug("Closing idle connections")
446-
client.httpClient.CloseIdleConnections()
447426

448427
// Build request
449-
reqUrl := config.KeyfactorUrl + "/" + config.CommandAPIPath + "/Certificates/Download"
450-
b.Logger().Debug("url: " + reqUrl)
451-
bodyContent := fmt.Sprintf(`{"CertID": %d, "IncludeChain": true, "ChainOrder": "endentityfirst" }`, kfCertId)
452-
payload := strings.NewReader(bodyContent)
453-
b.Logger().Debug("body: " + bodyContent)
454-
httpReq, err := http.NewRequest("POST", reqUrl, payload)
455-
if err != nil {
456-
b.Logger().Info("Error forming request: %s", err)
428+
429+
certId := int32(kfCertId)
430+
chainOrder := "endentityfirst"
431+
includeChain := true
432+
433+
certDownloadRequest := v1.CertificatesCertificateDownloadRequest{
434+
CertID: *v1.NewNullableInt32(&certId),
435+
ChainOrder: *v1.NewNullableString(&chainOrder),
436+
IncludeChain: &includeChain,
457437
}
458-
httpReq.Header.Add("x-keyfactor-requested-with", "APIClient")
459-
httpReq.Header.Add("content-type", "application/json")
460-
httpReq.Header.Add("x-certificateformat", "P7B")
438+
439+
apiRequest := client.V1.CertificateApi.NewCreateCertificatesDownloadRequest(ctx)
440+
apiRequest.CertificatesCertificateDownloadRequest(certDownloadRequest)
441+
apiRequest.XCertificateformat("P7B")
442+
443+
reqMap, _ := certDownloadRequest.ToMap()
461444

462445
// Send request and check status
463-
b.Logger().Debug("About to connect to " + config.KeyfactorUrl + "for cert retrieval")
464-
res, err := client.httpClient.Do(httpReq)
446+
b.Logger().Debug("request parameters: %s", reqMap)
447+
b.Logger().Debug("making request for cert retrieval")
448+
449+
response, httpResponse, err := apiRequest.Execute()
450+
465451
if err != nil {
466452
b.Logger().Info(fmt.Sprintf("failed getting cert: %s", err))
467453
return nil, "", err
468454
}
469-
if res.StatusCode != 200 {
470-
b.Logger().Error("request failed: server returned" + fmt.Sprint(res.StatusCode))
471-
b.Logger().Error("Error response = " + fmt.Sprint(res.Body))
472-
return nil, "", fmt.Errorf("error downloading certificate. returned status = %d\n ", res.StatusCode)
455+
if httpResponse.StatusCode != 200 {
456+
b.Logger().Error("request failed: server returned" + fmt.Sprint(httpResponse.StatusCode))
457+
b.Logger().Error("Error response = " + fmt.Sprint(httpResponse.Body))
458+
return nil, "", fmt.Errorf("error downloading certificate. returned status = %d\n ", httpResponse.StatusCode)
473459
}
474460

475-
// Read response and return certificate and key
476-
defer res.Body.Close()
477-
// Parse response
478-
479-
body, err := io.ReadAll(res.Body)
480-
if err != nil {
481-
b.Logger().Info("Error reading response: %s", err)
482-
return nil, "", err
483-
}
484-
var r KeyfactorCertDownloadResponse
485-
json.Unmarshal(body, &r)
486-
b.Logger().Debug("response = ", r)
461+
// Read response and convert to x509 certificates
487462

488-
certs, p7bErr := ConvertBase64P7BtoCertificates(r.Content)
463+
certs, p7bErr := ConvertBase64P7BtoCertificates(response.GetContent())
489464
if p7bErr != nil {
490465
return nil, "", p7bErr
491466
}

path_certs.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -533,7 +533,6 @@ func revokeCert(ctx context.Context, b *keyfactorBackend, req *logical.Request,
533533
}
534534

535535
b.Logger().Debug("Closing idle connections")
536-
client.httpClient.CloseIdleConnections()
537536

538537
kfId, err := req.Storage.Get(ctx, "kfId/"+serial) //retrieve the keyfactor certificate ID, keyed by sn here
539538
if err != nil {

0 commit comments

Comments
 (0)