2023-03-15 16:00:52 +00:00
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
2017-02-02 19:24:20 +00:00
package transit
import (
2018-01-08 18:31:38 +00:00
"context"
2017-02-02 19:24:20 +00:00
"strings"
"testing"
2019-04-12 21:54:35 +00:00
"github.com/hashicorp/vault/sdk/logical"
2017-02-02 19:24:20 +00:00
)
// Check the normal flow of rewrap
func TestTransit_BatchRewrapCase1 ( t * testing . T ) {
var resp * logical . Response
var err error
b , s := createBackendWithStorage ( t )
// Upsert the key and encrypt the data
plaintext := "dGhlIHF1aWNrIGJyb3duIGZveA=="
encData := map [ string ] interface { } {
"plaintext" : plaintext ,
}
// Create a key and encrypt a plaintext
encReq := & logical . Request {
Operation : logical . CreateOperation ,
Path : "encrypt/upserted_key" ,
Storage : s ,
Data : encData ,
}
2018-01-08 18:31:38 +00:00
resp , err = b . HandleRequest ( context . Background ( ) , encReq )
2017-02-02 19:24:20 +00:00
if err != nil || ( resp != nil && resp . IsError ( ) ) {
t . Fatalf ( "err:%v resp:%#v" , err , resp )
}
// Cache the ciphertext
ciphertext := resp . Data [ "ciphertext" ]
if ! strings . HasPrefix ( ciphertext . ( string ) , "vault:v1" ) {
t . Fatalf ( "bad: ciphertext version: expected: 'vault:v1', actual: %s" , ciphertext )
}
2020-06-01 17:16:01 +00:00
keyVersion := resp . Data [ "key_version" ] . ( int )
if keyVersion != 1 {
t . Fatalf ( "unexpected key version; got: %d, expected: %d" , keyVersion , 1 )
}
2017-02-02 19:24:20 +00:00
rewrapData := map [ string ] interface { } {
"ciphertext" : ciphertext ,
}
// Read the policy and check if the latest version is 1
policyReq := & logical . Request {
Operation : logical . ReadOperation ,
Path : "keys/upserted_key" ,
Storage : s ,
}
2018-01-08 18:31:38 +00:00
resp , err = b . HandleRequest ( context . Background ( ) , policyReq )
2017-02-02 19:24:20 +00:00
if err != nil || ( resp != nil && resp . IsError ( ) ) {
t . Fatalf ( "err:%v resp:%#v" , err , resp )
}
if resp . Data [ "latest_version" ] != 1 {
t . Fatalf ( "bad: latest_version: expected: 1, actual: %d" , resp . Data [ "latest_version" ] )
}
rotateReq := & logical . Request {
Operation : logical . UpdateOperation ,
Path : "keys/upserted_key/rotate" ,
Storage : s ,
}
2018-01-08 18:31:38 +00:00
resp , err = b . HandleRequest ( context . Background ( ) , rotateReq )
2017-02-02 19:24:20 +00:00
if err != nil || ( resp != nil && resp . IsError ( ) ) {
t . Fatalf ( "err:%v resp:%#v" , err , resp )
}
// Read the policy again and the latest version is 2
2018-01-08 18:31:38 +00:00
resp , err = b . HandleRequest ( context . Background ( ) , policyReq )
2017-02-02 19:24:20 +00:00
if err != nil || ( resp != nil && resp . IsError ( ) ) {
t . Fatalf ( "err:%v resp:%#v" , err , resp )
}
if resp . Data [ "latest_version" ] != 2 {
t . Fatalf ( "bad: latest_version: expected: 2, actual: %d" , resp . Data [ "latest_version" ] )
}
// Rewrap the ciphertext and check that they are different
rewrapReq := & logical . Request {
Operation : logical . UpdateOperation ,
Path : "rewrap/upserted_key" ,
Storage : s ,
Data : rewrapData ,
}
2018-01-08 18:31:38 +00:00
resp , err = b . HandleRequest ( context . Background ( ) , rewrapReq )
2017-02-02 19:24:20 +00:00
if err != nil || ( resp != nil && resp . IsError ( ) ) {
t . Fatalf ( "err:%v resp:%#v" , err , resp )
}
if ciphertext . ( string ) == resp . Data [ "ciphertext" ] . ( string ) {
t . Fatalf ( "bad: ciphertexts are same before and after rewrap" )
}
if ! strings . HasPrefix ( resp . Data [ "ciphertext" ] . ( string ) , "vault:v2" ) {
t . Fatalf ( "bad: ciphertext version: expected: 'vault:v2', actual: %s" , resp . Data [ "ciphertext" ] . ( string ) )
}
2020-06-01 17:16:01 +00:00
keyVersion = resp . Data [ "key_version" ] . ( int )
if keyVersion != 2 {
t . Fatalf ( "unexpected key version; got: %d, expected: %d" , keyVersion , 2 )
}
2017-02-02 19:24:20 +00:00
}
// Check the normal flow of rewrap with upserted key
func TestTransit_BatchRewrapCase2 ( t * testing . T ) {
var resp * logical . Response
var err error
b , s := createBackendWithStorage ( t )
// Upsert the key and encrypt the data
plaintext := "dGhlIHF1aWNrIGJyb3duIGZveA=="
encData := map [ string ] interface { } {
"plaintext" : plaintext ,
"context" : "dmlzaGFsCg==" ,
}
// Create a key and encrypt a plaintext
encReq := & logical . Request {
Operation : logical . CreateOperation ,
Path : "encrypt/upserted_key" ,
Storage : s ,
Data : encData ,
}
2018-01-08 18:31:38 +00:00
resp , err = b . HandleRequest ( context . Background ( ) , encReq )
2017-02-02 19:24:20 +00:00
if err != nil || ( resp != nil && resp . IsError ( ) ) {
t . Fatalf ( "err:%v resp:%#v" , err , resp )
}
// Cache the ciphertext
ciphertext := resp . Data [ "ciphertext" ]
if ! strings . HasPrefix ( ciphertext . ( string ) , "vault:v1" ) {
t . Fatalf ( "bad: ciphertext version: expected: 'vault:v1', actual: %s" , ciphertext )
}
2020-06-01 17:16:01 +00:00
keyVersion := resp . Data [ "key_version" ] . ( int )
if keyVersion != 1 {
t . Fatalf ( "unexpected key version; got: %d, expected: %d" , keyVersion , 1 )
}
2017-02-02 19:24:20 +00:00
rewrapData := map [ string ] interface { } {
"ciphertext" : ciphertext ,
"context" : "dmlzaGFsCg==" ,
}
// Read the policy and check if the latest version is 1
policyReq := & logical . Request {
Operation : logical . ReadOperation ,
Path : "keys/upserted_key" ,
Storage : s ,
}
2018-01-08 18:31:38 +00:00
resp , err = b . HandleRequest ( context . Background ( ) , policyReq )
2017-02-02 19:24:20 +00:00
if err != nil || ( resp != nil && resp . IsError ( ) ) {
t . Fatalf ( "err:%v resp:%#v" , err , resp )
}
if resp . Data [ "latest_version" ] != 1 {
t . Fatalf ( "bad: latest_version: expected: 1, actual: %d" , resp . Data [ "latest_version" ] )
}
rotateReq := & logical . Request {
Operation : logical . UpdateOperation ,
Path : "keys/upserted_key/rotate" ,
Storage : s ,
}
2018-01-08 18:31:38 +00:00
resp , err = b . HandleRequest ( context . Background ( ) , rotateReq )
2017-02-02 19:24:20 +00:00
if err != nil || ( resp != nil && resp . IsError ( ) ) {
t . Fatalf ( "err:%v resp:%#v" , err , resp )
}
// Read the policy again and the latest version is 2
2018-01-08 18:31:38 +00:00
resp , err = b . HandleRequest ( context . Background ( ) , policyReq )
2017-02-02 19:24:20 +00:00
if err != nil || ( resp != nil && resp . IsError ( ) ) {
t . Fatalf ( "err:%v resp:%#v" , err , resp )
}
if resp . Data [ "latest_version" ] != 2 {
t . Fatalf ( "bad: latest_version: expected: 2, actual: %d" , resp . Data [ "latest_version" ] )
}
// Rewrap the ciphertext and check that they are different
rewrapReq := & logical . Request {
Operation : logical . UpdateOperation ,
Path : "rewrap/upserted_key" ,
Storage : s ,
Data : rewrapData ,
}
2018-01-08 18:31:38 +00:00
resp , err = b . HandleRequest ( context . Background ( ) , rewrapReq )
2017-02-02 19:24:20 +00:00
if err != nil || ( resp != nil && resp . IsError ( ) ) {
t . Fatalf ( "err:%v resp:%#v" , err , resp )
}
if ciphertext . ( string ) == resp . Data [ "ciphertext" ] . ( string ) {
t . Fatalf ( "bad: ciphertexts are same before and after rewrap" )
}
if ! strings . HasPrefix ( resp . Data [ "ciphertext" ] . ( string ) , "vault:v2" ) {
t . Fatalf ( "bad: ciphertext version: expected: 'vault:v2', actual: %s" , resp . Data [ "ciphertext" ] . ( string ) )
}
2020-06-01 17:16:01 +00:00
keyVersion = resp . Data [ "key_version" ] . ( int )
if keyVersion != 2 {
t . Fatalf ( "unexpected key version; got: %d, expected: %d" , keyVersion , 2 )
}
2017-02-02 19:24:20 +00:00
}
// Batch encrypt plaintexts, rotate the keys and rewrap all the ciphertexts
func TestTransit_BatchRewrapCase3 ( t * testing . T ) {
var resp * logical . Response
var err error
b , s := createBackendWithStorage ( t )
2017-02-06 19:56:16 +00:00
batchEncryptionInput := [ ] interface { } {
2022-12-13 18:03:40 +00:00
map [ string ] interface { } { "plaintext" : "dmlzaGFsCg==" , "reference" : "ek" } ,
map [ string ] interface { } { "plaintext" : "dGhlIHF1aWNrIGJyb3duIGZveA==" , "reference" : "do" } ,
2017-02-06 19:56:16 +00:00
}
batchEncryptionData := map [ string ] interface { } {
"batch_input" : batchEncryptionInput ,
2017-02-02 19:24:20 +00:00
}
batchReq := & logical . Request {
Operation : logical . CreateOperation ,
Path : "encrypt/upserted_key" ,
Storage : s ,
2017-02-06 19:56:16 +00:00
Data : batchEncryptionData ,
2017-02-02 19:24:20 +00:00
}
2018-01-08 18:31:38 +00:00
resp , err = b . HandleRequest ( context . Background ( ) , batchReq )
2017-02-02 19:24:20 +00:00
if err != nil || ( resp != nil && resp . IsError ( ) ) {
t . Fatalf ( "err:%v resp:%#v" , err , resp )
}
2020-09-22 13:43:07 +00:00
batchEncryptionResponseItems := resp . Data [ "batch_results" ] . ( [ ] EncryptBatchResponseItem )
2017-02-06 19:56:16 +00:00
batchRewrapInput := make ( [ ] interface { } , len ( batchEncryptionResponseItems ) )
for i , item := range batchEncryptionResponseItems {
2022-12-13 18:03:40 +00:00
batchRewrapInput [ i ] = map [ string ] interface { } { "ciphertext" : item . Ciphertext , "reference" : item . Reference }
2017-02-02 19:24:20 +00:00
}
2017-02-06 19:56:16 +00:00
batchRewrapData := map [ string ] interface { } {
"batch_input" : batchRewrapInput ,
2017-02-02 19:24:20 +00:00
}
rotateReq := & logical . Request {
Operation : logical . UpdateOperation ,
Path : "keys/upserted_key/rotate" ,
Storage : s ,
}
2018-01-08 18:31:38 +00:00
resp , err = b . HandleRequest ( context . Background ( ) , rotateReq )
2017-02-02 19:24:20 +00:00
if err != nil || ( resp != nil && resp . IsError ( ) ) {
t . Fatalf ( "err:%v resp:%#v" , err , resp )
}
rewrapReq := & logical . Request {
Operation : logical . UpdateOperation ,
Path : "rewrap/upserted_key" ,
Storage : s ,
2017-02-06 19:56:16 +00:00
Data : batchRewrapData ,
2017-02-02 19:24:20 +00:00
}
2018-01-08 18:31:38 +00:00
resp , err = b . HandleRequest ( context . Background ( ) , rewrapReq )
2017-02-02 19:24:20 +00:00
if err != nil || ( resp != nil && resp . IsError ( ) ) {
t . Fatalf ( "err:%v resp:%#v" , err , resp )
}
2020-09-22 13:43:07 +00:00
batchRewrapResponseItems := resp . Data [ "batch_results" ] . ( [ ] EncryptBatchResponseItem )
2017-02-02 19:24:20 +00:00
2017-02-06 19:56:16 +00:00
if len ( batchRewrapResponseItems ) != len ( batchEncryptionResponseItems ) {
t . Fatalf ( "bad: length of input and output or rewrap are not matching; expected: %d, actual: %d" , len ( batchEncryptionResponseItems ) , len ( batchRewrapResponseItems ) )
2017-02-02 19:24:20 +00:00
}
decReq := & logical . Request {
Operation : logical . UpdateOperation ,
Path : "decrypt/upserted_key" ,
Storage : s ,
}
2017-02-06 19:56:16 +00:00
for i , eItem := range batchEncryptionResponseItems {
rItem := batchRewrapResponseItems [ i ]
2017-02-02 19:24:20 +00:00
2022-12-13 18:03:40 +00:00
inputRef := batchEncryptionInput [ i ] . ( map [ string ] interface { } ) [ "reference" ]
if eItem . Reference != inputRef {
t . Fatalf ( "bad: reference mismatch. Expected %s, Actual: %s" , inputRef , eItem . Reference )
}
2017-02-06 19:56:16 +00:00
if eItem . Ciphertext == rItem . Ciphertext {
2017-02-02 19:24:20 +00:00
t . Fatalf ( "bad: rewrap input and output are the same" )
}
2017-02-06 19:56:16 +00:00
if ! strings . HasPrefix ( rItem . Ciphertext , "vault:v2" ) {
t . Fatalf ( "bad: invalid version of ciphertext in rewrap response; expected: 'vault:v2', actual: %s" , rItem . Ciphertext )
2017-02-02 19:24:20 +00:00
}
2020-06-01 17:16:01 +00:00
if rItem . KeyVersion != 2 {
t . Fatalf ( "unexpected key version; got: %d, expected: %d" , rItem . KeyVersion , 2 )
}
2017-02-02 19:24:20 +00:00
decReq . Data = map [ string ] interface { } {
2017-02-06 19:56:16 +00:00
"ciphertext" : rItem . Ciphertext ,
2017-02-02 19:24:20 +00:00
}
2018-01-08 18:31:38 +00:00
resp , err = b . HandleRequest ( context . Background ( ) , decReq )
2017-02-02 19:24:20 +00:00
if err != nil || ( resp != nil && resp . IsError ( ) ) {
t . Fatalf ( "err:%v resp:%#v" , err , resp )
}
plaintext1 := "dGhlIHF1aWNrIGJyb3duIGZveA=="
plaintext2 := "dmlzaGFsCg=="
if resp . Data [ "plaintext" ] != plaintext1 && resp . Data [ "plaintext" ] != plaintext2 {
t . Fatalf ( "bad: plaintext. Expected: %q or %q, Actual: %q" , plaintext1 , plaintext2 , resp . Data [ "plaintext" ] )
}
2022-12-13 18:03:40 +00:00
2017-02-02 19:24:20 +00:00
}
}