Skip to content

Commit 97be5b0

Browse files
updated readme, cleanedup logs, completed testing
1 parent 0f7f116 commit 97be5b0

9 files changed

+175
-379
lines changed

backend.go

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ import (
2525
"github.com/hashicorp/vault/sdk/logical"
2626
)
2727

28-
//var config map[string]string
28+
const (
29+
operationPrefixKeyfactor string = "keyfactor"
30+
)
2931

3032
// Factory configures and returns backend
3133
func Factory(ctx context.Context, conf *logical.BackendConfig) (logical.Backend, error) {
@@ -66,9 +68,10 @@ func backend() *keyfactorBackend {
6668
pathCA(&b),
6769
pathCerts(&b),
6870
),
69-
Secrets: []*framework.Secret{},
70-
BackendType: logical.TypeLogical,
71-
Invalidate: b.invalidate,
71+
Secrets: []*framework.Secret{},
72+
BackendType: logical.TypeLogical,
73+
Invalidate: b.invalidate,
74+
InitializeFunc: b.Initialize,
7275
}
7376
return &b
7477
}
@@ -83,6 +86,15 @@ func (b *keyfactorBackend) reset() {
8386

8487
}
8588

89+
func (b *keyfactorBackend) Initialize(ctx context.Context, req *logical.InitializationRequest) error {
90+
b.configLock.RLock()
91+
defer b.configLock.RUnlock()
92+
if req == nil {
93+
return fmt.Errorf("initialization request is nil")
94+
}
95+
return nil
96+
}
97+
8698
// invalidate clears an existing client configuration in
8799
// the backend
88100
func (b *keyfactorBackend) invalidate(ctx context.Context, key string) {
@@ -110,7 +122,7 @@ func (b *keyfactorBackend) getClient(ctx context.Context, s logical.Storage) (*k
110122
return nil, errors.New("configuration is empty")
111123
}
112124

113-
b.client, err = newClient(config)
125+
b.client, err = newClient(config, b)
114126
if err != nil {
115127
return nil, err
116128
}
@@ -138,11 +150,11 @@ func (b *keyfactorBackend) submitCSR(ctx context.Context, req *logical.Request,
138150
}
139151

140152
b.Logger().Debug("Closing idle connections")
141-
b.client.httpClient.CloseIdleConnections()
153+
client.httpClient.CloseIdleConnections()
142154

143155
// build request parameter structure
144156

145-
url := config.KeyfactorUrl + "/KeyfactorAPI/Enrollment/CSR"
157+
url := config.KeyfactorUrl + "/" + config.CommandAPIPath + "/Enrollment/CSR"
146158
b.Logger().Debug("url: " + url)
147159
bodyContent := "{\"CSR\": \"" + csr + "\",\"CertificateAuthority\":\"" + caName + "\",\"IncludeChain\": true, \"Metadata\": {}, \"Timestamp\": \"" + time + "\",\"Template\": \"" + templateName + "\",\"SANs\": {}}"
148160
payload := strings.NewReader(bodyContent)

cert_util.go

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ func getCAId(ctx context.Context, req *logical.Request, b *keyfactorBackend) (st
180180

181181
// Build request
182182

183-
url := config.KeyfactorUrl + "/KeyfactorAPI/Certificates?pq.queryString=CA%20-eq%20%22" + ca_name + "%22%20AND%20CertState%20-eq%20%226%22" // CertState 6 = cert
183+
url := config.KeyfactorUrl + "/" + config.CommandAPIPath + "/Certificates?pq.queryString=CA%20-eq%20%22" + ca_name + "%22%20AND%20CertState%20-eq%20%226%22" // CertState 6 = cert
184184
b.Logger().Debug("url: " + url)
185185
httpReq, err := http.NewRequest("GET", url, nil)
186186
if err != nil {
@@ -256,8 +256,6 @@ func fetchCertFromKeyfactor(ctx context.Context, req *logical.Request, b *keyfac
256256
if config == nil {
257257
return "", errors.New("unable to load configuration")
258258
}
259-
// creds := config.Username + ":" + config.Password
260-
// encCreds := b64.StdEncoding.EncodeToString([]byte(creds))
261259

262260
// get the client
263261
client, err := b.getClient(ctx, req.Storage)
@@ -274,7 +272,7 @@ func fetchCertFromKeyfactor(ctx context.Context, req *logical.Request, b *keyfac
274272
}
275273

276274
// Build request
277-
url := config.KeyfactorUrl + "/KeyfactorAPI/Certificates/Download"
275+
url := config.KeyfactorUrl + "Certificates/Download"
278276
b.Logger().Debug("url: " + url)
279277
bodyContent := fmt.Sprintf(`{"CertID": %s, "IncludeChain": %s }`, kfCertId, include)
280278
payload := strings.NewReader(bodyContent)
@@ -319,7 +317,7 @@ func fetchCertFromKeyfactor(ctx context.Context, req *logical.Request, b *keyfac
319317
}
320318

321319
// Allows fetching certificates from the backend; it handles the slightly
322-
// separate pathing for CA, CRL, and revoked certificates.
320+
// separate pathing for CA and revoked certificates.
323321
func fetchCertBySerial(ctx context.Context, req *logical.Request, prefix, serial string) (*logical.StorageEntry, error) {
324322
var path, legacyPath string
325323
var err error

client.go

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ package kfbackend
1212
import (
1313
"errors"
1414
"fmt"
15-
"log"
1615
"net/http"
1716

1817
"github.com/Keyfactor/keyfactor-auth-client-go/auth_providers"
@@ -22,7 +21,7 @@ type keyfactorClient struct {
2221
httpClient *http.Client
2322
}
2423

25-
func newClient(config *keyfactorConfig) (*keyfactorClient, error) {
24+
func newClient(config *keyfactorConfig, b *keyfactorBackend) (*keyfactorClient, error) {
2625
client := new(keyfactorClient)
2726

2827
if config == nil {
@@ -49,6 +48,8 @@ func newClient(config *keyfactorConfig) (*keyfactorClient, error) {
4948
basicAuthConfig := &auth_providers.CommandAuthConfigBasic{}
5049

5150
if isBasicAuth {
51+
b.Logger().Debug(fmt.Sprintf("using basic auth with username %s, domain %s and password (hidden)", config.Username, config.Domain))
52+
5253
basicAuthConfig.WithCommandHostName(hostname).
5354
WithCommandAPIPath(config.CommandAPIPath).
5455
WithSkipVerify(config.SkipTLSVerify).
@@ -61,20 +62,22 @@ func newClient(config *keyfactorConfig) (*keyfactorClient, error) {
6162

6263
if bErr != nil {
6364
errMsg := fmt.Sprintf("[ERROR] unable to authenticate with provided basic auth credentials: %s", bErr.Error())
64-
log.Fatal(errMsg)
65+
b.Logger().Error(errMsg)
6566
return nil, bErr
67+
} else {
68+
b.Logger().Debug("successfully authenticated using basic auth")
6669
}
6770

6871
client.httpClient, bErr = basicAuthConfig.GetHttpClient()
6972

7073
if bErr != nil {
7174
errMsg := fmt.Sprintf("[ERROR] there was an error retreiving the basic auth http client: %s", bErr.Error())
72-
log.Fatal(errMsg)
75+
b.Logger().Error(errMsg)
7376
return nil, bErr
7477
}
7578

7679
} else if isOAuth {
77-
80+
b.Logger().Debug(fmt.Sprintf("using oAuth authentication with client_id: %s, token_url %s and client_secret: (hidden)", config.ClientId, config.TokenUrl))
7881
_ = oAuthConfig.WithCommandHostName(hostname).
7982
WithCommandAPIPath(config.CommandAPIPath).
8083
WithSkipVerify(config.SkipTLSVerify).
@@ -89,14 +92,14 @@ func newClient(config *keyfactorConfig) (*keyfactorClient, error) {
8992

9093
if oErr != nil {
9194
errMsg := fmt.Sprintf("[ERROR] unable to authenticate with provided oAuth credentials: %s", oErr.Error())
92-
log.Fatal(errMsg)
95+
b.Logger().Error(errMsg)
9396
return nil, oErr
9497
}
9598

9699
client.httpClient, oErr = oAuthConfig.GetHttpClient()
97100
if oErr != nil {
98101
errMsg := fmt.Sprintf("[ERROR] there was an error retreiving the oAuth http client: %s", oErr.Error())
99-
log.Fatal(errMsg)
102+
b.Logger().Error(errMsg)
100103
return nil, oErr
101104
}
102105
}

fields.go

Lines changed: 0 additions & 161 deletions
Original file line numberDiff line numberDiff line change
@@ -79,167 +79,6 @@ be larger than the role max TTL.`,
7979
return fields
8080
}
8181

82-
// addCACommonFields adds fields with help text specific to CA
83-
// certificate issuing and signing
84-
// func addCACommonFields(fields map[string]*framework.FieldSchema) map[string]*framework.FieldSchema {
85-
// fields = addIssueAndSignCommonFields(fields)
86-
87-
// fields["alt_names"] = &framework.FieldSchema{
88-
// Type: framework.TypeString,
89-
// Description: `The requested Subject Alternative Names, if any,
90-
// in a comma-delimited list. May contain both
91-
// DNS names and email addresses.`,
92-
// DisplayAttrs: &framework.DisplayAttributes{
93-
// Name: "DNS/Email Subject Alternative Names (SANs)",
94-
// },
95-
// }
96-
97-
// fields["common_name"] = &framework.FieldSchema{
98-
// Type: framework.TypeString,
99-
// Description: `The requested common name; if you want more than
100-
// one, specify the alternative names in the alt_names
101-
// map. If not specified when signing, the common
102-
// name will be taken from the CSR; other names
103-
// must still be specified in alt_names or ip_sans.`,
104-
// }
105-
106-
// fields["ttl"] = &framework.FieldSchema{
107-
// Type: framework.TypeDurationSecond,
108-
// Description: `The requested Time To Live for the certificate;
109-
// sets the expiration date. If not specified
110-
// the role default, backend default, or system
111-
// default TTL is used, in that order. Cannot
112-
// be larger than the mount max TTL. Note:
113-
// this only has an effect when generating
114-
// a CA cert or signing a CA cert, not when
115-
// generating a CSR for an intermediate CA.`,
116-
// DisplayAttrs: &framework.DisplayAttributes{
117-
// Name: "TTL",
118-
// },
119-
// }
120-
121-
// fields["ou"] = &framework.FieldSchema{
122-
// Type: framework.TypeCommaStringSlice,
123-
// Description: `If set, OU (OrganizationalUnit) will be set to
124-
// this value.`,
125-
// DisplayAttrs: &framework.DisplayAttributes{
126-
// Name: "OU (Organizational Unit)",
127-
// },
128-
// }
129-
130-
// fields["organization"] = &framework.FieldSchema{
131-
// Type: framework.TypeCommaStringSlice,
132-
// Description: `If set, O (Organization) will be set to
133-
// this value.`,
134-
// }
135-
136-
// fields["country"] = &framework.FieldSchema{
137-
// Type: framework.TypeCommaStringSlice,
138-
// Description: `If set, Country will be set to
139-
// this value.`,
140-
// }
141-
142-
// fields["locality"] = &framework.FieldSchema{
143-
// Type: framework.TypeCommaStringSlice,
144-
// Description: `If set, Locality will be set to
145-
// this value.`,
146-
// DisplayAttrs: &framework.DisplayAttributes{
147-
// Name: "Locality/City",
148-
// },
149-
// }
150-
151-
// fields["province"] = &framework.FieldSchema{
152-
// Type: framework.TypeCommaStringSlice,
153-
// Description: `If set, Province will be set to
154-
// this value.`,
155-
// DisplayAttrs: &framework.DisplayAttributes{
156-
// Name: "Province/State",
157-
// },
158-
// }
159-
160-
// fields["street_address"] = &framework.FieldSchema{
161-
// Type: framework.TypeCommaStringSlice,
162-
// Description: `If set, Street Address will be set to
163-
// this value.`,
164-
// DisplayAttrs: &framework.DisplayAttributes{
165-
// Name: "Street Address",
166-
// },
167-
// }
168-
169-
// fields["postal_code"] = &framework.FieldSchema{
170-
// Type: framework.TypeCommaStringSlice,
171-
// Description: `If set, Postal Code will be set to
172-
// this value.`,
173-
// DisplayAttrs: &framework.DisplayAttributes{
174-
// Name: "Postal Code",
175-
// },
176-
// }
177-
178-
// fields["serial_number"] = &framework.FieldSchema{
179-
// Type: framework.TypeString,
180-
// Description: `The requested serial number, if any. If you want
181-
// more than one, specify alternative names in
182-
// the alt_names map using OID 2.5.4.5.`,
183-
// }
184-
185-
// return fields
186-
// }
187-
188-
// // addCAKeyGenerationFields adds fields with help text specific to CA key
189-
// // generation and exporting
190-
// func addCAKeyGenerationFields(fields map[string]*framework.FieldSchema) map[string]*framework.FieldSchema {
191-
// fields["exported"] = &framework.FieldSchema{
192-
// Type: framework.TypeString,
193-
// Description: `Must be "internal" or "exported". If set to
194-
// "exported", the generated private key will be
195-
// returned. This is your *only* chance to retrieve
196-
// the private key!`,
197-
// }
198-
199-
// fields["key_bits"] = &framework.FieldSchema{
200-
// Type: framework.TypeInt,
201-
// Default: 2048,
202-
// Description: `The number of bits to use. You will almost
203-
// certainly want to change this if you adjust
204-
// the key_type.`,
205-
// DisplayAttrs: &framework.DisplayAttributes{
206-
// Value: 2048,
207-
// },
208-
// }
209-
210-
// fields["key_type"] = &framework.FieldSchema{
211-
// Type: framework.TypeString,
212-
// Default: "rsa",
213-
// Description: `The type of key to use; defaults to RSA. "rsa"
214-
// and "ec" are the only valid values.`,
215-
// AllowedValues: []interface{}{"rsa", "ec"},
216-
// DisplayAttrs: &framework.DisplayAttributes{
217-
// Value: "rsa",
218-
// },
219-
// }
220-
// return fields
221-
// }
222-
223-
// addCAIssueFields adds fields common to CA issuing, e.g. when returning
224-
// an actual certificate
225-
// func addCAIssueFields(fields map[string]*framework.FieldSchema) map[string]*framework.FieldSchema {
226-
// fields["max_path_length"] = &framework.FieldSchema{
227-
// Type: framework.TypeInt,
228-
// Default: -1,
229-
// Description: "The maximum allowable path length",
230-
// }
231-
232-
// fields["permitted_dns_domains"] = &framework.FieldSchema{
233-
// Type: framework.TypeCommaStringSlice,
234-
// Description: `Domains for which this certificate is allowed to sign or issue child certificates. If set, all DNS names (subject and alt) on child certs must be exact matches or subsets of the given domains (see https://tools.ietf.org/html/rfc5280#section-4.2.1.10).`,
235-
// DisplayAttrs: &framework.DisplayAttributes{
236-
// Name: "Permitted DNS Domains",
237-
// },
238-
// }
239-
240-
// return fields
241-
// }
242-
24382
func addRoleFields(fields map[string]*framework.FieldSchema) map[string]*framework.FieldSchema {
24483

24584
fields["name"] = &framework.FieldSchema{

images/configread.png

13.7 KB
Loading

path_ca.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,6 @@ func (b *keyfactorBackend) pathFetchCa(ctx context.Context, req *logical.Request
6363
serial = "ca"
6464
}
6565

66-
if len(serial) == 0 {
67-
response = logical.ErrorResponse("The serial number must be provided")
68-
}
69-
7066
if serial == "ca" {
7167
return fetchCAInfo(ctx, req, b)
7268
}

0 commit comments

Comments
 (0)