Files
vault/builtin/logical/transit/path_trim_test.go
hashicorp-copywrite[bot] 0b12cdcfd1 [COMPLIANCE] License changes (#22290)
* Adding explicit MPL license for sub-package.

This directory and its subdirectories (packages) contain files licensed with the MPLv2 `LICENSE` file in this directory and are intentionally licensed separately from the BSL `LICENSE` file at the root of this repository.

* Adding explicit MPL license for sub-package.

This directory and its subdirectories (packages) contain files licensed with the MPLv2 `LICENSE` file in this directory and are intentionally licensed separately from the BSL `LICENSE` file at the root of this repository.

* Updating the license from MPL to Business Source License.

Going forward, this project will be licensed under the Business Source License v1.1. Please see our blog post for more details at https://hashi.co/bsl-blog, FAQ at www.hashicorp.com/licensing-faq, and details of the license at www.hashicorp.com/bsl.

* add missing license headers

* Update copyright file headers to BUS-1.1

* Fix test that expected exact offset on hcl file

---------

Co-authored-by: hashicorp-copywrite[bot] <110428419+hashicorp-copywrite[bot]@users.noreply.github.com>
Co-authored-by: Sarah Thompson <sthompson@hashicorp.com>
Co-authored-by: Brian Kassouf <bkassouf@hashicorp.com>
2023-08-10 18:14:03 -07:00

274 lines
6.9 KiB
Go

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package transit
import (
"testing"
"github.com/hashicorp/vault/helper/namespace"
"github.com/hashicorp/vault/sdk/helper/keysutil"
"github.com/hashicorp/vault/sdk/logical"
)
func TestTransit_Trim(t *testing.T) {
b, storage := createBackendWithSysView(t)
doReq := func(t *testing.T, req *logical.Request) *logical.Response {
t.Helper()
resp, err := b.HandleRequest(namespace.RootContext(nil), req)
if err != nil || (resp != nil && resp.IsError()) {
t.Fatalf("got err:\n%#v\nresp:\n%#v\n", err, resp)
}
return resp
}
doErrReq := func(t *testing.T, req *logical.Request) {
t.Helper()
resp, err := b.HandleRequest(namespace.RootContext(nil), req)
if err == nil && (resp == nil || !resp.IsError()) {
t.Fatalf("expected error; resp:\n%#v\n", resp)
}
}
// Create a key
req := &logical.Request{
Path: "keys/aes",
Storage: storage,
Operation: logical.UpdateOperation,
}
doReq(t, req)
// Get the policy and check that the archive has correct number of keys
p, _, err := b.GetPolicy(namespace.RootContext(nil), keysutil.PolicyRequest{
Storage: storage,
Name: "aes",
}, b.GetRandomReader())
if err != nil {
t.Fatal(err)
}
// Archive: 0, 1
archive, err := p.LoadArchive(namespace.RootContext(nil), storage)
if err != nil {
t.Fatal(err)
}
// Index "0" in the archive is unused. Hence the length of the archived
// keys will always be 1 more than the actual number of keys.
if len(archive.Keys) != 2 {
t.Fatalf("bad: len of archived keys; expected: 2, actual: %d", len(archive.Keys))
}
// Ensure that there are 5 key versions, by rotating the key 4 times
for i := 0; i < 4; i++ {
req.Path = "keys/aes/rotate"
req.Data = nil
doReq(t, req)
}
// Archive: 0, 1, 2, 3, 4, 5
archive, err = p.LoadArchive(namespace.RootContext(nil), storage)
if err != nil {
t.Fatal(err)
}
if len(archive.Keys) != 6 {
t.Fatalf("bad: len of archived keys; expected: 6, actual: %d", len(archive.Keys))
}
// Min available version should not be set when min_encryption_version is not
// set
req.Path = "keys/aes/trim"
req.Data = map[string]interface{}{
"min_available_version": 1,
}
doErrReq(t, req)
// Set min_encryption_version to 0
req.Path = "keys/aes/config"
req.Data = map[string]interface{}{
"min_encryption_version": 0,
}
doReq(t, req)
// Min available version should not be converted to 0 for nil values
req.Path = "keys/aes/trim"
req.Data = map[string]interface{}{
"min_available_version": nil,
}
doErrReq(t, req)
// Set min_encryption_version to 4
req.Path = "keys/aes/config"
req.Data = map[string]interface{}{
"min_encryption_version": 4,
}
doReq(t, req)
// Set min_decryption_version to 3
req.Data = map[string]interface{}{
"min_decryption_version": 3,
}
doReq(t, req)
// Min available version cannot be greater than min encryption version
req.Path = "keys/aes/trim"
req.Data = map[string]interface{}{
"min_available_version": 5,
}
doErrReq(t, req)
// Min available version cannot be greater than min decryption version
req.Data["min_available_version"] = 4
doErrReq(t, req)
// Min available version cannot be negative
req.Data["min_available_version"] = -1
doErrReq(t, req)
// Min available version should be positive
req.Data["min_available_version"] = 0
doErrReq(t, req)
// Trim all keys before version 3. Index 0 and index 1 will be deleted from
// archived keys.
req.Data["min_available_version"] = 3
doReq(t, req)
// Archive: 3, 4, 5
archive, err = p.LoadArchive(namespace.RootContext(nil), storage)
if err != nil {
t.Fatal(err)
}
if len(archive.Keys) != 3 {
t.Fatalf("bad: len of archived keys; expected: 3, actual: %d", len(archive.Keys))
}
// Min decryption version should not be less than min available version
req.Path = "keys/aes/config"
req.Data = map[string]interface{}{
"min_decryption_version": 1,
}
doErrReq(t, req)
// Min encryption version should not be less than min available version
req.Data = map[string]interface{}{
"min_encryption_version": 2,
}
doErrReq(t, req)
// Rotate 5 more times
for i := 0; i < 5; i++ {
doReq(t, &logical.Request{
Path: "keys/aes/rotate",
Storage: storage,
Operation: logical.UpdateOperation,
})
}
// Archive: 3, 4, 5, 6, 7, 8, 9, 10
archive, err = p.LoadArchive(namespace.RootContext(nil), storage)
if err != nil {
t.Fatal(err)
}
if len(archive.Keys) != 8 {
t.Fatalf("bad: len of archived keys; expected: 8, actual: %d", len(archive.Keys))
}
// Set min encryption version to 7
req.Data = map[string]interface{}{
"min_encryption_version": 7,
}
doReq(t, req)
// Set min decryption version to 7
req.Data = map[string]interface{}{
"min_decryption_version": 7,
}
doReq(t, req)
// Trim all versions before 7
req.Path = "keys/aes/trim"
req.Data = map[string]interface{}{
"min_available_version": 7,
}
doReq(t, req)
// Archive: 7, 8, 9, 10
archive, err = p.LoadArchive(namespace.RootContext(nil), storage)
if err != nil {
t.Fatal(err)
}
if len(archive.Keys) != 4 {
t.Fatalf("bad: len of archived keys; expected: 4, actual: %d", len(archive.Keys))
}
// Read the key
req.Path = "keys/aes"
req.Operation = logical.ReadOperation
resp := doReq(t, req)
keys := resp.Data["keys"].(map[string]int64)
if len(keys) != 4 {
t.Fatalf("bad: number of keys; expected: 4, actual: %d", len(keys))
}
// Test if moving the min_encryption_version and min_decryption_versions
// are working fine
// Set min encryption version to 10
req.Path = "keys/aes/config"
req.Operation = logical.UpdateOperation
req.Data = map[string]interface{}{
"min_encryption_version": 10,
}
doReq(t, req)
if p.MinEncryptionVersion != 10 {
t.Fatalf("failed to set min encryption version")
}
// Set min decryption version to 9
req.Data = map[string]interface{}{
"min_decryption_version": 9,
}
doReq(t, req)
if p.MinDecryptionVersion != 9 {
t.Fatalf("failed to set min encryption version")
}
// Reduce the min decryption version to 8
req.Data = map[string]interface{}{
"min_decryption_version": 8,
}
doReq(t, req)
if p.MinDecryptionVersion != 8 {
t.Fatalf("failed to set min encryption version")
}
// Reduce the min encryption version to 8
req.Data = map[string]interface{}{
"min_encryption_version": 8,
}
doReq(t, req)
if p.MinDecryptionVersion != 8 {
t.Fatalf("failed to set min decryption version")
}
// Read the key to ensure that the keys are properly copied from the
// archive into the policy
req.Path = "keys/aes"
req.Operation = logical.ReadOperation
resp = doReq(t, req)
keys = resp.Data["keys"].(map[string]int64)
if len(keys) != 3 {
t.Fatalf("bad: number of keys; expected: 3, actual: %d", len(keys))
}
// Ensure that archive has remained unchanged
// Archive: 7, 8, 9, 10
archive, err = p.LoadArchive(namespace.RootContext(nil), storage)
if err != nil {
t.Fatal(err)
}
if len(archive.Keys) != 4 {
t.Fatalf("bad: len of archived keys; expected: 4, actual: %d", len(archive.Keys))
}
}