-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Kitography/vault 5474 rebase (#15150)
* These parts work (put in signature so that backend wouldn't break, but missing fields, desc, etc.) * Import and Generate API calls w/ needed additions to SDK. * make fmt * Add Help/Sync Text, fix some of internal/exported/kms code. * Fix PEM/DER Encoding issue. * make fmt * Standardize keyIdParam, keyNameParam, keyTypeParam * Add error response if key to be deleted is in use. * replaces all instances of "default" in code with defaultRef * Updates from Callbacks to Operations Function with explicit forwarding. * Fixes a panic with names not being updated everywhere. * add a logged error in addition to warning on deleting default key. * Normalize whitespace upon importing keys. Authored-by: Alexander Scheel <alexander.m.scheel@gmail.com> * Fix isKeyInUse functionality. * Fixes tests associated with newline at end of key pem.
- Loading branch information
1 parent
1b53ccd
commit c57c1ab
Showing
12 changed files
with
568 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,227 @@ | ||
package pki | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
"github.com/hashicorp/vault/sdk/framework" | ||
"github.com/hashicorp/vault/sdk/logical" | ||
) | ||
|
||
func pathListKeys(b *backend) *framework.Path { | ||
return &framework.Path{ | ||
Pattern: "keys/?$", | ||
|
||
Operations: map[logical.Operation]framework.OperationHandler{ | ||
logical.ListOperation: &framework.PathOperation{ | ||
Callback: b.pathListKeysHandler, | ||
ForwardPerformanceStandby: false, | ||
ForwardPerformanceSecondary: false, | ||
}, | ||
}, | ||
|
||
HelpSynopsis: pathListKeysHelpSyn, | ||
HelpDescription: pathListKeysHelpDesc, | ||
} | ||
} | ||
|
||
const ( | ||
pathListKeysHelpSyn = `Fetch a list of all issuer keys` | ||
pathListKeysHelpDesc = `This endpoint allows listing of known backing keys, returning | ||
their identifier and their name (if set).` | ||
) | ||
|
||
func (b *backend) pathListKeysHandler(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) { | ||
var responseKeys []string | ||
responseInfo := make(map[string]interface{}) | ||
|
||
entries, err := listKeys(ctx, req.Storage) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
for _, identifier := range entries { | ||
key, err := fetchKeyById(ctx, req.Storage, identifier) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
responseKeys = append(responseKeys, string(identifier)) | ||
responseInfo[string(identifier)] = map[string]interface{}{ | ||
keyNameParam: key.Name, | ||
} | ||
|
||
} | ||
return logical.ListResponseWithInfo(responseKeys, responseInfo), nil | ||
} | ||
|
||
func pathKey(b *backend) *framework.Path { | ||
pattern := "key/" + framework.GenericNameRegex(keyRefParam) | ||
return buildPathKey(b, pattern) | ||
} | ||
|
||
func buildPathKey(b *backend, pattern string) *framework.Path { | ||
return &framework.Path{ | ||
Pattern: pattern, | ||
|
||
Fields: map[string]*framework.FieldSchema{ | ||
keyRefParam: { | ||
Type: framework.TypeString, | ||
Description: `Reference to key; either "default" for the configured default key, an identifier of a key, or the name assigned to the key.`, | ||
Default: defaultRef, | ||
}, | ||
keyNameParam: { | ||
Type: framework.TypeString, | ||
Description: `Human-readable name for this key.`, | ||
}, | ||
}, | ||
|
||
Operations: map[logical.Operation]framework.OperationHandler{ | ||
logical.ReadOperation: &framework.PathOperation{ | ||
Callback: b.pathGetKeyHandler, | ||
ForwardPerformanceStandby: false, | ||
ForwardPerformanceSecondary: false, | ||
}, | ||
logical.UpdateOperation: &framework.PathOperation{ | ||
Callback: b.pathUpdateKeyHandler, | ||
ForwardPerformanceStandby: true, | ||
ForwardPerformanceSecondary: true, | ||
}, | ||
logical.DeleteOperation: &framework.PathOperation{ | ||
Callback: b.pathDeleteKeyHandler, | ||
ForwardPerformanceStandby: true, | ||
ForwardPerformanceSecondary: true, | ||
}, | ||
}, | ||
|
||
HelpSynopsis: pathKeysHelpSyn, | ||
HelpDescription: pathKeysHelpDesc, | ||
} | ||
} | ||
|
||
const ( | ||
pathKeysHelpSyn = `Fetch a single issuer key` | ||
pathKeysHelpDesc = `This allows fetching information associated with the underlying key. | ||
:ref can be either the literal value "default", in which case /config/keys | ||
will be consulted for the present default key, an identifier of a key, | ||
or its assigned name value. | ||
Writing to /key/:ref allows updating of the name field associated with | ||
the certificate. | ||
` | ||
) | ||
|
||
func (b *backend) pathGetKeyHandler(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) { | ||
keyRef := data.Get(keyRefParam).(string) | ||
if len(keyRef) == 0 { | ||
return logical.ErrorResponse("missing key reference"), nil | ||
} | ||
|
||
keyId, err := resolveKeyReference(ctx, req.Storage, keyRef) | ||
if err != nil { | ||
return nil, err | ||
} | ||
if keyId == "" { | ||
return logical.ErrorResponse("unable to resolve key id for reference" + keyRef), nil | ||
} | ||
|
||
key, err := fetchKeyById(ctx, req.Storage, keyId) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return &logical.Response{ | ||
Data: map[string]interface{}{ | ||
keyIdParam: key.ID, | ||
keyNameParam: key.Name, | ||
keyTypeParam: key.PrivateKeyType, | ||
}, | ||
}, nil | ||
} | ||
|
||
func (b *backend) pathUpdateKeyHandler(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) { | ||
keyRef := data.Get(keyRefParam).(string) | ||
if len(keyRef) == 0 { | ||
return logical.ErrorResponse("missing key reference"), nil | ||
} | ||
|
||
keyId, err := resolveKeyReference(ctx, req.Storage, keyRef) | ||
if err != nil { | ||
return nil, err | ||
} | ||
if keyId == "" { | ||
return logical.ErrorResponse("unable to resolve key id for reference" + keyRef), nil | ||
} | ||
|
||
key, err := fetchKeyById(ctx, req.Storage, keyId) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
newName := data.Get(keyNameParam).(string) | ||
if len(newName) > 0 && !nameMatcher.MatchString(newName) { | ||
return logical.ErrorResponse("new key name outside of valid character limits"), nil | ||
} | ||
|
||
if newName != key.Name { | ||
key.Name = newName | ||
|
||
err := writeKey(ctx, req.Storage, *key) | ||
if err != nil { | ||
return nil, err | ||
} | ||
} | ||
|
||
resp := &logical.Response{ | ||
Data: map[string]interface{}{ | ||
keyIdParam: key.ID, | ||
keyNameParam: key.Name, | ||
keyTypeParam: key.PrivateKeyType, | ||
}, | ||
} | ||
|
||
if len(newName) == 0 { | ||
resp.AddWarning("Name successfully deleted, you will now need to reference this key by it's Id: " + string(key.ID)) | ||
} | ||
|
||
return resp, nil | ||
} | ||
|
||
func (b *backend) pathDeleteKeyHandler(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) { | ||
keyRef := data.Get(keyRefParam).(string) | ||
if len(keyRef) == 0 { | ||
return logical.ErrorResponse("missing key reference"), nil | ||
} | ||
|
||
keyId, err := resolveKeyReference(ctx, req.Storage, keyRef) | ||
if err != nil { | ||
return nil, err | ||
} | ||
if keyId == "" { | ||
return logical.ErrorResponse("unable to resolve key id for reference" + keyRef), nil | ||
} | ||
|
||
keyInUse, issuerId, err := isKeyInUse(keyId.String(), ctx, req.Storage) | ||
if err != nil { | ||
return nil, err | ||
} | ||
if keyInUse { | ||
return logical.ErrorResponse(fmt.Sprintf("Failed to Delete Key. Key in Use by Issuer: %s", issuerId)), nil | ||
} | ||
|
||
wasDefault, err := deleteKey(ctx, req.Storage, keyId) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
var response *logical.Response | ||
if wasDefault { | ||
msg := fmt.Sprintf("Deleted key %v (via key_ref %v); this was configured as the default key. Operations without an explicit key will not work until a new default is configured.", string(keyId), keyRef) | ||
b.Logger().Error(msg) | ||
response = &logical.Response{} | ||
response.AddWarning(msg) | ||
} | ||
|
||
return response, nil | ||
} |
Oops, something went wrong.