-
Notifications
You must be signed in to change notification settings - Fork 4.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix transit byok tool, add docs, tests #19373
Merged
Merged
Changes from 4 commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
b1844de
Fix Vault Transit BYOK helper argument parsing
cipherboy d37a7ee
Add missing documentation on Transit CLI to website
cipherboy f0c4e75
Add tests for Transit BYOK vault subcommand
cipherboy 11cdfb1
Add changelog
cipherboy ca67626
Appease CI
cipherboy 7ce852c
Fix return usage
cipherboy File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
```release-note:bug | ||
cli/transit: Fix import, import-version command invocation | ||
``` |
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,185 @@ | ||
package command | ||
|
||
import ( | ||
"bytes" | ||
"crypto/rand" | ||
"crypto/rsa" | ||
"crypto/x509" | ||
"encoding/base64" | ||
"testing" | ||
|
||
"github.com/hashicorp/vault/api" | ||
|
||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestTransitImport(t *testing.T) { | ||
t.Parallel() | ||
|
||
client, closer := testVaultServer(t) | ||
defer closer() | ||
|
||
if err := client.Sys().Mount("transit", &api.MountInput{ | ||
Type: "transit", | ||
}); err != nil { | ||
t.Fatalf("transit mount error: %#v", err) | ||
} | ||
|
||
rsa1, rsa2, aes128, aes256 := generateKeys(t) | ||
|
||
type testCase struct { | ||
variant string | ||
path string | ||
key []byte | ||
args []string | ||
shouldFail bool | ||
} | ||
tests := []testCase{ | ||
{ | ||
"import", | ||
"transit/keys/rsa1", | ||
rsa1, | ||
[]string{"type=rsa-2048"}, | ||
false, /* first import */ | ||
}, | ||
{ | ||
"import", | ||
"transit/keys/rsa1", | ||
rsa2, | ||
[]string{"type=rsa-2048"}, | ||
true, /* already exists */ | ||
}, | ||
{ | ||
"import-version", | ||
"transit/keys/rsa1", | ||
rsa2, | ||
[]string{"type=rsa-2048"}, | ||
false, /* new version */ | ||
}, | ||
{ | ||
"import", | ||
"transit/keys/rsa2", | ||
rsa2, | ||
[]string{"type=rsa-4096"}, | ||
true, /* wrong type */ | ||
}, | ||
{ | ||
"import", | ||
"transit/keys/rsa2", | ||
rsa2, | ||
[]string{"type=rsa-2048"}, | ||
false, /* new name */ | ||
}, | ||
{ | ||
"import", | ||
"transit/keys/aes1", | ||
aes128, | ||
[]string{"type=aes128-gcm96"}, | ||
false, /* first import */ | ||
}, | ||
{ | ||
"import", | ||
"transit/keys/aes1", | ||
aes256, | ||
[]string{"type=aes256-gcm96"}, | ||
true, /* already exists */ | ||
}, | ||
{ | ||
"import-version", | ||
"transit/keys/aes1", | ||
aes256, | ||
[]string{"type=aes256-gcm96"}, | ||
true, /* new version, different type */ | ||
}, | ||
{ | ||
"import-version", | ||
"transit/keys/aes1", | ||
aes128, | ||
[]string{"type=aes128-gcm96"}, | ||
false, /* new version */ | ||
}, | ||
{ | ||
"import", | ||
"transit/keys/aes2", | ||
aes256, | ||
[]string{"type=aes128-gcm96"}, | ||
true, /* wrong type */ | ||
}, | ||
{ | ||
"import", | ||
"transit/keys/aes2", | ||
aes256, | ||
[]string{"type=aes256-gcm96"}, | ||
false, /* new name */ | ||
}, | ||
} | ||
|
||
for index, tc := range tests { | ||
t.Logf("Running test case %d: %v", index, tc) | ||
execTransitImport(t, client, tc.variant, tc.path, tc.key, tc.args, tc.shouldFail) | ||
} | ||
} | ||
|
||
func execTransitImport(t *testing.T, client *api.Client, method string, path string, key []byte, data []string, expectFailure bool) { | ||
t.Helper() | ||
|
||
keyBase64 := base64.StdEncoding.EncodeToString(key) | ||
|
||
var args []string | ||
args = append(args, "transit") | ||
args = append(args, method) | ||
args = append(args, path) | ||
args = append(args, keyBase64) | ||
args = append(args, data...) | ||
|
||
stdout := bytes.NewBuffer(nil) | ||
stderr := bytes.NewBuffer(nil) | ||
runOpts := &RunOptions{ | ||
Stdout: stdout, | ||
Stderr: stderr, | ||
Client: client, | ||
} | ||
|
||
code := RunCustom(args, runOpts) | ||
combined := stdout.String() + stderr.String() | ||
|
||
if code != 0 { | ||
if !expectFailure { | ||
t.Fatalf("Got unexpected failure from test (ret %d): %v", code, combined) | ||
} | ||
} else { | ||
if expectFailure { | ||
t.Fatalf("Expected failure, got success from test (ret %d): %v", code, combined) | ||
} | ||
} | ||
} | ||
|
||
func generateKeys(t *testing.T) (rsa1 []byte, rsa2 []byte, aes128 []byte, aes256 []byte) { | ||
t.Helper() | ||
|
||
priv1, err := rsa.GenerateKey(rand.Reader, 2048) | ||
require.NotNil(t, priv1, "failed generating RSA 1 key") | ||
require.NoError(t, err, "failed generating RSA 1 key") | ||
|
||
rsa1, err = x509.MarshalPKCS8PrivateKey(priv1) | ||
require.NotNil(t, rsa1, "failed marshaling RSA 1 key") | ||
require.NoError(t, err, "failed marshaling RSA 1 key") | ||
|
||
priv2, err := rsa.GenerateKey(rand.Reader, 2048) | ||
require.NotNil(t, priv2, "failed generating RSA 2 key") | ||
require.NoError(t, err, "failed generating RSA 2 key") | ||
|
||
rsa2, err = x509.MarshalPKCS8PrivateKey(priv2) | ||
require.NotNil(t, rsa2, "failed marshaling RSA 2 key") | ||
require.NoError(t, err, "failed marshaling RSA 2 key") | ||
|
||
aes128 = make([]byte, 128/8) | ||
_, err = rand.Read(aes128) | ||
require.NoError(t, err, "failed generating AES 128 key") | ||
|
||
aes256 = make([]byte, 256/8) | ||
_, err = rand.Read(aes256) | ||
require.NoError(t, err, "failed generating AES 256 key") | ||
|
||
return | ||
} |
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,62 @@ | ||
--- | ||
layout: docs | ||
page_title: transit import and transit import-version - Command | ||
description: |- | ||
The "transit import" and "transit import-version" commands import the | ||
specified key into Transit, via the Transit BYOK mechanism. | ||
--- | ||
|
||
# transit import and transit import-version | ||
|
||
The `transit import` and `transit import-version` commands import the | ||
specified key into Transit, via the [Transit BYOK | ||
mechanism](/vault/docs/secrets/transit#bring-your-own-key-byok). The former | ||
imports this key as a new key, failing if it already exists, whereas the | ||
latter will only update an existing key in Transit to a new version of the | ||
key material. | ||
|
||
This needs access to read the transit mount's wrapping key (at | ||
`transit/wrapping_key`) and the ability to write to either import | ||
endpoints (either `transit/keys/:name/import` or | ||
`transit/keys/:name/import_version`). | ||
|
||
## Examples | ||
|
||
Imports a 2048-bit RSA key as a new key: | ||
|
||
``` | ||
$ vault transit import transit/keys/test-key @test-key type=rsa-2048 | ||
Retrieving transit wrapping key. | ||
Wrapping source key with ephemeral key. | ||
Encrypting ephemeral key with transit wrapping key. | ||
Submitting wrapped key to Vault transit. | ||
Success! | ||
``` | ||
|
||
Imports a new version of an existing key: | ||
|
||
``` | ||
$ vault transit import-version transit/keys/test-key @test-key-updated | ||
Retrieving transit wrapping key. | ||
Wrapping source key with ephemeral key. | ||
Encrypting ephemeral key with transit wrapping key. | ||
Submitting wrapped key to Vault transit. | ||
Success! | ||
``` | ||
|
||
## Usage | ||
|
||
This command does not have any unique flags and respects core Vault CLI | ||
commands. See `vault transit import -help` for more information. | ||
|
||
This command requires two positional arguments: | ||
|
||
1. `PATH`, the path to the transit key to import in the format of | ||
`<mount>/keys/<key-name>`, where `<mount>` is the path to the mount | ||
(using `-namespace=<ns>` to specify any namespaces), and `<key-name>` | ||
is the desired name of the key. | ||
2. `KEY`, the key material to import in Standard Base64 encoding (either | ||
of a raw key in the case of symmetric keys such as AES, or of the DER | ||
encoded format for asymmetric keys such as RSA). If the value for `KEY` | ||
begins with an `@`, the CLI argument is assumed to be a path to a file | ||
on disk to be read. |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
😄