Skip to content

Commit

Permalink
Add alternative proposal PKI aliased paths (#15211)
Browse files Browse the repository at this point in the history
* Add aliased path for root/rotate/:exported

This adds a user-friendly path name for generating a rotated root. We
automatically choose the name "next" for the newly generated root at
this path if it doesn't already exist.

Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>

* Add aliased path for intermediate/cross-sign

This allows cross-signatures to work.

Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>

* Add path for replacing the current root

This updates default to point to the value of the issuer with name
"next" rather than its current value.

Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>

* Remove plural issuers/ in signing paths

These paths use a single issuer and thus shouldn't include the plural
issuers/ as a path prefix, instead using the singular issuer/ path
prefix.

Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>

* Only warn if default issuer was imported

When the default issuer was not (re-)imported, we'd fail to find it,
causing an extraneous warning about missing keys, even though this
issuer indeed had a key.

Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>

* Add missing issuer sign/issue paths

Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>
  • Loading branch information
cipherboy committed May 2, 2022
1 parent c57c1ab commit e9abf67
Show file tree
Hide file tree
Showing 8 changed files with 63 additions and 5 deletions.
5 changes: 5 additions & 0 deletions builtin/logical/pki/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,12 +122,17 @@ func Backend(conf *logical.BackendConfig) *backend {
pathGetIssuer(&b),
pathGetIssuerCRL(&b),
pathImportIssuer(&b),
pathIssuerIssue(&b),
pathIssuerSign(&b),
pathIssuerSignIntermediate(&b),
pathIssuerSignSelfIssued(&b),
pathIssuerSignVerbatim(&b),
pathIssuerGenerateRoot(&b),
pathRotateRoot(&b),
pathIssuerGenerateIntermediate(&b),
pathCrossSignIntermediate(&b),
pathConfigIssuers(&b),
pathReplaceRoot(&b),

// Key APIs
pathListKeys(&b),
Expand Down
2 changes: 1 addition & 1 deletion builtin/logical/pki/chain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ func (c CBGenerateIntermediate) Run(t *testing.T, client *api.Client, mount stri
csr := resp.Data["csr"].(string)

// Sign CSR
url = fmt.Sprintf(mount+"/issuers/%s/sign-intermediate", c.Parent)
url = fmt.Sprintf(mount+"/issuer/%s/sign-intermediate", c.Parent)
data = make(map[string]interface{})
data["csr"] = csr
data["common_name"] = c.Name
Expand Down
28 changes: 28 additions & 0 deletions builtin/logical/pki/path_config_ca.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,31 @@ func pathConfigIssuers(b *backend) *framework.Path {
}
}

func pathReplaceRoot(b *backend) *framework.Path {
return &framework.Path{
Pattern: "root/replace",
Fields: map[string]*framework.FieldSchema{
"default": {
Type: framework.TypeString,
Description: `Reference (name or identifier) to the default issuer.`,
Default: "next",
},
},

Operations: map[logical.Operation]framework.OperationHandler{
logical.UpdateOperation: &framework.PathOperation{
Callback: b.pathCAIssuersWrite,
// Read more about why these flags are set in backend.go.
ForwardPerformanceStandby: true,
ForwardPerformanceSecondary: true,
},
},

HelpSynopsis: pathConfigIssuersHelpSyn,
HelpDescription: pathConfigIssuersHelpDesc,
}
}

func (b *backend) pathCAIssuersRead(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
config, err := getIssuersConfig(ctx, req.Storage)
if err != nil {
Expand Down Expand Up @@ -128,6 +153,9 @@ This path allows configuration of issuer parameters.
Presently, the "default" parameter controls which issuer is the default,
accessible by the existing signing paths (/root/sign-intermediate,
/root/sign-self-issued, /sign-verbatim, /sign/:role, and /issue/:role).
The /root/replace path is aliased to this path, with default taking the
value of the issuer with the name "next", if it exists.
`

func pathConfigKeys(b *backend) *framework.Path {
Expand Down
7 changes: 7 additions & 0 deletions builtin/logical/pki/path_intermediate.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,13 @@ func (b *backend) pathGenerateIntermediate(ctx context.Context, req *logical.Req
return logical.ErrorResponse("Can not create intermediate until migration has completed"), nil
}

// Nasty hack :-) For cross-signing, we want to use the existing key, but
// this isn't _actually_ part of the path. Put it into the request
// parameters as if it was.
if req.Path == "intermediate/cross-sign" {
data.Raw["exported"] = "existing"
}

exported, format, role, errorResp := b.getGenerationParams(ctx, data, req.MountPoint)
if errorResp != nil {
return errorResp, nil
Expand Down
2 changes: 1 addition & 1 deletion builtin/logical/pki/path_issue_sign.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ func buildPathSign(b *backend, pattern string) *framework.Path {
}

func pathIssuerSignVerbatim(b *backend) *framework.Path {
pattern := "issuers/" + framework.GenericNameRegex(issuerRefParam) + "/sign-verbatim"
pattern := "issuer/" + framework.GenericNameRegex(issuerRefParam) + "/sign-verbatim"
return buildPathIssuerSignVerbatim(b, pattern)
}

Expand Down
10 changes: 9 additions & 1 deletion builtin/logical/pki/path_manage_issuers.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ func pathIssuerGenerateRoot(b *backend) *framework.Path {
return buildPathGenerateRoot(b, "issuers/generate/root/"+framework.GenericNameRegex("exported"))
}

func pathRotateRoot(b *backend) *framework.Path {
return buildPathGenerateRoot(b, "root/rotate/"+framework.GenericNameRegex("exported"))
}

func buildPathGenerateRoot(b *backend, pattern string) *framework.Path {
ret := &framework.Path{
Pattern: pattern,
Expand Down Expand Up @@ -44,6 +48,10 @@ func pathIssuerGenerateIntermediate(b *backend) *framework.Path {
"issuers/generate/intermediate/"+framework.GenericNameRegex("exported"))
}

func pathCrossSignIntermediate(b *backend) *framework.Path {
return buildPathGenerateIntermediate(b, "intermediate/cross-sign")
}

func buildPathGenerateIntermediate(b *backend, pattern string) *framework.Path {
ret := &framework.Path{
Pattern: pattern,
Expand Down Expand Up @@ -214,7 +222,7 @@ func (b *backend) pathImportIssuers(ctx context.Context, req *logical.Request, d
config, err := getIssuersConfig(ctx, req.Storage)
if err == nil && len(config.DefaultIssuerId) > 0 {
// We can use the mapping above to check the issuer mapping.
if keyId, ok := issuerKeyMap[string(config.DefaultIssuerId)]; !ok || len(keyId) == 0 {
if keyId, ok := issuerKeyMap[string(config.DefaultIssuerId)]; ok && len(keyId) == 0 {
msg := "The default issuer has no key associated with it. Some operations like issuing certificates and signing CRLs will be unavailable with the requested default issuer until a key is imported or the default issuer is changed."
response.AddWarning(msg)
b.Logger().Error(msg)
Expand Down
10 changes: 10 additions & 0 deletions builtin/logical/pki/path_root.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,16 @@ func (b *backend) pathCAGenerateRoot(ctx context.Context, req *logical.Request,
if err != nil {
return logical.ErrorResponse(err.Error()), nil
}
// Handle the aliased path specifying the new issuer name as "next", but
// only do it if its not in use.
if strings.HasPrefix(req.Path, "root/rotate/") && len(issuerName) == 0 {
// err is nil when the issuer name is in use.
_, err = resolveIssuerReference(ctx, req.Storage, "next")
if err != nil {
issuerName = "next"
}
}

keyName, err := getKeyName(ctx, req.Storage, data)
if err != nil {
return logical.ErrorResponse(err.Error()), nil
Expand Down
4 changes: 2 additions & 2 deletions builtin/logical/pki/path_sign_issuers.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
)

func pathIssuerSignIntermediate(b *backend) *framework.Path {
pattern := "issuers/" + framework.GenericNameRegex(issuerRefParam) + "/sign-intermediate"
pattern := "issuer/" + framework.GenericNameRegex(issuerRefParam) + "/sign-intermediate"
return pathIssuerSignIntermediateRaw(b, pattern)
}

Expand Down Expand Up @@ -75,7 +75,7 @@ See the API documentation for more information about required parameters.
)

func pathIssuerSignSelfIssued(b *backend) *framework.Path {
pattern := "issuers/" + framework.GenericNameRegex(issuerRefParam) + "/sign-self-issued"
pattern := "issuer/" + framework.GenericNameRegex(issuerRefParam) + "/sign-self-issued"
return buildPathIssuerSignSelfIssued(b, pattern)
}

Expand Down

0 comments on commit e9abf67

Please sign in to comment.