cbecc40e48
* add first stepwise test env, Docker, with example transit test * update transit stepwise test * add other tests that use stepwise * cleanup test, make names different than just 'transit' * return the stderr if compile fails with error * minor cleanups * minor cleanups * go mod vendor * cleanups * remove some extra code, and un-export some fields/methods * update vendor * remove reference to vault.CoreConfig, which really wasn't used anyway * update with go mod vendor * restore Precheck method to test cases * clean up some networking things; create networks with UUID, clean up during teardown * vendor stepwise * Update sdk/testing/stepwise/environments/docker/environment.go haha thanks :D Co-authored-by: Michael Golowka <72365+pcman312@users.noreply.github.com> * Update sdk/testing/stepwise/environments/docker/environment.go Great catch, thanks Co-authored-by: Michael Golowka <72365+pcman312@users.noreply.github.com> * fix redundant name * update error message in test * Update builtin/credential/userpass/stepwise_test.go More explicit error checking and responding Co-authored-by: Michael Golowka <72365+pcman312@users.noreply.github.com> * Update builtin/logical/aws/stepwise_test.go `test` -> `testFunc` Co-authored-by: Michael Golowka <72365+pcman312@users.noreply.github.com> * Update builtin/logical/transit/stepwise_test.go Co-authored-by: Michael Golowka <72365+pcman312@users.noreply.github.com> * fix typos * update error messages to provide clarity * Update sdk/testing/stepwise/environments/docker/environment.go Co-authored-by: Michael Golowka <72365+pcman312@users.noreply.github.com> * update error handling / collection in Teardown * panic if GenerateUUID returns an error * Update sdk/testing/stepwise/environments/docker/environment.go Co-authored-by: Michael Golowka <72365+pcman312@users.noreply.github.com> * Update builtin/credential/userpass/stepwise_test.go Co-authored-by: Calvin Leung Huang <cleung2010@gmail.com> * Update builtin/logical/aws/stepwise_test.go Co-authored-by: Calvin Leung Huang <cleung2010@gmail.com> * Update builtin/logical/transit/stepwise_test.go Co-authored-by: Calvin Leung Huang <cleung2010@gmail.com> * Update sdk/testing/stepwise/environments/docker/environment.go Co-authored-by: Calvin Leung Huang <cleung2010@gmail.com> * import ordering * standardize on dc from rc for cluster * lowercase name * CreateAPIClient -> NewAPIClient * testWait -> ensure * go mod cleanup * cleanups * move fields and method around * make start and dockerclusternode private; use better random serial number * use better random for SerialNumber * add a timeout to the context used for terminating the docker container * Use a constant for the Docker client version * rearrange import statements Co-authored-by: Michael Golowka <72365+pcman312@users.noreply.github.com> Co-authored-by: Calvin Leung Huang <cleung2010@gmail.com>
234 lines
7.3 KiB
Go
234 lines
7.3 KiB
Go
package transit
|
|
|
|
import (
|
|
"encoding/base64"
|
|
"fmt"
|
|
"os"
|
|
"testing"
|
|
|
|
"github.com/hashicorp/vault/api"
|
|
"github.com/hashicorp/vault/sdk/helper/keysutil"
|
|
"github.com/hashicorp/vault/sdk/testing/stepwise"
|
|
dockerEnvironment "github.com/hashicorp/vault/sdk/testing/stepwise/environments/docker"
|
|
"github.com/mitchellh/mapstructure"
|
|
)
|
|
|
|
// TestBackend_basic_docker is an example test using the Docker Environment
|
|
func TestAccBackend_basic_docker(t *testing.T) {
|
|
decryptData := make(map[string]interface{})
|
|
envOptions := stepwise.MountOptions{
|
|
RegistryName: "updatedtransit",
|
|
PluginType: stepwise.PluginTypeSecrets,
|
|
PluginName: "transit",
|
|
MountPathPrefix: "transit_temp",
|
|
}
|
|
stepwise.Run(t, stepwise.Case{
|
|
Environment: dockerEnvironment.NewEnvironment("updatedtransit", &envOptions),
|
|
Steps: []stepwise.Step{
|
|
testAccStepwiseListPolicy(t, "test", true),
|
|
testAccStepwiseWritePolicy(t, "test", true),
|
|
testAccStepwiseListPolicy(t, "test", false),
|
|
testAccStepwiseReadPolicy(t, "test", false, true),
|
|
testAccStepwiseEncryptContext(t, "test", testPlaintext, "my-cool-context", decryptData),
|
|
testAccStepwiseDecrypt(t, "test", testPlaintext, decryptData),
|
|
testAccStepwiseEnableDeletion(t, "test"),
|
|
testAccStepwiseDeletePolicy(t, "test"),
|
|
testAccStepwiseReadPolicy(t, "test", true, true),
|
|
},
|
|
})
|
|
}
|
|
|
|
func testAccStepwiseWritePolicy(t *testing.T, name string, derived bool) stepwise.Step {
|
|
ts := stepwise.Step{
|
|
Operation: stepwise.WriteOperation,
|
|
Path: "keys/" + name,
|
|
Data: map[string]interface{}{
|
|
"derived": derived,
|
|
},
|
|
}
|
|
if os.Getenv("TRANSIT_ACC_KEY_TYPE") == "CHACHA" {
|
|
ts.Data["type"] = "chacha20-poly1305"
|
|
}
|
|
return ts
|
|
}
|
|
|
|
func testAccStepwiseListPolicy(t *testing.T, name string, expectNone bool) stepwise.Step {
|
|
return stepwise.Step{
|
|
Operation: stepwise.ListOperation,
|
|
Path: "keys",
|
|
Assert: func(resp *api.Secret, err error) error {
|
|
if (resp == nil || len(resp.Data) == 0) && !expectNone {
|
|
return fmt.Errorf("missing response")
|
|
}
|
|
if expectNone && resp != nil {
|
|
return fmt.Errorf("response data when expecting none")
|
|
}
|
|
|
|
if expectNone && resp == nil {
|
|
return nil
|
|
}
|
|
|
|
var d struct {
|
|
Keys []string `mapstructure:"keys"`
|
|
}
|
|
if err := mapstructure.Decode(resp.Data, &d); err != nil {
|
|
return err
|
|
}
|
|
if len(d.Keys) == 0 {
|
|
return fmt.Errorf("missing keys")
|
|
}
|
|
if len(d.Keys) > 1 {
|
|
return fmt.Errorf("only 1 key expected, %d returned", len(d.Keys))
|
|
}
|
|
if d.Keys[0] != name {
|
|
return fmt.Errorf("Actual key: %s\nExpected key: %s", d.Keys[0], name)
|
|
}
|
|
return nil
|
|
},
|
|
}
|
|
}
|
|
|
|
func testAccStepwiseReadPolicy(t *testing.T, name string, expectNone, derived bool) stepwise.Step {
|
|
t.Helper()
|
|
return testAccStepwiseReadPolicyWithVersions(t, name, expectNone, derived, 1, 0)
|
|
}
|
|
|
|
func testAccStepwiseReadPolicyWithVersions(t *testing.T, name string, expectNone, derived bool, minDecryptionVersion int, minEncryptionVersion int) stepwise.Step {
|
|
t.Helper()
|
|
return stepwise.Step{
|
|
Operation: stepwise.ReadOperation,
|
|
Path: "keys/" + name,
|
|
Assert: func(resp *api.Secret, err error) error {
|
|
t.Helper()
|
|
if resp == nil && !expectNone {
|
|
return fmt.Errorf("missing response")
|
|
} else if expectNone {
|
|
if resp != nil {
|
|
return fmt.Errorf("response when expecting none")
|
|
}
|
|
return nil
|
|
}
|
|
var d struct {
|
|
Name string `mapstructure:"name"`
|
|
Key []byte `mapstructure:"key"`
|
|
Keys map[string]int64 `mapstructure:"keys"`
|
|
Type string `mapstructure:"type"`
|
|
Derived bool `mapstructure:"derived"`
|
|
KDF string `mapstructure:"kdf"`
|
|
DeletionAllowed bool `mapstructure:"deletion_allowed"`
|
|
ConvergentEncryption bool `mapstructure:"convergent_encryption"`
|
|
MinDecryptionVersion int `mapstructure:"min_decryption_version"`
|
|
MinEncryptionVersion int `mapstructure:"min_encryption_version"`
|
|
}
|
|
if err := mapstructure.Decode(resp.Data, &d); err != nil {
|
|
return err
|
|
}
|
|
|
|
if d.Name != name {
|
|
return fmt.Errorf("bad name: %#v", d)
|
|
}
|
|
if os.Getenv("TRANSIT_ACC_KEY_TYPE") == "CHACHA" {
|
|
if d.Type != keysutil.KeyType(keysutil.KeyType_ChaCha20_Poly1305).String() {
|
|
return fmt.Errorf("bad key type: %#v", d)
|
|
}
|
|
} else if d.Type != keysutil.KeyType(keysutil.KeyType_AES256_GCM96).String() {
|
|
return fmt.Errorf("bad key type: %#v", d)
|
|
}
|
|
// Should NOT get a key back
|
|
if d.Key != nil {
|
|
return fmt.Errorf("unexpected key found")
|
|
}
|
|
if d.Keys == nil {
|
|
return fmt.Errorf("no keys found")
|
|
}
|
|
if d.MinDecryptionVersion != minDecryptionVersion {
|
|
return fmt.Errorf("minimum decryption version mismatch, expected (%#v), found (%#v)", minEncryptionVersion, d.MinDecryptionVersion)
|
|
}
|
|
if d.MinEncryptionVersion != minEncryptionVersion {
|
|
return fmt.Errorf("minimum encryption version mismatch, expected (%#v), found (%#v)", minEncryptionVersion, d.MinDecryptionVersion)
|
|
}
|
|
if d.DeletionAllowed == true {
|
|
return fmt.Errorf("expected DeletionAllowed to be false, but got true")
|
|
}
|
|
if d.Derived != derived {
|
|
return fmt.Errorf("derived mismatch, expected (%t), got (%t)", derived, d.Derived)
|
|
}
|
|
if derived && d.KDF != "hkdf_sha256" {
|
|
return fmt.Errorf("expected KDF to be hkdf_sha256, but got (%s)", d.KDF)
|
|
}
|
|
return nil
|
|
},
|
|
}
|
|
}
|
|
|
|
func testAccStepwiseEncryptContext(
|
|
t *testing.T, name, plaintext, context string, decryptData map[string]interface{}) stepwise.Step {
|
|
return stepwise.Step{
|
|
Operation: stepwise.UpdateOperation,
|
|
Path: "encrypt/" + name,
|
|
Data: map[string]interface{}{
|
|
"plaintext": base64.StdEncoding.EncodeToString([]byte(plaintext)),
|
|
"context": base64.StdEncoding.EncodeToString([]byte(context)),
|
|
},
|
|
Assert: func(resp *api.Secret, err error) error {
|
|
var d struct {
|
|
Ciphertext string `mapstructure:"ciphertext"`
|
|
}
|
|
if err := mapstructure.Decode(resp.Data, &d); err != nil {
|
|
return err
|
|
}
|
|
if d.Ciphertext == "" {
|
|
return fmt.Errorf("missing ciphertext")
|
|
}
|
|
decryptData["ciphertext"] = d.Ciphertext
|
|
decryptData["context"] = base64.StdEncoding.EncodeToString([]byte(context))
|
|
return nil
|
|
},
|
|
}
|
|
}
|
|
|
|
func testAccStepwiseDecrypt(
|
|
t *testing.T, name, plaintext string, decryptData map[string]interface{}) stepwise.Step {
|
|
return stepwise.Step{
|
|
Operation: stepwise.UpdateOperation,
|
|
Path: "decrypt/" + name,
|
|
Data: decryptData,
|
|
Assert: func(resp *api.Secret, err error) error {
|
|
var d struct {
|
|
Plaintext string `mapstructure:"plaintext"`
|
|
}
|
|
if err := mapstructure.Decode(resp.Data, &d); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Decode the base64
|
|
plainRaw, err := base64.StdEncoding.DecodeString(d.Plaintext)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if string(plainRaw) != plaintext {
|
|
return fmt.Errorf("plaintext mismatch: %s expect: %s, decryptData was %#v", plainRaw, plaintext, decryptData)
|
|
}
|
|
return nil
|
|
},
|
|
}
|
|
}
|
|
|
|
func testAccStepwiseEnableDeletion(t *testing.T, name string) stepwise.Step {
|
|
return stepwise.Step{
|
|
Operation: stepwise.UpdateOperation,
|
|
Path: "keys/" + name + "/config",
|
|
Data: map[string]interface{}{
|
|
"deletion_allowed": true,
|
|
},
|
|
}
|
|
}
|
|
|
|
func testAccStepwiseDeletePolicy(t *testing.T, name string) stepwise.Step {
|
|
return stepwise.Step{
|
|
Operation: stepwise.DeleteOperation,
|
|
Path: "keys/" + name,
|
|
}
|
|
}
|