Skip to content

Commit 32de94b

Browse files
replaced all Command API calls with Keyfactor GO SDK. Added RunningVersion and multiplexing support
1 parent dfb955e commit 32de94b

File tree

9 files changed

+672
-454
lines changed

9 files changed

+672
-454
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
- 1.4.2
2+
- Updated the Hashicorp SDK libraries
3+
- Incorporated the Keyfactor GO SDK for authentication and interaction with the Command API
4+
15
- 1.4.1
26
- Updated CA and CA chain retreival to work for CA's hosted outside of Command (EJBCA)
37
- Updated Keyfactor Client library to 1.2.0

backend.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ const (
2525
operationPrefixKeyfactor string = "keyfactor"
2626
)
2727

28+
const PluginVersion = "1.4.2" // this should match the release version of the plugin
29+
2830
// Factory configures and returns backend
2931
func Factory(ctx context.Context, conf *logical.BackendConfig) (logical.Backend, error) {
3032

@@ -68,6 +70,7 @@ func backend() *keyfactorBackend {
6870
BackendType: logical.TypeLogical,
6971
Invalidate: b.invalidate,
7072
InitializeFunc: b.Initialize,
73+
RunningVersion: "v" + PluginVersion,
7174
}
7275
return &b
7376
}

cert_util.go

