mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-11-01 19:17:58 +00:00
transit: change batch input format (#2331)
* transit: change batch input format * transit: no json-in-json for batch response * docs: transit: update batch input format * transit: fix tests after changing response format
This commit is contained in:
@@ -5,9 +5,9 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/vault/helper/errutil"
|
||||
"github.com/hashicorp/vault/helper/jsonutil"
|
||||
"github.com/hashicorp/vault/logical"
|
||||
"github.com/hashicorp/vault/logical/framework"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
)
|
||||
|
||||
func (b *backend) pathDecrypt() *framework.Path {
|
||||
@@ -39,27 +39,6 @@ Base64 encoded nonce value used during encryption. Must be provided if
|
||||
convergent encryption is enabled for this key and the key was generated with
|
||||
Vault 0.6.1. Not required for keys created in 0.6.2+.`,
|
||||
},
|
||||
|
||||
"batch_input": &framework.FieldSchema{
|
||||
Type: framework.TypeString,
|
||||
Description: `
|
||||
Base64 encoded list of items to be decrypted in a single batch. When this
|
||||
parameter is set, if the parameters 'ciphertext', 'context' and 'nonce' are
|
||||
also set, they will be ignored. JSON format for the input (which should be
|
||||
base64 encoded) goes like this:
|
||||
|
||||
[
|
||||
{
|
||||
"context": "c2FtcGxlY29udGV4dA==",
|
||||
"ciphertext": "vault:v1:/DupSiSbX/ATkGmKAmhqD0tvukByrx6gmps7dVI="
|
||||
},
|
||||
{
|
||||
"context": "YW5vdGhlcnNhbXBsZWNvbnRleHQ=",
|
||||
"ciphertext": "vault:v1:XjsPWPjqPrBi1N2Ms2s1QM798YyFWnO4TR4lsFA="
|
||||
},
|
||||
...
|
||||
]`,
|
||||
},
|
||||
},
|
||||
|
||||
Callbacks: map[logical.Operation]framework.OperationFunc{
|
||||
@@ -73,18 +52,13 @@ base64 encoded) goes like this:
|
||||
|
||||
func (b *backend) pathDecryptWrite(
|
||||
req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
||||
batchInputRaw := d.Get("batch_input").(string)
|
||||
batchInputRaw := d.Raw["batch_input"]
|
||||
var batchInputItems []BatchRequestItem
|
||||
var batchInput []byte
|
||||
var err error
|
||||
if len(batchInputRaw) != 0 {
|
||||
batchInput, err = base64.StdEncoding.DecodeString(batchInputRaw)
|
||||
if batchInputRaw != nil {
|
||||
err = mapstructure.Decode(batchInputRaw, &batchInputItems)
|
||||
if err != nil {
|
||||
return logical.ErrorResponse("failed to base64-decode batch input"), logical.ErrInvalidRequest
|
||||
}
|
||||
|
||||
if err := jsonutil.DecodeJSON([]byte(batchInput), &batchInputItems); err != nil {
|
||||
return nil, fmt.Errorf("invalid input: %v", err)
|
||||
return nil, fmt.Errorf("failed to parse batch input: %v", err)
|
||||
}
|
||||
|
||||
if len(batchInputItems) == 0 {
|
||||
@@ -99,24 +73,8 @@ func (b *backend) pathDecryptWrite(
|
||||
batchInputItems = make([]BatchRequestItem, 1)
|
||||
batchInputItems[0] = BatchRequestItem{
|
||||
Ciphertext: ciphertext,
|
||||
}
|
||||
|
||||
// Decode the context
|
||||
contextRaw := d.Get("context").(string)
|
||||
if len(contextRaw) != 0 {
|
||||
batchInputItems[0].Context, err = base64.StdEncoding.DecodeString(contextRaw)
|
||||
if err != nil {
|
||||
return logical.ErrorResponse("failed to base64-decode context"), logical.ErrInvalidRequest
|
||||
}
|
||||
}
|
||||
|
||||
// Decode the nonce
|
||||
nonceRaw := d.Get("nonce").(string)
|
||||
if len(nonceRaw) != 0 {
|
||||
batchInputItems[0].Nonce, err = base64.StdEncoding.DecodeString(nonceRaw)
|
||||
if err != nil {
|
||||
return logical.ErrorResponse("failed to base64-decode nonce"), logical.ErrInvalidRequest
|
||||
}
|
||||
Context: d.Get("context").(string),
|
||||
Nonce: d.Get("nonce").(string),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,6 +90,24 @@ func (b *backend) pathDecryptWrite(
|
||||
batchResponseItems[i].Error = "missing ciphertext to decrypt"
|
||||
continue
|
||||
}
|
||||
|
||||
// Decode the context
|
||||
if len(item.Context) != 0 {
|
||||
batchInputItems[i].DecodedContext, err = base64.StdEncoding.DecodeString(item.Context)
|
||||
if err != nil {
|
||||
batchResponseItems[i].Error = err.Error()
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// Decode the nonce
|
||||
if len(item.Nonce) != 0 {
|
||||
batchInputItems[i].DecodedNonce, err = base64.StdEncoding.DecodeString(item.Nonce)
|
||||
if err != nil {
|
||||
batchResponseItems[i].Error = err.Error()
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get the policy
|
||||
@@ -151,7 +127,7 @@ func (b *backend) pathDecryptWrite(
|
||||
continue
|
||||
}
|
||||
|
||||
plaintext, err := p.Decrypt(item.Context, item.Nonce, item.Ciphertext)
|
||||
plaintext, err := p.Decrypt(item.DecodedContext, item.DecodedNonce, item.Ciphertext)
|
||||
if err != nil {
|
||||
switch err.(type) {
|
||||
case errutil.UserError:
|
||||
@@ -165,13 +141,9 @@ func (b *backend) pathDecryptWrite(
|
||||
}
|
||||
|
||||
resp := &logical.Response{}
|
||||
if len(batchInputRaw) != 0 {
|
||||
batchResponseJSON, err := jsonutil.EncodeJSON(batchResponseItems)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to JSON encode batch response")
|
||||
}
|
||||
if batchInputRaw != nil {
|
||||
resp.Data = map[string]interface{}{
|
||||
"batch_results": string(batchResponseJSON),
|
||||
"batch_results": batchResponseItems,
|
||||
}
|
||||
} else {
|
||||
if batchResponseItems[0].Error != "" {
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
package transit
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/vault/helper/jsonutil"
|
||||
"github.com/hashicorp/vault/logical"
|
||||
)
|
||||
|
||||
@@ -15,10 +13,13 @@ func TestTransit_BatchDecryptionCase1(t *testing.T) {
|
||||
|
||||
b, s := createBackendWithStorage(t)
|
||||
|
||||
batchEncryptionInput := `[{"plaintext":"dGhlIHF1aWNrIGJyb3duIGZveA=="},{"plaintext":"Cg=="}]`
|
||||
batchEncryptionInputB64 := base64.StdEncoding.EncodeToString([]byte(batchEncryptionInput))
|
||||
batchEncryptionInput := []interface{}{
|
||||
map[string]interface{}{"plaintext": "dGhlIHF1aWNrIGJyb3duIGZveA=="},
|
||||
map[string]interface{}{"plaintext": "Cg=="},
|
||||
}
|
||||
|
||||
batchEncryptionData := map[string]interface{}{
|
||||
"batch_input": batchEncryptionInputB64,
|
||||
"batch_input": batchEncryptionInput,
|
||||
}
|
||||
|
||||
batchEncryptionReq := &logical.Request{
|
||||
@@ -32,9 +33,8 @@ func TestTransit_BatchDecryptionCase1(t *testing.T) {
|
||||
t.Fatalf("err:%v resp:%#v", err, resp)
|
||||
}
|
||||
|
||||
batchDecryptionInput := resp.Data["batch_results"].(string)
|
||||
batchDecryptionData := map[string]interface{}{
|
||||
"batch_input": batchDecryptionInput,
|
||||
"batch_input": resp.Data["batch_results"],
|
||||
}
|
||||
|
||||
batchDecryptionReq := &logical.Request{
|
||||
@@ -56,10 +56,12 @@ func TestTransit_BatchDecryptionCase2(t *testing.T) {
|
||||
|
||||
b, s := createBackendWithStorage(t)
|
||||
|
||||
batchEncryptionInput := `[{"plaintext":"dGhlIHF1aWNrIGJyb3duIGZveA=="},{"plaintext":"Cg=="}]`
|
||||
batchEncryptionInputB64 := base64.StdEncoding.EncodeToString([]byte(batchEncryptionInput))
|
||||
batchEncryptionInput := []interface{}{
|
||||
map[string]interface{}{"plaintext": "Cg=="},
|
||||
map[string]interface{}{"plaintext": "dGhlIHF1aWNrIGJyb3duIGZveA=="},
|
||||
}
|
||||
batchEncryptionData := map[string]interface{}{
|
||||
"batch_input": batchEncryptionInputB64,
|
||||
"batch_input": batchEncryptionInput,
|
||||
}
|
||||
|
||||
batchEncryptionReq := &logical.Request{
|
||||
@@ -73,10 +75,13 @@ func TestTransit_BatchDecryptionCase2(t *testing.T) {
|
||||
t.Fatalf("err:%v resp:%#v", err, resp)
|
||||
}
|
||||
|
||||
batchDecryptionInput := resp.Data["batch_results"].(string)
|
||||
batchDecryptionInputB64 := base64.StdEncoding.EncodeToString([]byte(batchDecryptionInput))
|
||||
batchResponseItems := resp.Data["batch_results"].([]BatchResponseItem)
|
||||
batchDecryptionInput := make([]interface{}, len(batchResponseItems))
|
||||
for i, item := range batchResponseItems {
|
||||
batchDecryptionInput[i] = map[string]interface{}{"ciphertext": item.Ciphertext}
|
||||
}
|
||||
batchDecryptionData := map[string]interface{}{
|
||||
"batch_input": batchDecryptionInputB64,
|
||||
"batch_input": batchDecryptionInput,
|
||||
}
|
||||
|
||||
batchDecryptionReq := &logical.Request{
|
||||
@@ -90,14 +95,11 @@ func TestTransit_BatchDecryptionCase2(t *testing.T) {
|
||||
t.Fatalf("err:%v resp:%#v", err, resp)
|
||||
}
|
||||
|
||||
var batchDecryptionResponseArray []BatchResponseItem
|
||||
if err := jsonutil.DecodeJSON([]byte(resp.Data["batch_results"].(string)), &batchDecryptionResponseArray); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
batchDecryptionResponseItems := resp.Data["batch_results"].([]BatchResponseItem)
|
||||
|
||||
plaintext1 := "dGhlIHF1aWNrIGJyb3duIGZveA=="
|
||||
plaintext2 := "Cg=="
|
||||
for _, item := range batchDecryptionResponseArray {
|
||||
for _, item := range batchDecryptionResponseItems {
|
||||
if item.Plaintext != plaintext1 && item.Plaintext != plaintext2 {
|
||||
t.Fatalf("bad: plaintext: %q", item.Plaintext)
|
||||
}
|
||||
@@ -127,13 +129,13 @@ func TestTransit_BatchDecryptionCase3(t *testing.T) {
|
||||
t.Fatalf("err:%v resp:%#v", err, resp)
|
||||
}
|
||||
|
||||
batchInput := `[{"plaintext":"dGhlIHF1aWNrIGJyb3duIGZveA==",
|
||||
"context":"dGVzdGNvbnRleHQ="},{"plaintext":"dGhlIHF1aWNrIGJyb3duIGZveA==",
|
||||
"context":"dGVzdGNvbnRleHQ="}]`
|
||||
batchInput := []interface{}{
|
||||
map[string]interface{}{"plaintext": "dGhlIHF1aWNrIGJyb3duIGZveA==", "context": "dGVzdGNvbnRleHQ="},
|
||||
map[string]interface{}{"plaintext": "dGhlIHF1aWNrIGJyb3duIGZveA==", "context": "dGVzdGNvbnRleHQ="},
|
||||
}
|
||||
|
||||
batchInputB64 := base64.StdEncoding.EncodeToString([]byte(batchInput))
|
||||
batchData := map[string]interface{}{
|
||||
"batch_input": batchInputB64,
|
||||
"batch_input": batchInput,
|
||||
}
|
||||
batchReq := &logical.Request{
|
||||
Operation: logical.UpdateOperation,
|
||||
@@ -146,24 +148,15 @@ func TestTransit_BatchDecryptionCase3(t *testing.T) {
|
||||
t.Fatalf("err:%v resp:%#v", err, resp)
|
||||
}
|
||||
|
||||
var decryptionRequestItems []BatchRequestItem
|
||||
var batchResponseArray []BatchRequestItem
|
||||
if err := jsonutil.DecodeJSON([]byte(resp.Data["batch_results"].(string)), &batchResponseArray); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, item := range batchResponseArray {
|
||||
item.Context = []byte("testcontext")
|
||||
decryptionRequestItems = append(decryptionRequestItems, item)
|
||||
batchDecryptionInputItems := resp.Data["batch_results"].([]BatchResponseItem)
|
||||
|
||||
batchDecryptionInput := make([]interface{}, len(batchDecryptionInputItems))
|
||||
for i, item := range batchDecryptionInputItems {
|
||||
batchDecryptionInput[i] = map[string]interface{}{"ciphertext": item.Ciphertext, "context": "dGVzdGNvbnRleHQ="}
|
||||
}
|
||||
|
||||
batchDecryptionInput, err := jsonutil.EncodeJSON(decryptionRequestItems)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to encode batch decryption input")
|
||||
}
|
||||
|
||||
batchDecryptionInputB64 := base64.StdEncoding.EncodeToString(batchDecryptionInput)
|
||||
batchDecryptionData := map[string]interface{}{
|
||||
"batch_input": batchDecryptionInputB64,
|
||||
"batch_input": batchDecryptionInput,
|
||||
}
|
||||
|
||||
batchDecryptionReq := &logical.Request{
|
||||
@@ -177,13 +170,10 @@ func TestTransit_BatchDecryptionCase3(t *testing.T) {
|
||||
t.Fatalf("err:%v resp:%#v", err, resp)
|
||||
}
|
||||
|
||||
var batchDecryptionResponseArray []BatchResponseItem
|
||||
if err := jsonutil.DecodeJSON([]byte(resp.Data["batch_results"].(string)), &batchDecryptionResponseArray); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
batchDecryptionResponseItems := resp.Data["batch_results"].([]BatchResponseItem)
|
||||
|
||||
plaintext := "dGhlIHF1aWNrIGJyb3duIGZveA=="
|
||||
for _, item := range batchDecryptionResponseArray {
|
||||
for _, item := range batchDecryptionResponseItems {
|
||||
if item.Plaintext != plaintext {
|
||||
t.Fatalf("bad: plaintext. Expected: %q, Actual: %q", plaintext, item.Plaintext)
|
||||
}
|
||||
|
||||
@@ -6,16 +6,19 @@ import (
|
||||
"sync"
|
||||
|
||||
"github.com/hashicorp/vault/helper/errutil"
|
||||
"github.com/hashicorp/vault/helper/jsonutil"
|
||||
"github.com/hashicorp/vault/helper/keysutil"
|
||||
"github.com/hashicorp/vault/logical"
|
||||
"github.com/hashicorp/vault/logical/framework"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
)
|
||||
|
||||
// BatchRequestItem represents a request item for batch processing
|
||||
type BatchRequestItem struct {
|
||||
// Context for key derivation. This is required for derived keys.
|
||||
Context []byte `json:"context" structs:"context" mapstructure:"context"`
|
||||
Context string `json:"context" structs:"context" mapstructure:"context"`
|
||||
|
||||
// DecodedContext is the base64 decoded version of Context
|
||||
DecodedContext []byte
|
||||
|
||||
// Plaintext for encryption
|
||||
Plaintext string `json:"plaintext" structs:"plaintext" mapstructure:"plaintext"`
|
||||
@@ -24,7 +27,10 @@ type BatchRequestItem struct {
|
||||
Ciphertext string `json:"ciphertext" structs:"ciphertext" mapstructure:"ciphertext"`
|
||||
|
||||
// Nonce to be used when v1 convergent encryption is used
|
||||
Nonce []byte `json:"nonce" structs:"nonce" mapstructure:"nonce"`
|
||||
Nonce string `json:"nonce" structs:"nonce" mapstructure:"nonce"`
|
||||
|
||||
// DecodedNonce is the base64 decoded version of Nonce
|
||||
DecodedNonce []byte
|
||||
}
|
||||
|
||||
// BatchResponseItem represents a response item for batch processing
|
||||
@@ -94,27 +100,6 @@ same ciphertext is generated. It is *very important* when using this mode that
|
||||
you ensure that all nonces are unique for a given context. Failing to do so
|
||||
will severely impact the ciphertext's security.`,
|
||||
},
|
||||
|
||||
"batch_input": &framework.FieldSchema{
|
||||
Type: framework.TypeString,
|
||||
Description: `
|
||||
Base64 encoded list of items to be encrypted in a single batch. When this
|
||||
parameter is set, if the parameters 'plaintext', 'context' and 'nonce' are also
|
||||
set, they will be ignored. JSON format for the input (which should be base64
|
||||
encoded) goes like this:
|
||||
|
||||
[
|
||||
{
|
||||
"context": "c2FtcGxlY29udGV4dA==",
|
||||
"plaintext": "dGhlIHF1aWNrIGJyb3duIGZveA=="
|
||||
},
|
||||
{
|
||||
"context": "YW5vdGhlcnNhbXBsZWNvbnRleHQ=",
|
||||
"plaintext": "dGhlIHF1aWNrIGJyb3duIGZveA=="
|
||||
},
|
||||
...
|
||||
]`,
|
||||
},
|
||||
},
|
||||
|
||||
Callbacks: map[logical.Operation]framework.OperationFunc{
|
||||
@@ -147,17 +132,12 @@ func (b *backend) pathEncryptWrite(
|
||||
name := d.Get("name").(string)
|
||||
var err error
|
||||
|
||||
batchInputRaw := d.Get("batch_input").(string)
|
||||
var batchInput []byte
|
||||
batchInputRaw := d.Raw["batch_input"]
|
||||
var batchInputItems []BatchRequestItem
|
||||
if len(batchInputRaw) != 0 {
|
||||
batchInput, err = base64.StdEncoding.DecodeString(batchInputRaw)
|
||||
if batchInputRaw != nil {
|
||||
err = mapstructure.Decode(batchInputRaw, &batchInputItems)
|
||||
if err != nil {
|
||||
return logical.ErrorResponse("failed to base64-decode batch input"), logical.ErrInvalidRequest
|
||||
}
|
||||
|
||||
if err := jsonutil.DecodeJSON([]byte(batchInput), &batchInputItems); err != nil {
|
||||
return nil, fmt.Errorf("invalid input: %v", err)
|
||||
return nil, fmt.Errorf("failed to parse batch input: %v", err)
|
||||
}
|
||||
|
||||
if len(batchInputItems) == 0 {
|
||||
@@ -172,24 +152,8 @@ func (b *backend) pathEncryptWrite(
|
||||
batchInputItems = make([]BatchRequestItem, 1)
|
||||
batchInputItems[0] = BatchRequestItem{
|
||||
Plaintext: valueRaw.(string),
|
||||
}
|
||||
|
||||
// Decode the context
|
||||
contextRaw := d.Get("context").(string)
|
||||
if len(contextRaw) != 0 {
|
||||
batchInputItems[0].Context, err = base64.StdEncoding.DecodeString(contextRaw)
|
||||
if err != nil {
|
||||
return logical.ErrorResponse("failed to base64-decode context"), logical.ErrInvalidRequest
|
||||
}
|
||||
}
|
||||
|
||||
// Decode the nonce
|
||||
nonceRaw := d.Get("nonce").(string)
|
||||
if len(nonceRaw) != 0 {
|
||||
batchInputItems[0].Nonce, err = base64.StdEncoding.DecodeString(nonceRaw)
|
||||
if err != nil {
|
||||
return logical.ErrorResponse("failed to base64-decode nonce"), logical.ErrInvalidRequest
|
||||
}
|
||||
Context: d.Get("context").(string),
|
||||
Nonce: d.Get("nonce").(string),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,6 +174,24 @@ func (b *backend) pathEncryptWrite(
|
||||
batchResponseItems[i].Error = "failed to base64-decode plaintext"
|
||||
continue
|
||||
}
|
||||
|
||||
// Decode the context
|
||||
if len(item.Context) != 0 {
|
||||
batchInputItems[i].DecodedContext, err = base64.StdEncoding.DecodeString(item.Context)
|
||||
if err != nil {
|
||||
batchResponseItems[i].Error = err.Error()
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// Decode the nonce
|
||||
if len(item.Nonce) != 0 {
|
||||
batchInputItems[i].DecodedNonce, err = base64.StdEncoding.DecodeString(item.Nonce)
|
||||
if err != nil {
|
||||
batchResponseItems[i].Error = err.Error()
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get the policy
|
||||
@@ -262,7 +244,7 @@ func (b *backend) pathEncryptWrite(
|
||||
continue
|
||||
}
|
||||
|
||||
ciphertext, err := p.Encrypt(item.Context, item.Nonce, item.Plaintext)
|
||||
ciphertext, err := p.Encrypt(item.DecodedContext, item.DecodedNonce, item.Plaintext)
|
||||
if err != nil {
|
||||
switch err.(type) {
|
||||
case errutil.UserError:
|
||||
@@ -281,13 +263,9 @@ func (b *backend) pathEncryptWrite(
|
||||
}
|
||||
|
||||
resp := &logical.Response{}
|
||||
if len(batchInputRaw) != 0 {
|
||||
batchResponseJSON, err := jsonutil.EncodeJSON(batchResponseItems)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to JSON encode batch response")
|
||||
}
|
||||
if batchInputRaw != nil {
|
||||
resp.Data = map[string]interface{}{
|
||||
"batch_results": string(batchResponseJSON),
|
||||
"batch_results": batchResponseItems,
|
||||
}
|
||||
} else {
|
||||
if batchResponseItems[0].Error != "" {
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
package transit
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/vault/helper/jsonutil"
|
||||
"github.com/hashicorp/vault/logical"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
)
|
||||
@@ -14,6 +12,7 @@ import (
|
||||
func TestTransit_BatchEncryptionCase1(t *testing.T) {
|
||||
var resp *logical.Response
|
||||
var err error
|
||||
|
||||
b, s := createBackendWithStorage(t)
|
||||
|
||||
// Create the policy
|
||||
@@ -128,7 +127,7 @@ func TestTransit_BatchEncryptionCase3(t *testing.T) {
|
||||
|
||||
b, s := createBackendWithStorage(t)
|
||||
|
||||
batchInput := `[ {"plaintext":"dGhlIHF1aWNrIGJyb3duIGZveA=="}]`
|
||||
batchInput := `[{"plaintext":"dGhlIHF1aWNrIGJyb3duIGZveA=="}]`
|
||||
batchData := map[string]interface{}{
|
||||
"batch_input": batchInput,
|
||||
}
|
||||
@@ -162,10 +161,13 @@ func TestTransit_BatchEncryptionCase4(t *testing.T) {
|
||||
t.Fatalf("err:%v resp:%#v", err, resp)
|
||||
}
|
||||
|
||||
batchInput := `[{"plaintext":"dGhlIHF1aWNrIGJyb3duIGZveA=="},{"plaintext":"dGhlIHF1aWNrIGJyb3duIGZveA=="}]`
|
||||
batchInputB64 := base64.StdEncoding.EncodeToString([]byte(batchInput))
|
||||
batchInput := []interface{}{
|
||||
map[string]interface{}{"plaintext": "dGhlIHF1aWNrIGJyb3duIGZveA=="},
|
||||
map[string]interface{}{"plaintext": "dGhlIHF1aWNrIGJyb3duIGZveA=="},
|
||||
}
|
||||
|
||||
batchData := map[string]interface{}{
|
||||
"batch_input": batchInputB64,
|
||||
"batch_input": batchInput,
|
||||
}
|
||||
batchReq := &logical.Request{
|
||||
Operation: logical.UpdateOperation,
|
||||
@@ -178,10 +180,7 @@ func TestTransit_BatchEncryptionCase4(t *testing.T) {
|
||||
t.Fatalf("err:%v resp:%#v", err, resp)
|
||||
}
|
||||
|
||||
var batchResponseArray []BatchResponseItem
|
||||
if err := jsonutil.DecodeJSON([]byte(resp.Data["batch_results"].(string)), &batchResponseArray); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
batchResponseItems := resp.Data["batch_results"].([]BatchResponseItem)
|
||||
|
||||
decReq := &logical.Request{
|
||||
Operation: logical.UpdateOperation,
|
||||
@@ -191,7 +190,7 @@ func TestTransit_BatchEncryptionCase4(t *testing.T) {
|
||||
|
||||
plaintext := "dGhlIHF1aWNrIGJyb3duIGZveA=="
|
||||
|
||||
for _, item := range batchResponseArray {
|
||||
for _, item := range batchResponseItems {
|
||||
decReq.Data = map[string]interface{}{
|
||||
"ciphertext": item.Ciphertext,
|
||||
}
|
||||
@@ -229,14 +228,15 @@ func TestTransit_BatchEncryptionCase5(t *testing.T) {
|
||||
t.Fatalf("err:%v resp:%#v", err, resp)
|
||||
}
|
||||
|
||||
batchInput := `[{"plaintext":"dGhlIHF1aWNrIGJyb3duIGZveA==",
|
||||
"context":"dmlzaGFsCg=="},{"plaintext":"dGhlIHF1aWNrIGJyb3duIGZveA==",
|
||||
"context":"dmlzaGFsCg=="}]`
|
||||
|
||||
batchInputB64 := base64.StdEncoding.EncodeToString([]byte(batchInput))
|
||||
batchData := map[string]interface{}{
|
||||
"batch_input": batchInputB64,
|
||||
batchInput := []interface{}{
|
||||
map[string]interface{}{"plaintext": "dGhlIHF1aWNrIGJyb3duIGZveA==", "context": "dmlzaGFsCg=="},
|
||||
map[string]interface{}{"plaintext": "dGhlIHF1aWNrIGJyb3duIGZveA==", "context": "dmlzaGFsCg=="},
|
||||
}
|
||||
|
||||
batchData := map[string]interface{}{
|
||||
"batch_input": batchInput,
|
||||
}
|
||||
|
||||
batchReq := &logical.Request{
|
||||
Operation: logical.UpdateOperation,
|
||||
Path: "encrypt/existing_key",
|
||||
@@ -248,10 +248,7 @@ func TestTransit_BatchEncryptionCase5(t *testing.T) {
|
||||
t.Fatalf("err:%v resp:%#v", err, resp)
|
||||
}
|
||||
|
||||
var batchResponseArray []BatchResponseItem
|
||||
if err := jsonutil.DecodeJSON([]byte(resp.Data["batch_results"].(string)), &batchResponseArray); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
batchResponseItems := resp.Data["batch_results"].([]BatchResponseItem)
|
||||
|
||||
decReq := &logical.Request{
|
||||
Operation: logical.UpdateOperation,
|
||||
@@ -261,7 +258,7 @@ func TestTransit_BatchEncryptionCase5(t *testing.T) {
|
||||
|
||||
plaintext := "dGhlIHF1aWNrIGJyb3duIGZveA=="
|
||||
|
||||
for _, item := range batchResponseArray {
|
||||
for _, item := range batchResponseItems {
|
||||
decReq.Data = map[string]interface{}{
|
||||
"ciphertext": item.Ciphertext,
|
||||
"context": "dmlzaGFsCg==",
|
||||
@@ -284,10 +281,13 @@ func TestTransit_BatchEncryptionCase6(t *testing.T) {
|
||||
|
||||
b, s := createBackendWithStorage(t)
|
||||
|
||||
batchInput := `[{"plaintext":"dGhlIHF1aWNrIGJyb3duIGZveA=="},{"plaintext":"dGhlIHF1aWNrIGJyb3duIGZveA=="}]`
|
||||
batchInputB64 := base64.StdEncoding.EncodeToString([]byte(batchInput))
|
||||
batchInput := []interface{}{
|
||||
map[string]interface{}{"plaintext": "dGhlIHF1aWNrIGJyb3duIGZveA=="},
|
||||
map[string]interface{}{"plaintext": "dGhlIHF1aWNrIGJyb3duIGZveA=="},
|
||||
}
|
||||
|
||||
batchData := map[string]interface{}{
|
||||
"batch_input": batchInputB64,
|
||||
"batch_input": batchInput,
|
||||
}
|
||||
batchReq := &logical.Request{
|
||||
Operation: logical.CreateOperation,
|
||||
@@ -300,10 +300,7 @@ func TestTransit_BatchEncryptionCase6(t *testing.T) {
|
||||
t.Fatalf("err:%v resp:%#v", err, resp)
|
||||
}
|
||||
|
||||
var batchResponseArray []interface{}
|
||||
if err := jsonutil.DecodeJSON([]byte(resp.Data["batch_results"].(string)), &batchResponseArray); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
batchResponseItems := resp.Data["batch_results"].([]BatchResponseItem)
|
||||
|
||||
decReq := &logical.Request{
|
||||
Operation: logical.UpdateOperation,
|
||||
@@ -313,7 +310,7 @@ func TestTransit_BatchEncryptionCase6(t *testing.T) {
|
||||
|
||||
plaintext := "dGhlIHF1aWNrIGJyb3duIGZveA=="
|
||||
|
||||
for _, responseItem := range batchResponseArray {
|
||||
for _, responseItem := range batchResponseItems {
|
||||
var item BatchResponseItem
|
||||
if err := mapstructure.Decode(responseItem, &item); err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -339,13 +336,13 @@ func TestTransit_BatchEncryptionCase7(t *testing.T) {
|
||||
|
||||
b, s := createBackendWithStorage(t)
|
||||
|
||||
batchInput := `[{"plaintext":"dGhlIHF1aWNrIGJyb3duIGZveA==",
|
||||
"context":"dmlzaGFsCg=="},{"plaintext":"dGhlIHF1aWNrIGJyb3duIGZveA==",
|
||||
"context":"dmlzaGFsCg=="}]`
|
||||
batchInput := []interface{}{
|
||||
map[string]interface{}{"plaintext": "dGhlIHF1aWNrIGJyb3duIGZveA==", "context": "dmlzaGFsCg=="},
|
||||
map[string]interface{}{"plaintext": "dGhlIHF1aWNrIGJyb3duIGZveA==", "context": "dmlzaGFsCg=="},
|
||||
}
|
||||
|
||||
batchInputB64 := base64.StdEncoding.EncodeToString([]byte(batchInput))
|
||||
batchData := map[string]interface{}{
|
||||
"batch_input": batchInputB64,
|
||||
"batch_input": batchInput,
|
||||
}
|
||||
batchReq := &logical.Request{
|
||||
Operation: logical.CreateOperation,
|
||||
@@ -358,10 +355,7 @@ func TestTransit_BatchEncryptionCase7(t *testing.T) {
|
||||
t.Fatalf("err:%v resp:%#v", err, resp)
|
||||
}
|
||||
|
||||
var batchResponseArray []BatchResponseItem
|
||||
if err := jsonutil.DecodeJSON([]byte(resp.Data["batch_results"].(string)), &batchResponseArray); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
batchResponseItems := resp.Data["batch_results"].([]BatchResponseItem)
|
||||
|
||||
decReq := &logical.Request{
|
||||
Operation: logical.UpdateOperation,
|
||||
@@ -371,7 +365,7 @@ func TestTransit_BatchEncryptionCase7(t *testing.T) {
|
||||
|
||||
plaintext := "dGhlIHF1aWNrIGJyb3duIGZveA=="
|
||||
|
||||
for _, item := range batchResponseArray {
|
||||
for _, item := range batchResponseItems {
|
||||
decReq.Data = map[string]interface{}{
|
||||
"ciphertext": item.Ciphertext,
|
||||
"context": "dmlzaGFsCg==",
|
||||
@@ -405,10 +399,11 @@ func TestTransit_BatchEncryptionCase8(t *testing.T) {
|
||||
t.Fatalf("err:%v resp:%#v", err, resp)
|
||||
}
|
||||
|
||||
batchInput := `[{"plaintext":"simple_plaintext"}]`
|
||||
batchInputB64 := base64.StdEncoding.EncodeToString([]byte(batchInput))
|
||||
batchInput := []interface{}{
|
||||
map[string]interface{}{"plaintext": "simple_plaintext"},
|
||||
}
|
||||
batchData := map[string]interface{}{
|
||||
"batch_input": batchInputB64,
|
||||
"batch_input": batchInput,
|
||||
}
|
||||
batchReq := &logical.Request{
|
||||
Operation: logical.UpdateOperation,
|
||||
@@ -447,11 +442,13 @@ func TestTransit_BatchEncryptionCase9(t *testing.T) {
|
||||
|
||||
b, s := createBackendWithStorage(t)
|
||||
|
||||
batchInput := `[{"plaintext":"dGhlIHF1aWNrIGJyb3duIGZveA=="},{"plaintext":"dGhlIHF1aWNrIGJyb3duIGZveA=="}]`
|
||||
batchInputB64 := base64.StdEncoding.EncodeToString([]byte(batchInput))
|
||||
batchInput := []interface{}{
|
||||
map[string]interface{}{"plaintext": "dGhlIHF1aWNrIGJyb3duIGZveA=="},
|
||||
map[string]interface{}{"plaintext": "dGhlIHF1aWNrIGJyb3duIGZveA=="},
|
||||
}
|
||||
plaintext := "dGhlIHF1aWNrIGJyb3duIGZveA=="
|
||||
batchData := map[string]interface{}{
|
||||
"batch_input": batchInputB64,
|
||||
"batch_input": batchInput,
|
||||
"plaintext": plaintext,
|
||||
}
|
||||
batchReq := &logical.Request{
|
||||
@@ -477,13 +474,13 @@ func TestTransit_BatchEncryptionCase10(t *testing.T) {
|
||||
|
||||
b, s := createBackendWithStorage(t)
|
||||
|
||||
batchInput := `[{"plaintext":"dGhlIHF1aWNrIGJyb3duIGZveA=="
|
||||
},{"plaintext":"dGhlIHF1aWNrIGJyb3duIGZveA==",
|
||||
"context":"dmlzaGFsCg=="}]`
|
||||
batchInput := []interface{}{
|
||||
map[string]interface{}{"plaintext": "dGhlIHF1aWNrIGJyb3duIGZveA=="},
|
||||
map[string]interface{}{"plaintext": "dGhlIHF1aWNrIGJyb3duIGZveA==", "context": "dmlzaGFsCg=="},
|
||||
}
|
||||
|
||||
batchInputB64 := base64.StdEncoding.EncodeToString([]byte(batchInput))
|
||||
batchData := map[string]interface{}{
|
||||
"batch_input": batchInputB64,
|
||||
"batch_input": batchInput,
|
||||
}
|
||||
|
||||
batchReq := &logical.Request{
|
||||
@@ -498,19 +495,19 @@ func TestTransit_BatchEncryptionCase10(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Case11: Incorrect inputs for context and nonce should not be ignored
|
||||
// Case11: Incorrect inputs for context and nonce should not fail the operation
|
||||
func TestTransit_BatchEncryptionCase11(t *testing.T) {
|
||||
var err error
|
||||
|
||||
b, s := createBackendWithStorage(t)
|
||||
|
||||
batchInput := `[{"plaintext":"dGhlIHF1aWNrIGJyb3duIGZveA==",
|
||||
"context":"dmlzaGFsCg=="},{"plaintext":"dGhlIHF1aWNrIGJyb3duIGZveA==",
|
||||
"context":"not-encoded"}]`
|
||||
batchInput := []interface{}{
|
||||
map[string]interface{}{"plaintext": "dGhlIHF1aWNrIGJyb3duIGZveA==", "context": "dmlzaGFsCg=="},
|
||||
map[string]interface{}{"plaintext": "dGhlIHF1aWNrIGJyb3duIGZveA==", "context": "not-encoded"},
|
||||
}
|
||||
|
||||
batchInputB64 := base64.StdEncoding.EncodeToString([]byte(batchInput))
|
||||
batchData := map[string]interface{}{
|
||||
"batch_input": batchInputB64,
|
||||
"batch_input": batchInput,
|
||||
}
|
||||
batchReq := &logical.Request{
|
||||
Operation: logical.CreateOperation,
|
||||
@@ -519,30 +516,23 @@ func TestTransit_BatchEncryptionCase11(t *testing.T) {
|
||||
Data: batchData,
|
||||
}
|
||||
_, err = b.HandleRequest(batchReq)
|
||||
if err == nil {
|
||||
t.Fatalf("expected an error")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Case12: Invalid batch input
|
||||
func TestTransit_BatchEncryptionCase12(t *testing.T) {
|
||||
var err error
|
||||
|
||||
b, s := createBackendWithStorage(t)
|
||||
|
||||
batchInput := `{
|
||||
"randomjson": [{
|
||||
"plaintext": "dGhlIHF1aWNrIGJyb3duIGZveA==",
|
||||
"context": "dmlzaGFsCg=="
|
||||
}, {
|
||||
"plaintext": "dGhlIHF1aWNrIGJyb3duIGZveA==",
|
||||
"context": "not-encoded"
|
||||
}]
|
||||
}`
|
||||
batchInput := []interface{}{
|
||||
map[string]interface{}{},
|
||||
"unexpected_interface",
|
||||
}
|
||||
|
||||
batchInputB64 := base64.StdEncoding.EncodeToString([]byte(batchInput))
|
||||
batchData := map[string]interface{}{
|
||||
"batch_input": batchInputB64,
|
||||
"batch_input": batchInput,
|
||||
}
|
||||
batchReq := &logical.Request{
|
||||
Operation: logical.CreateOperation,
|
||||
|
||||
@@ -5,9 +5,9 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/vault/helper/errutil"
|
||||
"github.com/hashicorp/vault/helper/jsonutil"
|
||||
"github.com/hashicorp/vault/logical"
|
||||
"github.com/hashicorp/vault/logical/framework"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
)
|
||||
|
||||
func (b *backend) pathRewrap() *framework.Path {
|
||||
@@ -33,27 +33,6 @@ func (b *backend) pathRewrap() *framework.Path {
|
||||
Type: framework.TypeString,
|
||||
Description: "Nonce for when convergent encryption is used",
|
||||
},
|
||||
|
||||
"batch_input": &framework.FieldSchema{
|
||||
Type: framework.TypeString,
|
||||
Description: `
|
||||
Base64 encoded list of items to be rewrapped in a single batch. When this
|
||||
parameter is set, if the parameters 'ciphertext', 'context' and 'nonce' are
|
||||
also set, they will be ignored. JSON format for the input (which should be
|
||||
bae64 encoded) goes like this:
|
||||
|
||||
[
|
||||
{
|
||||
"context": "c2FtcGxlY29udGV4dA==",
|
||||
"ciphertext": "vault:v1:/DupSiSbX/ATkGmKAmhqD0tvukByrx6gmps7dVI="
|
||||
},
|
||||
{
|
||||
"context": "YW5vdGhlcnNhbXBsZWNvbnRleHQ=",
|
||||
"ciphertext": "vault:v1:XjsPWPjqPrBi1N2Ms2s1QM798YyFWnO4TR4lsFA="
|
||||
},
|
||||
...
|
||||
]`,
|
||||
},
|
||||
},
|
||||
|
||||
Callbacks: map[logical.Operation]framework.OperationFunc{
|
||||
@@ -67,18 +46,13 @@ bae64 encoded) goes like this:
|
||||
|
||||
func (b *backend) pathRewrapWrite(
|
||||
req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
||||
batchInputRaw := d.Get("batch_input").(string)
|
||||
batchInputRaw := d.Raw["batch_input"]
|
||||
var batchInputItems []BatchRequestItem
|
||||
var batchInput []byte
|
||||
var err error
|
||||
if len(batchInputRaw) != 0 {
|
||||
batchInput, err = base64.StdEncoding.DecodeString(batchInputRaw)
|
||||
if batchInputRaw != nil {
|
||||
err = mapstructure.Decode(batchInputRaw, &batchInputItems)
|
||||
if err != nil {
|
||||
return logical.ErrorResponse("failed to base64-decode batch input"), logical.ErrInvalidRequest
|
||||
}
|
||||
|
||||
if err := jsonutil.DecodeJSON([]byte(batchInput), &batchInputItems); err != nil {
|
||||
return nil, fmt.Errorf("invalid input: %v", err)
|
||||
return nil, fmt.Errorf("failed to parse batch input: %v", err)
|
||||
}
|
||||
|
||||
if len(batchInputItems) == 0 {
|
||||
@@ -93,24 +67,8 @@ func (b *backend) pathRewrapWrite(
|
||||
batchInputItems = make([]BatchRequestItem, 1)
|
||||
batchInputItems[0] = BatchRequestItem{
|
||||
Ciphertext: ciphertext,
|
||||
}
|
||||
|
||||
// Decode the context
|
||||
contextRaw := d.Get("context").(string)
|
||||
if len(contextRaw) != 0 {
|
||||
batchInputItems[0].Context, err = base64.StdEncoding.DecodeString(contextRaw)
|
||||
if err != nil {
|
||||
return logical.ErrorResponse("failed to base64-decode context"), logical.ErrInvalidRequest
|
||||
}
|
||||
}
|
||||
|
||||
// Decode the nonce
|
||||
nonceRaw := d.Get("nonce").(string)
|
||||
if len(nonceRaw) != 0 {
|
||||
batchInputItems[0].Nonce, err = base64.StdEncoding.DecodeString(nonceRaw)
|
||||
if err != nil {
|
||||
return logical.ErrorResponse("failed to base64-decode nonce"), logical.ErrInvalidRequest
|
||||
}
|
||||
Context: d.Get("context").(string),
|
||||
Nonce: d.Get("nonce").(string),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,6 +84,24 @@ func (b *backend) pathRewrapWrite(
|
||||
batchResponseItems[i].Error = "missing ciphertext to decrypt"
|
||||
continue
|
||||
}
|
||||
|
||||
// Decode the context
|
||||
if len(item.Context) != 0 {
|
||||
batchInputItems[i].DecodedContext, err = base64.StdEncoding.DecodeString(item.Context)
|
||||
if err != nil {
|
||||
batchResponseItems[i].Error = err.Error()
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// Decode the nonce
|
||||
if len(item.Nonce) != 0 {
|
||||
batchInputItems[i].DecodedNonce, err = base64.StdEncoding.DecodeString(item.Nonce)
|
||||
if err != nil {
|
||||
batchResponseItems[i].Error = err.Error()
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get the policy
|
||||
@@ -145,7 +121,7 @@ func (b *backend) pathRewrapWrite(
|
||||
continue
|
||||
}
|
||||
|
||||
plaintext, err := p.Decrypt(item.Context, item.Nonce, item.Ciphertext)
|
||||
plaintext, err := p.Decrypt(item.DecodedContext, item.DecodedNonce, item.Ciphertext)
|
||||
if err != nil {
|
||||
switch err.(type) {
|
||||
case errutil.UserError:
|
||||
@@ -156,7 +132,7 @@ func (b *backend) pathRewrapWrite(
|
||||
}
|
||||
}
|
||||
|
||||
ciphertext, err := p.Encrypt(item.Context, item.Nonce, plaintext)
|
||||
ciphertext, err := p.Encrypt(item.DecodedContext, item.DecodedNonce, plaintext)
|
||||
if err != nil {
|
||||
switch err.(type) {
|
||||
case errutil.UserError:
|
||||
@@ -177,13 +153,9 @@ func (b *backend) pathRewrapWrite(
|
||||
}
|
||||
|
||||
resp := &logical.Response{}
|
||||
if len(batchInputRaw) != 0 {
|
||||
batchResponseJSON, err := jsonutil.EncodeJSON(batchResponseItems)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to JSON encode batch response")
|
||||
}
|
||||
if batchInputRaw != nil {
|
||||
resp.Data = map[string]interface{}{
|
||||
"batch_results": string(batchResponseJSON),
|
||||
"batch_results": batchResponseItems,
|
||||
}
|
||||
} else {
|
||||
if batchResponseItems[0].Error != "" {
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
package transit
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/vault/helper/jsonutil"
|
||||
"github.com/hashicorp/vault/logical"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
)
|
||||
|
||||
// Check the normal flow of rewrap
|
||||
@@ -205,30 +202,33 @@ func TestTransit_BatchRewrapCase3(t *testing.T) {
|
||||
|
||||
b, s := createBackendWithStorage(t)
|
||||
|
||||
batchInput := `[{"plaintext":"dGhlIHF1aWNrIGJyb3duIGZveA=="},{"plaintext":"dmlzaGFsCg=="}]`
|
||||
batchInputB64 := base64.StdEncoding.EncodeToString([]byte(batchInput))
|
||||
batchData := map[string]interface{}{
|
||||
"batch_input": batchInputB64,
|
||||
batchEncryptionInput := []interface{}{
|
||||
map[string]interface{}{"plaintext": "dmlzaGFsCg=="},
|
||||
map[string]interface{}{"plaintext": "dGhlIHF1aWNrIGJyb3duIGZveA=="},
|
||||
}
|
||||
batchEncryptionData := map[string]interface{}{
|
||||
"batch_input": batchEncryptionInput,
|
||||
}
|
||||
batchReq := &logical.Request{
|
||||
Operation: logical.CreateOperation,
|
||||
Path: "encrypt/upserted_key",
|
||||
Storage: s,
|
||||
Data: batchData,
|
||||
Data: batchEncryptionData,
|
||||
}
|
||||
resp, err = b.HandleRequest(batchReq)
|
||||
if err != nil || (resp != nil && resp.IsError()) {
|
||||
t.Fatalf("err:%v resp:%#v", err, resp)
|
||||
}
|
||||
|
||||
var batchEncryptionResponseArray []interface{}
|
||||
if err := jsonutil.DecodeJSON([]byte(resp.Data["batch_results"].(string)), &batchEncryptionResponseArray); err != nil {
|
||||
t.Fatal(err)
|
||||
batchEncryptionResponseItems := resp.Data["batch_results"].([]BatchResponseItem)
|
||||
|
||||
batchRewrapInput := make([]interface{}, len(batchEncryptionResponseItems))
|
||||
for i, item := range batchEncryptionResponseItems {
|
||||
batchRewrapInput[i] = map[string]interface{}{"ciphertext": item.Ciphertext}
|
||||
}
|
||||
|
||||
batchInputB64 = base64.StdEncoding.EncodeToString([]byte(resp.Data["batch_results"].(string)))
|
||||
rewrapData := map[string]interface{}{
|
||||
"batch_input": batchInputB64,
|
||||
batchRewrapData := map[string]interface{}{
|
||||
"batch_input": batchRewrapInput,
|
||||
}
|
||||
|
||||
rotateReq := &logical.Request{
|
||||
@@ -245,7 +245,7 @@ func TestTransit_BatchRewrapCase3(t *testing.T) {
|
||||
Operation: logical.UpdateOperation,
|
||||
Path: "rewrap/upserted_key",
|
||||
Storage: s,
|
||||
Data: rewrapData,
|
||||
Data: batchRewrapData,
|
||||
}
|
||||
|
||||
resp, err = b.HandleRequest(rewrapReq)
|
||||
@@ -253,13 +253,10 @@ func TestTransit_BatchRewrapCase3(t *testing.T) {
|
||||
t.Fatalf("err:%v resp:%#v", err, resp)
|
||||
}
|
||||
|
||||
var batchRewrapResponseArray []interface{}
|
||||
if err := jsonutil.DecodeJSON([]byte(resp.Data["batch_results"].(string)), &batchRewrapResponseArray); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
batchRewrapResponseItems := resp.Data["batch_results"].([]BatchResponseItem)
|
||||
|
||||
if len(batchRewrapResponseArray) != len(batchEncryptionResponseArray) {
|
||||
t.Fatalf("bad: length of input and output or rewrap are not matching; expected: %d, actual: %d", len(batchEncryptionResponseArray), len(batchRewrapResponseArray))
|
||||
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))
|
||||
}
|
||||
|
||||
decReq := &logical.Request{
|
||||
@@ -268,27 +265,19 @@ func TestTransit_BatchRewrapCase3(t *testing.T) {
|
||||
Storage: s,
|
||||
}
|
||||
|
||||
for i, responseItem := range batchEncryptionResponseArray {
|
||||
var input BatchRequestItem
|
||||
if err := mapstructure.Decode(responseItem, &input); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for i, eItem := range batchEncryptionResponseItems {
|
||||
rItem := batchRewrapResponseItems[i]
|
||||
|
||||
var output BatchResponseItem
|
||||
if err := mapstructure.Decode(batchRewrapResponseArray[i], &output); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if input.Ciphertext == output.Ciphertext {
|
||||
if eItem.Ciphertext == rItem.Ciphertext {
|
||||
t.Fatalf("bad: rewrap input and output are the same")
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(output.Ciphertext, "vault:v2") {
|
||||
t.Fatalf("bad: invalid version of ciphertext in rewrap response; expected: 'vault:v2', actual: %s", output.Ciphertext)
|
||||
if !strings.HasPrefix(rItem.Ciphertext, "vault:v2") {
|
||||
t.Fatalf("bad: invalid version of ciphertext in rewrap response; expected: 'vault:v2', actual: %s", rItem.Ciphertext)
|
||||
}
|
||||
|
||||
decReq.Data = map[string]interface{}{
|
||||
"ciphertext": output.Ciphertext,
|
||||
"ciphertext": rItem.Ciphertext,
|
||||
}
|
||||
|
||||
resp, err = b.HandleRequest(decReq)
|
||||
|
||||
@@ -479,10 +479,10 @@ only encrypt or decrypt using the named keys they need access to.
|
||||
<li>
|
||||
<span class="param">batch_input</span>
|
||||
<span class="param-flags">optional</span>
|
||||
Base64 encoded list of items to be encrypted in a single batch. When
|
||||
List of items to be encrypted in a single batch. When
|
||||
this parameter is set, if the parameters 'plaintext', 'context' and
|
||||
'nonce' are also set, they will be ignored. JSON format for the input
|
||||
(which should be base64 encoded) goes like this:
|
||||
'nonce' are also set, they will be ignored. Format for the input
|
||||
goes like this:
|
||||
|
||||
```javascript
|
||||
[
|
||||
@@ -582,10 +582,9 @@ only encrypt or decrypt using the named keys they need access to.
|
||||
<li>
|
||||
<span class="param">batch_input</span>
|
||||
<span class="param-flags">optional</span>
|
||||
Base64 encoded list of items to be decrypted in a single batch. When
|
||||
this parameter is set, if the parameters 'ciphertext', 'context' and
|
||||
'nonce' are also set, they will be ignored. JSON format for the input
|
||||
(which should be base64 encoded) goes like this:
|
||||
List of items to be decrypted in a single batch. When this parameter is
|
||||
set, if the parameters 'ciphertext', 'context' and 'nonce' are also
|
||||
set, they will be ignored. Format for the input goes like this:
|
||||
|
||||
```javascript
|
||||
[
|
||||
@@ -660,10 +659,9 @@ only encrypt or decrypt using the named keys they need access to.
|
||||
<li>
|
||||
<span class="param">batch_input</span>
|
||||
<span class="param-flags">optional</span>
|
||||
Base64 encoded list of items to be rewrapped in a single batch. When
|
||||
this parameter is set, if the parameters 'ciphertext', 'context' and
|
||||
'nonce' are also set, they will be ignored. JSON format for the input
|
||||
(which should be bae64 encoded) goes like this:
|
||||
List of items to be rewrapped in a single batch. When this parameter is
|
||||
set, if the parameters 'ciphertext', 'context' and 'nonce' are also
|
||||
set, they will be ignored. Format for the input goes like this:
|
||||
|
||||
```javascript
|
||||
[
|
||||
|
||||
Reference in New Issue
Block a user