Skip to content

Commit 88349e2

Browse files
committed
chore(status): Ensure that status is properly progogated in the /role path
Signed-off-by: Hayden Roszell <hroszell@gmail.com>
1 parent 00a9e43 commit 88349e2

6 files changed

Lines changed: 53 additions & 28 deletions

File tree

CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
# v1.5.0
2+
## Fixes
3+
* Patched bug that required the `allow_any_name` or `allowed_domains=[""]` role parameters to issue/sign certificates with no CN.
4+
5+
## Chores
6+
* Upgrade from Go `v1.21` to `v1.22`.
7+
* Implement more strict golangci-lint policy.
8+
9+
## Features
10+
* If upstream EJBCA API call fails, the HTTP status code is propogated to the Vault user via the Vault API status code.
11+
* Implement OAuth 2.0 "client credentials" token flow as a supported authentication mechanism to EJBCA.
12+
113
# v1.4.0
214
## Fixes
315
* Paths that need to write to the Storage backend now forward the request to the primary node. This is important in Enterprise HA deployments where Performance Standby Nodes are allowed to handle read requests/paths.

backend_test.go

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ package ejbca
1818

1919
import (
2020
"context"
21-
"encoding/json"
2221
"os"
2322
"testing"
2423

@@ -77,28 +76,3 @@ func getTestBackend(tb testing.TB) (*ejbcaBackend, logical.Storage) {
7776

7877
return b.(*ejbcaBackend), config.StorageView
7978
}
80-
81-
func logicalResponseIsEjbcaError(resp *logical.Response) bool {
82-
if resp == nil {
83-
return false
84-
}
85-
if contentType, ok := resp.Data[logical.HTTPContentType].(string); !ok || contentType != "application/json" {
86-
return false
87-
}
88-
if rawBody, ok := resp.Data[logical.HTTPRawBody].(string); !ok || rawBody == "" {
89-
return false
90-
}
91-
if _, ok := resp.Data[logical.HTTPStatusCode].(int); !ok {
92-
return false
93-
}
94-
95-
err := json.Unmarshal([]byte(resp.Data[logical.HTTPRawBody].(string)), &resp.Data)
96-
if err != nil {
97-
return false
98-
}
99-
if _, ok := resp.Data["errors"]; !ok {
100-
return false
101-
}
102-
103-
return true
104-
}

ca_utils.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ func (c *caStorageContext) resolveIssuerReference(caName string) error {
7171
}
7272
}
7373

74-
return fmt.Errorf("CA %s not found", caName)
74+
return errutil.UserError{Err: fmt.Sprintf("Could not find CA called %s in connected EJBCA - please make sure that it exists and that your credentials have the proper permissions.", caName)}
7575
}
7676

7777
func (c *caStorageContext) putCaEntry(caName string, entry caEntry) error {
@@ -361,10 +361,12 @@ func (b *caResponseBuilder) Build() (*logical.Response, error) {
361361
if err != nil {
362362
var userError errutil.UserError
363363
if errors.As(err, &userError) {
364+
logger.Trace("fetchCaBundle failed as UserError - returning logical ErrorResponse")
364365
return logical.ErrorResponse(err.Error()), nil
365366
}
366367
var ejbcaError ejbcaAPIError
367368
if errors.As(err, &ejbcaError) {
369+
logger.Trace("fetchCaBundle failed as ejbcaAPIError - returning logical raw response with status", "code", ejbcaError.Code)
368370
return ejbcaError.ToLogicalResponse()
369371
}
370372
// Only return error if path is JSON response.

client.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,31 @@ func (e ejbcaAPIError) ToLogicalResponse() (*logical.Response, error) {
6767
return response, err
6868
}
6969

70+
func logicalResponseIsEjbcaError(resp *logical.Response) bool {
71+
if resp == nil {
72+
return false
73+
}
74+
if contentType, ok := resp.Data[logical.HTTPContentType].(string); !ok || contentType != "application/json" {
75+
return false
76+
}
77+
if rawBody, ok := resp.Data[logical.HTTPRawBody].(string); !ok || rawBody == "" {
78+
return false
79+
}
80+
if _, ok := resp.Data[logical.HTTPStatusCode].(int); !ok {
81+
return false
82+
}
83+
84+
err := json.Unmarshal([]byte(resp.Data[logical.HTTPRawBody].(string)), &resp.Data)
85+
if err != nil {
86+
return false
87+
}
88+
if _, ok := resp.Data["errors"]; !ok {
89+
return false
90+
}
91+
92+
return true
93+
}
94+
7095
func (e *ejbcaClient) EjbcaAPIError(b *ejbcaBackend, detail string, err error) error {
7196
logger := b.Logger().Named("ejbcaClient.createErrorFromEjbcaErr")
7297
if err == nil {

path_role.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package ejbca
1919
import (
2020
"context"
2121
"encoding/json"
22+
"errors"
2223
"fmt"
2324
"net/http"
2425
"strings"
@@ -1098,6 +1099,15 @@ func (b *ejbcaBackend) pathRoleCreate(ctx context.Context, req *logical.Request,
10981099
logger.Debug("Validating role entry before storing", "entry", entry)
10991100
resp, err := entry.validate(b.makeStorageContext(ctx, req.Storage))
11001101
if err != nil {
1102+
var userError errutil.UserError
1103+
if errors.As(err, &userError) {
1104+
return logical.ErrorResponse(err.Error()), nil
1105+
}
1106+
var ejbcaError ejbcaAPIError
1107+
if errors.As(err, &ejbcaError) {
1108+
return ejbcaError.ToLogicalResponse()
1109+
}
1110+
11011111
return nil, err
11021112
}
11031113
if warning != "" {
@@ -1392,6 +1402,8 @@ func (r *roleEntry) validate(sc *storageContext) (*logical.Response, error) {
13921402
r.EndEntityName = config.DefaultEndEntityName
13931403
}
13941404

1405+
// We expect resolveIssuerReference to return its error as a known type to allow the
1406+
// caller to properly handle it. IE - blindly return err if it's not nil
13951407
err = sc.CA().resolveIssuerReference(r.Issuer)
13961408
if err != nil {
13971409
return nil, err

storage.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ func (c *certStorageContext) listRevokedCerts() ([]string, error) {
274274

275275
list, err := c.storageContext.Storage.List(c.storageContext.Context, revokedPath)
276276
if err != nil {
277-
return nil, fmt.Errorf("failed listing revoked certs: %w", err)
277+
return nil, errutil.InternalError{Err: fmt.Sprintf("failed listing revoked certs: %s", err)}
278278
}
279279

280280
// Normalize serial back to a format people are expecting.

0 commit comments

Comments
 (0)