Lines changed: 85 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ import (
2727
"time"
2828

2929
v1 "github.com/Keyfactor/keyfactor-go-client-sdk/v24/api/keyfactor/v1"
30-
"github.com/hashicorp/errwrap"
3130
"github.com/hashicorp/vault/sdk/helper/errutil"
3231
"github.com/hashicorp/vault/sdk/logical"
3332
"go.mozilla.org/pkcs7"
@@ -78,7 +77,7 @@ func (b *keyfactorBackend) submitCSR(ctx context.Context, req *logical.Request,
7877
}
7978

8079
// build request parameter structure
81-
var metadataMap map[string]interface{}
80+
metadataMap := make(map[string]interface{})
8281

8382
err = json.Unmarshal([]byte(metaDataJson), &metadataMap)
8483

@@ -95,12 +94,12 @@ func (b *keyfactorBackend) submitCSR(ctx context.Context, req *logical.Request,
9594
Metadata: metadataMap,
9695
Timestamp: &time,
9796
Template: *v1.NewNullableString(&templateName),
98-
//SANs: map[string][]string{},
97+
SANs: make(map[string][]string),
9998
}
10099

101100
// SANs parameter
102-
b.Logger().Debug("ip_sans = %s", ip_sans)
103-
b.Logger().Debug("dns_sans = %s", dns_sans)
101+
b.Logger().Debug(fmt.Sprintf("ip_sans = %s", ip_sans))
102+
b.Logger().Debug(fmt.Sprintf("dns_sans = %s", dns_sans))
104103

105104
if len(ip_sans) > 0 {
106105
enrollmentRequest.SANs["ip"] = ip_sans
@@ -110,38 +109,43 @@ func (b *keyfactorBackend) submitCSR(ctx context.Context, req *logical.Request,
110109
enrollmentRequest.SANs["dns"] = dns_sans
111110
}
112111

113-
reqMap, _ := enrollmentRequest.ToMap()
112+
reqMap := make(map[string]interface{})
113+
reqMap, err = enrollmentRequest.ToMap()
114114

115-
b.Logger().Debug("request body: %s", reqMap)
115+
if err != nil {
116+
b.Logger().Error(fmt.Sprintf("conversion of paramaters to map failed: %s", err.Error()))
117+
}
118+
119+
b.Logger().Debug(fmt.Sprintf("request body: %s", reqMap))
116120

117121
// Send request and check status
118122

119-
b.Logger().Debug("about to connect to " + config.KeyfactorUrl + " with Keyfactor client for CSR submission")
123+
b.Logger().Debug("setting parameters on the request.. ")
124+
125+
apiRequest := client.V1.EnrollmentApi.NewCreateEnrollmentCSRRequest(ctx).EnrollmentCSREnrollmentRequest(enrollmentRequest).XCertificateformat("PEM")
120126

121-
apiRequest := client.V1.EnrollmentApi.NewCreateEnrollmentCSRRequest(ctx)
122-
apiRequest.XCertificateformat("PEM")
123-
apiRequest.EnrollmentCSREnrollmentRequest(enrollmentRequest)
127+
b.Logger().Debug("about to connect to " + config.KeyfactorUrl + " with Keyfactor client for CSR submission")
124128

125129
resData, httpRes, err := apiRequest.Execute()
126130

127131
if err != nil || httpRes.StatusCode != 200 {
128-
b.Logger().Error("there was an error performing CSR enrollment. HttpStatusCode: %d, error: %s", httpRes.StatusCode, err)
132+
b.Logger().Error(fmt.Sprintf("there was an error performing CSR enrollment. HttpStatusCode: %d, error: %s", httpRes.StatusCode, err))
129133
return nil, "", err
130134
}
131135

132136
// Read certificates from response
133137
certs, ok := resData.CertificateInformation.GetCertificatesOk()
134138

135139
if !ok {
136-
b.Logger().Error("unable to read certificate response : %s", err)
140+
b.Logger().Error(fmt.Sprintf("unable to read certificate response : %s", err))
137141
return nil, "", err
138142
}
139143

140144
serial := resData.CertificateInformation.SerialNumber
141145
kfId := resData.CertificateInformation.KeyfactorID
142146

143147
resMap, _ := resData.ToMap()
144-
b.Logger().Debug("full response: %s", resMap)
148+
b.Logger().Debug(fmt.Sprintf("full response: %s", resMap))
145149

146150
// store the ca chain
147151

@@ -170,7 +174,7 @@ func (b *keyfactorBackend) submitCSR(ctx context.Context, req *logical.Request,
170174

171175
err = req.Storage.Put(ctx, entry)
172176
if err != nil {
173-
return nil, "", errwrap.Wrapf("unable to store certificate locally: {{err}}", err)
177+
return nil, "", fmt.Errorf("unable to store certificate locally: {{err}}", err)
174178
}
175179

176180
kfIdEntry, err := logical.StorageEntryJSON("kfId/"+normalizedSerial, kfId)
@@ -180,7 +184,7 @@ func (b *keyfactorBackend) submitCSR(ctx context.Context, req *logical.Request,
180184

181185
err = req.Storage.Put(ctx, kfIdEntry)
182186
if err != nil {
183-
return nil, "", errwrap.Wrapf("unable to store the keyfactor ID for the certificate locally: {{err}}", err)
187+
return nil, "", fmt.Errorf("unable to store the keyfactor ID for the certificate locally: {{err}}", err)
184188
}
185189

186190
return certs, normalizedSerial, nil
@@ -203,7 +207,7 @@ func fetchCAInfo(ctx context.Context, req *logical.Request, b *keyfactorBackend,
203207
if includeChain {
204208
storagePath = fmt.Sprintf("%s_chain", storagePath) // the storage path for the ca chain is "ca/{{ca name}}_chain"
205209
}
206-
b.Logger().Debug("local storage path = %s", storagePath)
210+
b.Logger().Debug(fmt.Sprintf("local storage path = %s", storagePath))
207211

208212
caEntry, err := req.Storage.Get(ctx, storagePath)
209213

@@ -546,67 +550,67 @@ func ConvertBase64P7BtoPEM(base64P7B string) ([]string, error) {
546550
return pemEncodedCerts, nil
547551
}
548552

549-
type KeyfactorCertResponse []struct {
550-
ID int `json:"Id"`
551-
Thumbprint string `json:"Thumbprint"`
552-
SerialNumber string `json:"SerialNumber"`
553-
IssuedDN string `json:"IssuedDN"`
554-
IssuedCN string `json:"IssuedCN"`
555-
ImportDate time.Time `json:"ImportDate"`
556-
NotBefore time.Time `json:"NotBefore"`
557-
NotAfter time.Time `json:"NotAfter"`
558-
IssuerDN string `json:"IssuerDN"`
559-
PrincipalID interface{} `json:"PrincipalId"`
560-
TemplateID interface{} `json:"TemplateId"`
561-
CertState int `json:"CertState"`
562-
KeySizeInBits int `json:"KeySizeInBits"`
563-
KeyType int `json:"KeyType"`
564-
RequesterID int `json:"RequesterId"`
565-
IssuedOU interface{} `json:"IssuedOU"`
566-
IssuedEmail interface{} `json:"IssuedEmail"`
567-
KeyUsage int `json:"KeyUsage"`
568-
SigningAlgorithm string `json:"SigningAlgorithm"`
569-
CertStateString string `json:"CertStateString"`
570-
KeyTypeString string `json:"KeyTypeString"`
571-
RevocationEffDate interface{} `json:"RevocationEffDate"`
572-
RevocationReason interface{} `json:"RevocationReason"`
573-
RevocationComment interface{} `json:"RevocationComment"`
574-
CertificateAuthorityID int `json:"CertificateAuthorityId"`
575-
CertificateAuthorityName string `json:"CertificateAuthorityName"`
576-
TemplateName interface{} `json:"TemplateName"`
577-
ArchivedKey bool `json:"ArchivedKey"`
578-
HasPrivateKey bool `json:"HasPrivateKey"`
579-
PrincipalName interface{} `json:"PrincipalName"`
580-
CertRequestID interface{} `json:"CertRequestId"`
581-
RequesterName string `json:"RequesterName"`
582-
ContentBytes string `json:"ContentBytes"`
583-
ExtendedKeyUsages []interface{} `json:"ExtendedKeyUsages"`
584-
SubjectAltNameElements []interface{} `json:"SubjectAltNameElements"`
585-
CRLDistributionPoints []interface{} `json:"CRLDistributionPoints"`
586-
LocationsCount []interface{} `json:"LocationsCount"`
587-
SSLLocations []interface{} `json:"SSLLocations"`
588-
Locations []interface{} `json:"Locations"`
589-
Metadata Metadata `json:"Metadata"`
590-
CertificateKeyID int `json:"CertificateKeyId"`
591-
CARowIndex int `json:"CARowIndex"`
592-
DetailedKeyUsage DetailedKeyUsage `json:"DetailedKeyUsage"`
593-
KeyRecoverable bool `json:"KeyRecoverable"`
594-
}
595-
type Metadata struct {
596-
}
597-
type DetailedKeyUsage struct {
598-
CrlSign bool `json:"CrlSign"`
599-
DataEncipherment bool `json:"DataEncipherment"`
600-
DecipherOnly bool `json:"DecipherOnly"`
601-
DigitalSignature bool `json:"DigitalSignature"`
602-
EncipherOnly bool `json:"EncipherOnly"`
603-
KeyAgreement bool `json:"KeyAgreement"`
604-
KeyCertSign bool `json:"KeyCertSign"`
605-
KeyEncipherment bool `json:"KeyEncipherment"`
606-
NonRepudiation bool `json:"NonRepudiation"`
607-
HexCode string `json:"HexCode"`
608-
}
609-
610-
type KeyfactorCertDownloadResponse struct {
611-
Content string `json:"Content"`
612-
}
553+
// type KeyfactorCertResponse []struct {
554+
// ID int `json:"Id"`
555+
// Thumbprint string `json:"Thumbprint"`
556+
// SerialNumber string `json:"SerialNumber"`
557+
// IssuedDN string `json:"IssuedDN"`
558+
// IssuedCN string `json:"IssuedCN"`
559+
// ImportDate time.Time `json:"ImportDate"`
560+
// NotBefore time.Time `json:"NotBefore"`
561+
// NotAfter time.Time `json:"NotAfter"`
562+
// IssuerDN string `json:"IssuerDN"`
563+
// PrincipalID interface{} `json:"PrincipalId"`
564+
// TemplateID interface{} `json:"TemplateId"`
565+
// CertState int `json:"CertState"`
566+
// KeySizeInBits int `json:"KeySizeInBits"`
567+
// KeyType int `json:"KeyType"`
568+
// RequesterID int `json:"RequesterId"`
569+
// IssuedOU interface{} `json:"IssuedOU"`
570+
// IssuedEmail interface{} `json:"IssuedEmail"`
571+
// KeyUsage int `json:"KeyUsage"`
572+
// SigningAlgorithm string `json:"SigningAlgorithm"`
573+
// CertStateString string `json:"CertStateString"`
574+
// KeyTypeString string `json:"KeyTypeString"`
575+
// RevocationEffDate interface{} `json:"RevocationEffDate"`
576+
// RevocationReason interface{} `json:"RevocationReason"`
577+
// RevocationComment interface{} `json:"RevocationComment"`
578+
// CertificateAuthorityID int `json:"CertificateAuthorityId"`
579+
// CertificateAuthorityName string `json:"CertificateAuthorityName"`
580+
// TemplateName interface{} `json:"TemplateName"`
581+
// ArchivedKey bool `json:"ArchivedKey"`
582+
// HasPrivateKey bool `json:"HasPrivateKey"`
583+
// PrincipalName interface{} `json:"PrincipalName"`
584+
// CertRequestID interface{} `json:"CertRequestId"`
585+
// RequesterName string `json:"RequesterName"`
586+
// ContentBytes string `json:"ContentBytes"`
587+
// ExtendedKeyUsages []interface{} `json:"ExtendedKeyUsages"`
588+
// SubjectAltNameElements []interface{} `json:"SubjectAltNameElements"`
589+
// CRLDistributionPoints []interface{} `json:"CRLDistributionPoints"`
590+
// LocationsCount []interface{} `json:"LocationsCount"`
591+
// SSLLocations []interface{} `json:"SSLLocations"`
592+
// Locations []interface{} `json:"Locations"`
593+
// Metadata Metadata `json:"Metadata"`
594+
// CertificateKeyID int `json:"CertificateKeyId"`
595+
// CARowIndex int `json:"CARowIndex"`
596+
// DetailedKeyUsage DetailedKeyUsage `json:"DetailedKeyUsage"`
597+
// KeyRecoverable bool `json:"KeyRecoverable"`
598+
// }
599+
// type Metadata struct {
600+
// }
601+
// type DetailedKeyUsage struct {
602+
// CrlSign bool `json:"CrlSign"`
603+
// DataEncipherment bool `json:"DataEncipherment"`
604+
// DecipherOnly bool `json:"DecipherOnly"`
605+
// DigitalSignature bool `json:"DigitalSignature"`
606+
// EncipherOnly bool `json:"EncipherOnly"`
607+
// KeyAgreement bool `json:"KeyAgreement"`
608+
// KeyCertSign bool `json:"KeyCertSign"`
609+
// KeyEncipherment bool `json:"KeyEncipherment"`
610+
// NonRepudiation bool `json:"NonRepudiation"`
611+
// HexCode string `json:"HexCode"`
612+
// }
613+
614+
// type KeyfactorCertDownloadResponse struct {
615+
// Content string `json:"Content"`
616+
// }

cmd/keyfactor/main.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,11 @@ func main() {
2626
tlsConfig := apiClientMeta.GetTLSConfig()
2727
tlsProviderFunc := api.VaultPluginTLSProvider(tlsConfig)
2828

29-
if err := plugin.Serve(&plugin.ServeOpts{
29+
err := plugin.ServeMultiplex(&plugin.ServeOpts{
3030
BackendFactoryFunc: kfbackend.Factory,
3131
TLSProviderFunc: tlsProviderFunc,
32-
}); err != nil {
32+
})
33+
if err != nil {
3334
logger := hclog.New(&hclog.LoggerOptions{})
3435
logger.Error("plugin shutting down", "error", err)
3536
os.Exit(1)

fields.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ request`,
4545
Type: framework.TypeString,
4646
Description: `The requested common name; if you want more than
4747
one, specify the alternative names in the
48-
alt_names map. If email protection is enabled
48+
dns_sans. If email protection is enabled
4949
in the role, this may be an email address.`,
5050
Required: true,
5151
}

0 commit comments

Comments
 (0)