Add the batch reference field, as in Transform, to Transit operations (#18243)

* Add the batch reference field, as in Transform, to Transit operations

* changelog

* docs

* More mapstructure tags
This commit is contained in:
Scott Miller
2022-12-13 12:03:40 -06:00
committed by GitHub
parent 5900230b9e
commit 018e50b16b
12 changed files with 145 additions and 23 deletions

View File

@@ -19,6 +19,10 @@ type DecryptBatchResponseItem struct {
// Error, if set represents a failure encountered while encrypting a // Error, if set represents a failure encountered while encrypting a
// corresponding batch request item // corresponding batch request item
Error string `json:"error,omitempty" structs:"error" mapstructure:"error"` Error string `json:"error,omitempty" structs:"error" mapstructure:"error"`
// Reference is an arbitrary caller supplied string value that will be placed on the
// batch response to ease correlation between inputs and outputs
Reference string `json:"reference" structs:"reference" mapstructure:"reference"`
} }
func (b *backend) pathDecrypt() *framework.Path { func (b *backend) pathDecrypt() *framework.Path {
@@ -195,6 +199,10 @@ func (b *backend) pathDecryptWrite(ctx context.Context, req *logical.Request, d
resp := &logical.Response{} resp := &logical.Response{}
if batchInputRaw != nil { if batchInputRaw != nil {
// Copy the references
for i := range batchInputItems {
batchResponseItems[i].Reference = batchInputItems[i].Reference
}
resp.Data = map[string]interface{}{ resp.Data = map[string]interface{}{
"batch_results": batchResponseItems, "batch_results": batchResponseItems,
} }

View File

@@ -19,9 +19,9 @@ func TestTransit_BatchDecryption(t *testing.T) {
b, s := createBackendWithStorage(t) b, s := createBackendWithStorage(t)
batchEncryptionInput := []interface{}{ batchEncryptionInput := []interface{}{
map[string]interface{}{"plaintext": ""}, // empty string map[string]interface{}{"plaintext": "", "reference": "foo"}, // empty string
map[string]interface{}{"plaintext": "Cg=="}, // newline map[string]interface{}{"plaintext": "Cg==", "reference": "bar"}, // newline
map[string]interface{}{"plaintext": "dGhlIHF1aWNrIGJyb3duIGZveA=="}, map[string]interface{}{"plaintext": "dGhlIHF1aWNrIGJyb3duIGZveA==", "reference": "baz"},
} }
batchEncryptionData := map[string]interface{}{ batchEncryptionData := map[string]interface{}{
"batch_input": batchEncryptionInput, "batch_input": batchEncryptionInput,
@@ -41,7 +41,7 @@ func TestTransit_BatchDecryption(t *testing.T) {
batchResponseItems := resp.Data["batch_results"].([]EncryptBatchResponseItem) batchResponseItems := resp.Data["batch_results"].([]EncryptBatchResponseItem)
batchDecryptionInput := make([]interface{}, len(batchResponseItems)) batchDecryptionInput := make([]interface{}, len(batchResponseItems))
for i, item := range batchResponseItems { for i, item := range batchResponseItems {
batchDecryptionInput[i] = map[string]interface{}{"ciphertext": item.Ciphertext} batchDecryptionInput[i] = map[string]interface{}{"ciphertext": item.Ciphertext, "reference": item.Reference}
} }
batchDecryptionData := map[string]interface{}{ batchDecryptionData := map[string]interface{}{
"batch_input": batchDecryptionInput, "batch_input": batchDecryptionInput,
@@ -59,7 +59,8 @@ func TestTransit_BatchDecryption(t *testing.T) {
} }
batchDecryptionResponseItems := resp.Data["batch_results"].([]DecryptBatchResponseItem) batchDecryptionResponseItems := resp.Data["batch_results"].([]DecryptBatchResponseItem)
expectedResult := "[{\"plaintext\":\"\"},{\"plaintext\":\"Cg==\"},{\"plaintext\":\"dGhlIHF1aWNrIGJyb3duIGZveA==\"}]" // This seems fragile
expectedResult := "[{\"plaintext\":\"\",\"reference\":\"foo\"},{\"plaintext\":\"Cg==\",\"reference\":\"bar\"},{\"plaintext\":\"dGhlIHF1aWNrIGJyb3duIGZveA==\",\"reference\":\"baz\"}]"
jsonResponse, err := json.Marshal(batchDecryptionResponseItems) jsonResponse, err := json.Marshal(batchDecryptionResponseItems)
if err != nil || err == nil && string(jsonResponse) != expectedResult { if err != nil || err == nil && string(jsonResponse) != expectedResult {

View File

@@ -42,6 +42,10 @@ type BatchRequestItem struct {
// Associated Data for AEAD ciphers // Associated Data for AEAD ciphers
AssociatedData string `json:"associated_data" struct:"associated_data" mapstructure:"associated_data"` AssociatedData string `json:"associated_data" struct:"associated_data" mapstructure:"associated_data"`
// Reference is an arbitrary caller supplied string value that will be placed on the
// batch response to ease correlation between inputs and outputs
Reference string `json:"reference" structs:"reference" mapstructure:"reference"`
} }
// EncryptBatchResponseItem represents a response item for batch processing // EncryptBatchResponseItem represents a response item for batch processing
@@ -56,6 +60,10 @@ type EncryptBatchResponseItem struct {
// Error, if set represents a failure encountered while encrypting a // Error, if set represents a failure encountered while encrypting a
// corresponding batch request item // corresponding batch request item
Error string `json:"error,omitempty" structs:"error" mapstructure:"error"` Error string `json:"error,omitempty" structs:"error" mapstructure:"error"`
// Reference is an arbitrary caller supplied string value that will be placed on the
// batch response to ease correlation between inputs and outputs
Reference string `json:"reference"`
} }
type AssocDataFactory struct { type AssocDataFactory struct {
@@ -261,6 +269,14 @@ func decodeBatchRequestItems(src interface{}, requirePlaintext bool, requireCiph
errs.Errors = append(errs.Errors, fmt.Sprintf("'[%d].associated_data' expected type 'string', got unconvertible type '%T'", i, item["associated_data"])) errs.Errors = append(errs.Errors, fmt.Sprintf("'[%d].associated_data' expected type 'string', got unconvertible type '%T'", i, item["associated_data"]))
} }
} }
if v, has := item["reference"]; has {
if !reflect.ValueOf(v).IsValid() {
} else if casted, ok := v.(string); ok {
(*dst)[i].Reference = casted
} else {
errs.Errors = append(errs.Errors, fmt.Sprintf("'[%d].reference' expected type 'string', got unconvertible type '%T'", i, item["reference"]))
}
}
} }
if len(errs.Errors) > 0 { if len(errs.Errors) > 0 {
@@ -471,6 +487,10 @@ func (b *backend) pathEncryptWrite(ctx context.Context, req *logical.Request, d
resp := &logical.Response{} resp := &logical.Response{}
if batchInputRaw != nil { if batchInputRaw != nil {
// Copy the references
for i := range batchInputItems {
batchResponseItems[i].Reference = batchInputItems[i].Reference
}
resp.Data = map[string]interface{}{ resp.Data = map[string]interface{}{
"batch_results": batchResponseItems, "batch_results": batchResponseItems,
} }

View File

@@ -225,7 +225,7 @@ func TestTransit_BatchEncryptionCase3(t *testing.T) {
} }
} }
// Case4: Test batch encryption with an existing key // Case4: Test batch encryption with an existing key (and test references)
func TestTransit_BatchEncryptionCase4(t *testing.T) { func TestTransit_BatchEncryptionCase4(t *testing.T) {
var resp *logical.Response var resp *logical.Response
var err error var err error
@@ -243,8 +243,8 @@ func TestTransit_BatchEncryptionCase4(t *testing.T) {
} }
batchInput := []interface{}{ batchInput := []interface{}{
map[string]interface{}{"plaintext": "dGhlIHF1aWNrIGJyb3duIGZveA=="}, map[string]interface{}{"plaintext": "dGhlIHF1aWNrIGJyb3duIGZveA==", "reference": "b"},
map[string]interface{}{"plaintext": "dGhlIHF1aWNrIGJyb3duIGZveA=="}, map[string]interface{}{"plaintext": "dGhlIHF1aWNrIGJyb3duIGZveA==", "reference": "a"},
} }
batchData := map[string]interface{}{ batchData := map[string]interface{}{
@@ -271,7 +271,7 @@ func TestTransit_BatchEncryptionCase4(t *testing.T) {
plaintext := "dGhlIHF1aWNrIGJyb3duIGZveA==" plaintext := "dGhlIHF1aWNrIGJyb3duIGZveA=="
for _, item := range batchResponseItems { for i, item := range batchResponseItems {
if item.KeyVersion != 1 { if item.KeyVersion != 1 {
t.Fatalf("unexpected key version; got: %d, expected: %d", item.KeyVersion, 1) t.Fatalf("unexpected key version; got: %d, expected: %d", item.KeyVersion, 1)
} }
@@ -287,6 +287,10 @@ func TestTransit_BatchEncryptionCase4(t *testing.T) {
if resp.Data["plaintext"] != plaintext { if resp.Data["plaintext"] != plaintext {
t.Fatalf("bad: plaintext. Expected: %q, Actual: %q", plaintext, resp.Data["plaintext"]) t.Fatalf("bad: plaintext. Expected: %q, Actual: %q", plaintext, resp.Data["plaintext"])
} }
inputItem := batchInput[i].(map[string]interface{})
if item.Reference != inputItem["reference"] {
t.Fatalf("reference mismatch. Expected %s, Actual: %s", inputItem["reference"], item.Reference)
}
} }
} }

View File

@@ -35,6 +35,10 @@ type batchResponseHMACItem struct {
// For batch processing to successfully mimic previous handling for simple 'input', // For batch processing to successfully mimic previous handling for simple 'input',
// both output values are needed - though 'err' should never be serialized. // both output values are needed - though 'err' should never be serialized.
err error err error
// Reference is an arbitrary caller supplied string value that will be placed on the
// batch response to ease correlation between inputs and outputs
Reference string `json:"reference" mapstructure:"reference"`
} }
func (b *backend) pathHMAC() *framework.Path { func (b *backend) pathHMAC() *framework.Path {
@@ -201,6 +205,10 @@ func (b *backend) pathHMACWrite(ctx context.Context, req *logical.Request, d *fr
// Generate the response // Generate the response
resp := &logical.Response{} resp := &logical.Response{}
if batchInputRaw != nil { if batchInputRaw != nil {
// Copy the references
for i := range batchInputItems {
response[i].Reference = batchInputItems[i]["reference"]
}
resp.Data = map[string]interface{}{ resp.Data = map[string]interface{}{
"batch_results": response, "batch_results": response,
} }
@@ -362,6 +370,10 @@ func (b *backend) pathHMACVerify(ctx context.Context, req *logical.Request, d *f
// Generate the response // Generate the response
resp := &logical.Response{} resp := &logical.Response{}
if batchInputRaw != nil { if batchInputRaw != nil {
// Copy the references
for i := range batchInputItems {
response[i].Reference = batchInputItems[i]["reference"]
}
resp.Data = map[string]interface{}{ resp.Data = map[string]interface{}{
"batch_results": response, "batch_results": response,
} }

View File

@@ -248,18 +248,18 @@ func TestTransit_batchHMAC(t *testing.T) {
req.Path = "hmac/foo" req.Path = "hmac/foo"
batchInput := []batchRequestHMACItem{ batchInput := []batchRequestHMACItem{
{"input": "dGhlIHF1aWNrIGJyb3duIGZveA=="}, {"input": "dGhlIHF1aWNrIGJyb3duIGZveA==", "reference": "one"},
{"input": "dGhlIHF1aWNrIGJyb3duIGZveA=="}, {"input": "dGhlIHF1aWNrIGJyb3duIGZveA==", "reference": "two"},
{"input": ""}, {"input": "", "reference": "three"},
{"input": ":;.?"}, {"input": ":;.?", "reference": "four"},
{}, {},
} }
expected := []batchResponseHMACItem{ expected := []batchResponseHMACItem{
{HMAC: "vault:v1:UcBvm5VskkukzZHlPgm3p5P/Yr/PV6xpuOGZISya3A4="}, {HMAC: "vault:v1:UcBvm5VskkukzZHlPgm3p5P/Yr/PV6xpuOGZISya3A4=", Reference: "one"},
{HMAC: "vault:v1:UcBvm5VskkukzZHlPgm3p5P/Yr/PV6xpuOGZISya3A4="}, {HMAC: "vault:v1:UcBvm5VskkukzZHlPgm3p5P/Yr/PV6xpuOGZISya3A4=", Reference: "two"},
{HMAC: "vault:v1:BCfVv6rlnRsIKpjCZCxWvh5iYwSSabRXpX9XJniuNgc="}, {HMAC: "vault:v1:BCfVv6rlnRsIKpjCZCxWvh5iYwSSabRXpX9XJniuNgc=", Reference: "three"},
{Error: "unable to decode input as base64: illegal base64 data at input byte 0"}, {Error: "unable to decode input as base64: illegal base64 data at input byte 0", Reference: "four"},
{Error: "missing input for HMAC"}, {Error: "missing input for HMAC"},
} }
@@ -286,6 +286,9 @@ func TestTransit_batchHMAC(t *testing.T) {
if expected[i].Error != "" && expected[i].Error != m.Error { if expected[i].Error != "" && expected[i].Error != m.Error {
t.Fatalf("Expected Error %q got %q in result %d", expected[i].Error, m.Error, i) t.Fatalf("Expected Error %q got %q in result %d", expected[i].Error, m.Error, i)
} }
if expected[i].Reference != m.Reference {
t.Fatalf("Expected references to match, Got %s, Expected %s", m.Reference, expected[i].Reference)
}
} }
// Verify a previous version // Verify a previous version

View File

@@ -182,6 +182,10 @@ func (b *backend) pathRewrapWrite(ctx context.Context, req *logical.Request, d *
resp := &logical.Response{} resp := &logical.Response{}
if batchInputRaw != nil { if batchInputRaw != nil {
// Copy the references
for i := range batchInputItems {
batchResponseItems[i].Reference = batchInputItems[i].Reference
}
resp.Data = map[string]interface{}{ resp.Data = map[string]interface{}{
"batch_results": batchResponseItems, "batch_results": batchResponseItems,
} }

View File

@@ -224,8 +224,8 @@ func TestTransit_BatchRewrapCase3(t *testing.T) {
b, s := createBackendWithStorage(t) b, s := createBackendWithStorage(t)
batchEncryptionInput := []interface{}{ batchEncryptionInput := []interface{}{
map[string]interface{}{"plaintext": "dmlzaGFsCg=="}, map[string]interface{}{"plaintext": "dmlzaGFsCg==", "reference": "ek"},
map[string]interface{}{"plaintext": "dGhlIHF1aWNrIGJyb3duIGZveA=="}, map[string]interface{}{"plaintext": "dGhlIHF1aWNrIGJyb3duIGZveA==", "reference": "do"},
} }
batchEncryptionData := map[string]interface{}{ batchEncryptionData := map[string]interface{}{
"batch_input": batchEncryptionInput, "batch_input": batchEncryptionInput,
@@ -245,7 +245,7 @@ func TestTransit_BatchRewrapCase3(t *testing.T) {
batchRewrapInput := make([]interface{}, len(batchEncryptionResponseItems)) batchRewrapInput := make([]interface{}, len(batchEncryptionResponseItems))
for i, item := range batchEncryptionResponseItems { for i, item := range batchEncryptionResponseItems {
batchRewrapInput[i] = map[string]interface{}{"ciphertext": item.Ciphertext} batchRewrapInput[i] = map[string]interface{}{"ciphertext": item.Ciphertext, "reference": item.Reference}
} }
batchRewrapData := map[string]interface{}{ batchRewrapData := map[string]interface{}{
@@ -289,6 +289,11 @@ func TestTransit_BatchRewrapCase3(t *testing.T) {
for i, eItem := range batchEncryptionResponseItems { for i, eItem := range batchEncryptionResponseItems {
rItem := batchRewrapResponseItems[i] rItem := batchRewrapResponseItems[i]
inputRef := batchEncryptionInput[i].(map[string]interface{})["reference"]
if eItem.Reference != inputRef {
t.Fatalf("bad: reference mismatch. Expected %s, Actual: %s", inputRef, eItem.Reference)
}
if eItem.Ciphertext == rItem.Ciphertext { if eItem.Ciphertext == rItem.Ciphertext {
t.Fatalf("bad: rewrap input and output are the same") t.Fatalf("bad: rewrap input and output are the same")
} }
@@ -315,5 +320,6 @@ func TestTransit_BatchRewrapCase3(t *testing.T) {
if resp.Data["plaintext"] != plaintext1 && resp.Data["plaintext"] != plaintext2 { if resp.Data["plaintext"] != plaintext1 && resp.Data["plaintext"] != plaintext2 {
t.Fatalf("bad: plaintext. Expected: %q or %q, Actual: %q", plaintext1, plaintext2, resp.Data["plaintext"]) t.Fatalf("bad: plaintext. Expected: %q or %q, Actual: %q", plaintext1, plaintext2, resp.Data["plaintext"])
} }
} }
} }

View File

@@ -39,6 +39,10 @@ type batchResponseSignItem struct {
// For batch processing to successfully mimic previous handling for simple 'input', // For batch processing to successfully mimic previous handling for simple 'input',
// both output values are needed - though 'err' should never be serialized. // both output values are needed - though 'err' should never be serialized.
err error err error
// Reference is an arbitrary caller supplied string value that will be placed on the
// batch response to ease correlation between inputs and outputs
Reference string `json:"reference" mapstructure:"reference"`
} }
// BatchRequestVerifyItem represents a request item for batch processing. // BatchRequestVerifyItem represents a request item for batch processing.
@@ -59,6 +63,10 @@ type batchResponseVerifyItem struct {
// For batch processing to successfully mimic previous handling for simple 'input', // For batch processing to successfully mimic previous handling for simple 'input',
// both output values are needed - though 'err' should never be serialized. // both output values are needed - though 'err' should never be serialized.
err error err error
// Reference is an arbitrary caller supplied string value that will be placed on the
// batch response to ease correlation between inputs and outputs
Reference string `json:"reference" mapstructure:"reference"`
} }
const defaultHashAlgorithm = "sha2-256" const defaultHashAlgorithm = "sha2-256"
@@ -420,6 +428,10 @@ func (b *backend) pathSignWrite(ctx context.Context, req *logical.Request, d *fr
// Generate the response // Generate the response
resp := &logical.Response{} resp := &logical.Response{}
if batchInputRaw != nil { if batchInputRaw != nil {
// Copy the references
for i := range batchInputItems {
response[i].Reference = batchInputItems[i]["reference"]
}
resp.Data = map[string]interface{}{ resp.Data = map[string]interface{}{
"batch_results": response, "batch_results": response,
} }
@@ -636,6 +648,10 @@ func (b *backend) pathVerifyWrite(ctx context.Context, req *logical.Request, d *
// Generate the response // Generate the response
resp := &logical.Response{} resp := &logical.Response{}
if batchInputRaw != nil { if batchInputRaw != nil {
// Copy the references
for i := range batchInputItems {
response[i].Reference = batchInputItems[i]["reference"]
}
resp.Data = map[string]interface{}{ resp.Data = map[string]interface{}{
"batch_results": response, "batch_results": response,
} }

View File

@@ -25,6 +25,7 @@ type signOutcome struct {
requestOk bool requestOk bool
valid bool valid bool
keyValid bool keyValid bool
reference string
} }
func TestTransit_SignVerify_ECDSA(t *testing.T) { func TestTransit_SignVerify_ECDSA(t *testing.T) {
@@ -483,6 +484,7 @@ func TestTransit_SignVerify_ED25519(t *testing.T) {
} }
for i, v := range sig { for i, v := range sig {
batchRequestItems[i]["signature"] = v batchRequestItems[i]["signature"] = v
batchRequestItems[i]["reference"] = outcome[i].reference
} }
} else if attachSig { } else if attachSig {
req.Data["signature"] = sig[0] req.Data["signature"] = sig[0]
@@ -535,6 +537,9 @@ func TestTransit_SignVerify_ED25519(t *testing.T) {
if pubKeyRaw, ok := req.Data["public_key"]; ok { if pubKeyRaw, ok := req.Data["public_key"]; ok {
validatePublicKey(t, batchRequestItems[i]["input"], sig[i], pubKeyRaw.([]byte), outcome[i].keyValid, postpath, b) validatePublicKey(t, batchRequestItems[i]["input"], sig[i], pubKeyRaw.([]byte), outcome[i].keyValid, postpath, b)
} }
if v.Reference != outcome[i].reference {
t.Fatalf("verification failed, mismatched references %s vs %s", v.Reference, outcome[i].reference)
}
} }
return return
} }
@@ -634,15 +639,18 @@ func TestTransit_SignVerify_ED25519(t *testing.T) {
// Test Batch Signing // Test Batch Signing
batchInput := []batchRequestSignItem{ batchInput := []batchRequestSignItem{
{"context": "abcd", "input": "dGhlIHF1aWNrIGJyb3duIGZveA=="}, {"context": "abcd", "input": "dGhlIHF1aWNrIGJyb3duIGZveA==", "reference": "uno"},
{"context": "efgh", "input": "dGhlIHF1aWNrIGJyb3duIGZveA=="}, {"context": "efgh", "input": "dGhlIHF1aWNrIGJyb3duIGZveA==", "reference": "dos"},
} }
req.Data = map[string]interface{}{ req.Data = map[string]interface{}{
"batch_input": batchInput, "batch_input": batchInput,
} }
outcome = []signOutcome{{requestOk: true, valid: true, keyValid: true}, {requestOk: true, valid: true, keyValid: true}} outcome = []signOutcome{
{requestOk: true, valid: true, keyValid: true, reference: "uno"},
{requestOk: true, valid: true, keyValid: true, reference: "dos"},
}
sig = signRequest(req, false, "foo") sig = signRequest(req, false, "foo")
verifyRequest(req, false, outcome, "foo", sig, true) verifyRequest(req, false, outcome, "foo", sig, true)

4
changelog/18243.txt Normal file
View File

@@ -0,0 +1,4 @@
```release-note:improvement
secrets/transit: Add an optional reference field to batch operation items
which is repeated on batch responses to help more easily correlate inputs with outputs.
```

View File

@@ -627,6 +627,12 @@ will be returned.
for any given context (and thus, any given encryption key) this nonce value is for any given context (and thus, any given encryption key) this nonce value is
**never reused**. **never reused**.
- `reference` `(string: "")` -
A user-supplied string that will be present in the `reference` field on the
corresponding `batch_results` item in the response, to assist in understanding
which result corresponds to a particular input. Only valid on batch requests
when using batch_input below.
- `batch_input` `(array<object>: nil)`  Specifies a list of items to be - `batch_input` `(array<object>: nil)`  Specifies a list of items to be
encrypted in a single batch. When this parameter is set, if the parameters encrypted in a single batch. When this parameter is set, if the parameters
'plaintext', 'context' and 'nonce' are also set, they will be ignored. 'plaintext', 'context' and 'nonce' are also set, they will be ignored.
@@ -740,6 +746,12 @@ This endpoint decrypts the provided ciphertext using the named key.
and the key was generated with Vault 0.6.1. Not required for keys created in and the key was generated with Vault 0.6.1. Not required for keys created in
0.6.2+. 0.6.2+.
- `reference` `(string: "")` -
A user-supplied string that will be present in the `reference` field on the
corresponding `batch_results` item in the response, to assist in understanding
which result corresponds to a particular input. Only valid on batch requests
when using batch_input below.
- `batch_input` `(array<object>: nil)`  Specifies a list of items to be - `batch_input` `(array<object>: nil)`  Specifies a list of items to be
decrypted in a single batch. When this parameter is set, if the parameters decrypted in a single batch. When this parameter is set, if the parameters
'ciphertext', 'context' and 'nonce' are also set, they will be ignored. 'ciphertext', 'context' and 'nonce' are also set, they will be ignored.
@@ -824,6 +836,12 @@ functionality to untrusted users or scripts.
and the key was generated with Vault 0.6.1. Not required for keys created in and the key was generated with Vault 0.6.1. Not required for keys created in
0.6.2+. 0.6.2+.
- `reference` `(string: "")` -
A user-supplied string that will be present in the `reference` field on the
corresponding `batch_results` item in the response, to assist in understanding
which result corresponds to a particular input. Only valid on batch requests
when using batch_input below.
- `batch_input` `(array<object>: nil)`  Specifies a list of items to be - `batch_input` `(array<object>: nil)`  Specifies a list of items to be
decrypted in a single batch. When this parameter is set, if the parameters decrypted in a single batch. When this parameter is set, if the parameters
'ciphertext', 'context' and 'nonce' are also set, they will be ignored. 'ciphertext', 'context' and 'nonce' are also set, they will be ignored.
@@ -1085,6 +1103,12 @@ be used.
- `input` `(string: "")`  Specifies the **base64 encoded** input data. One of - `input` `(string: "")`  Specifies the **base64 encoded** input data. One of
`input` or `batch_input` must be supplied. `input` or `batch_input` must be supplied.
- `reference` `(string: "")` -
A user-supplied string that will be present in the `reference` field on the
corresponding `batch_results` item in the response, to assist in understanding
which result corresponds to a particular input. Only valid on batch requests
when using batch_input below.
- `batch_input` `(array<object>: nil)`  Specifies a list of items for processing. - `batch_input` `(array<object>: nil)`  Specifies a list of items for processing.
When this parameter is set, if the parameter 'input' is also set, it will be When this parameter is set, if the parameter 'input' is also set, it will be
ignored. Responses are returned in the 'batch_results' array component of the ignored. Responses are returned in the 'batch_results' array component of the
@@ -1233,6 +1257,12 @@ supports signing.
- `input` `(string: "")`  Specifies the **base64 encoded** input data. One of - `input` `(string: "")`  Specifies the **base64 encoded** input data. One of
`input` or `batch_input` must be supplied. `input` or `batch_input` must be supplied.
- `reference` `(string: "")` -
A user-supplied string that will be present in the `reference` field on the
corresponding `batch_results` item in the response, to assist in understanding
which result corresponds to a particular input. Only valid on batch requests
when using batch_input below.
- `batch_input` `(array<object>: nil)`  Specifies a list of items for processing. - `batch_input` `(array<object>: nil)`  Specifies a list of items for processing.
When this parameter is set, any supplied 'input' or 'context' parameters will be When this parameter is set, any supplied 'input' or 'context' parameters will be
ignored. Responses are returned in the 'batch_results' array component of the ignored. Responses are returned in the 'batch_results' array component of the
@@ -1417,6 +1447,12 @@ data.
`/transit/hmac` function. Either this must be supplied or `signature` must be `/transit/hmac` function. Either this must be supplied or `signature` must be
supplied. supplied.
- `reference` `(string: "")` -
A user-supplied string that will be present in the `reference` field on the
corresponding `batch_results` item in the response, to assist in understanding
which result corresponds to a particular input. Only valid on batch requests
when using batch_input below.
- `batch_input` `(array<object>: nil)`  Specifies a list of items for processing. - `batch_input` `(array<object>: nil)`  Specifies a list of items for processing.
When this parameter is set, any supplied 'input', 'hmac' or 'signature' parameters When this parameter is set, any supplied 'input', 'hmac' or 'signature' parameters
will be ignored. 'batch_input' items should contain an 'input' parameter and will be ignored. 'batch_input' items should contain an 'input' parameter and