-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add the ability to rotate the configured API key (#19)
Add a path, config/rotate-root, to allow the rotation the admin API key used by the secret engine. Closes: #12
- Loading branch information
Showing
9 changed files
with
528 additions
and
22 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
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
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,102 @@ | ||
package ibmcloudsecrets | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
|
||
"github.com/hashicorp/vault/sdk/framework" | ||
"github.com/hashicorp/vault/sdk/logical" | ||
) | ||
|
||
func pathConfigRotateRoot(b *ibmCloudSecretBackend) *framework.Path { | ||
return &framework.Path{ | ||
Pattern: "config/rotate-root", | ||
|
||
Operations: map[logical.Operation]framework.OperationHandler{ | ||
logical.UpdateOperation: &framework.PathOperation{ | ||
Callback: b.pathConfigRotateRootWrite, | ||
}, | ||
}, | ||
|
||
HelpSynopsis: pathConfigRotateRootHelpSyn, | ||
HelpDescription: pathConfigRotateRootHelpDesc, | ||
} | ||
} | ||
|
||
func (b *ibmCloudSecretBackend) pathConfigRotateRootWrite(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) { | ||
|
||
config, errResp := b.getConfig(ctx, req.Storage) | ||
if errResp != nil { | ||
return errResp, nil | ||
} | ||
|
||
if config == nil || config.APIKey == "" { | ||
return nil, errors.New("no API key was set in the configuration") | ||
} | ||
|
||
iam, resp := b.getIAMHelper(ctx, req.Storage) | ||
if resp != nil { | ||
b.Logger().Error("failed to retrieve an IAM helper", "error", resp.Error()) | ||
return resp, nil | ||
} | ||
|
||
adminToken, err := b.getAdminToken(ctx, req.Storage) | ||
if err != nil { | ||
b.Logger().Error("error obtaining the token for the configured API key", "error", err) | ||
return nil, err | ||
} | ||
|
||
oldKeyDetails, err := iam.GetAPIKeyDetails(adminToken, config.APIKey) | ||
if err != nil { | ||
b.Logger().Error("error obtaining details about the current API key", "error", err) | ||
return nil, err | ||
} | ||
|
||
// with old key, verify account == acount from the config | ||
keyName := "vault-generated-root-credential" | ||
keyDescription := "Generated by Vault's secret engine for IBM Cloud credentials during root key rotation." | ||
|
||
// Generate a new service account key | ||
newAPIKey, err := iam.CreateAPIKey(adminToken, oldKeyDetails.IAMID, oldKeyDetails.AccountID, keyName, keyDescription) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
// Update the configuration with the new key | ||
config.APIKey = newAPIKey.APIKey | ||
entry, err := logical.StorageEntryJSON("config", config) | ||
if err != nil { | ||
return nil, err | ||
} | ||
if err := req.Storage.Put(ctx, entry); err != nil { | ||
return nil, err | ||
} | ||
|
||
// Reset the backend to pick up the new key | ||
b.reset() | ||
|
||
// Delete the old API key | ||
err = iam.DeleteAPIKey(adminToken, oldKeyDetails.ID) | ||
if err != nil { | ||
errResponse := logical.ErrorResponse("error deleting API key %s after successfully rotating the API key to key %s: %s", oldKeyDetails.ID, newAPIKey.ID, err) | ||
return errResponse, err | ||
} | ||
|
||
return &logical.Response{ | ||
Data: map[string]interface{}{ | ||
apiKeyID: newAPIKey.ID, | ||
}, | ||
}, nil | ||
} | ||
|
||
const pathConfigRotateRootHelpSyn = ` | ||
Request to rotate the IBM Cloud credentials used by Vault | ||
` | ||
|
||
const pathConfigRotateRootHelpDesc = ` | ||
This path attempts to rotate the IBM Cloud API key used by Vault | ||
for this mount. It does this by generating a new key for the user or service ID, | ||
replacing the internal value, and then deleting the old API key. | ||
Note that it does not create a new service ID or user account, only a new | ||
API key on the same IAM ID as the existing key. | ||
` |
Oops, something went wrong.