Skip to content

Commit

Permalink
Return the partial success code override for all batch error types (#…
Browse files Browse the repository at this point in the history
…18310)

* Return the partial success code override for all batch error types

* changelog

* docs

* Lost the actual override logic. :)

* And don't hardcode 400

* gate on success
  • Loading branch information
sgmiller committed Dec 13, 2022
1 parent 1f0672c commit 2c76637
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 9 deletions.
36 changes: 27 additions & 9 deletions builtin/logical/transit/path_encrypt.go
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,7 @@ func (b *backend) pathEncryptWrite(ctx context.Context, req *logical.Request, d
// item fails, respectively mark the error in the response
// collection and continue to process other items.
warnAboutNonceUsage := false
successesInBatch := false
for i, item := range batchInputItems {
if batchResponseItems[i].Error != "" {
continue
Expand Down Expand Up @@ -409,6 +410,7 @@ func (b *backend) pathEncryptWrite(ctx context.Context, req *logical.Request, d

batchResponseItems[i].Ciphertext = ciphertext
batchResponseItems[i].KeyVersion = keyVersion
successesInBatch = true
}

resp := &logical.Response{}
Expand Down Expand Up @@ -443,15 +445,31 @@ func (b *backend) pathEncryptWrite(ctx context.Context, req *logical.Request, d

p.Unlock()

// Depending on the errors in the batch, different status codes should be returned. User errors
// will return a 400 and precede internal errors which return a 500. The reasoning behind this is
// that user errors are non-retryable without making changes to the request, and should be surfaced
// to the user first.
switch {
case userErrorInBatch:
return logical.RespondWithStatusCode(resp, req, http.StatusBadRequest)
case internalErrorInBatch:
return logical.RespondWithStatusCode(resp, req, http.StatusInternalServerError)
return batchRequestResponse(d, resp, req, successesInBatch, userErrorInBatch, internalErrorInBatch)
}

// Depending on the errors in the batch, different status codes should be returned. User errors
// will return a 400 and precede internal errors which return a 500. The reasoning behind this is
// that user errors are non-retryable without making changes to the request, and should be surfaced
// to the user first.
func batchRequestResponse(d *framework.FieldData, resp *logical.Response, req *logical.Request, successesInBatch, userErrorInBatch, internalErrorInBatch bool) (*logical.Response, error) {
if userErrorInBatch || internalErrorInBatch {
var code int
switch {
case userErrorInBatch:
code = http.StatusBadRequest
case internalErrorInBatch:
code = http.StatusInternalServerError
}
if codeRaw, ok := d.GetOk("partial_failure_response_code"); ok && successesInBatch {
newCode := codeRaw.(int)
if newCode < 1 || newCode > 599 {
resp.AddWarning(fmt.Sprintf("invalid HTTP response code override from partial_failure_response_code, reverting to %d", code))
} else {
code = newCode
}
}
return logical.RespondWithStatusCode(resp, req, code)
}

return resp, nil
Expand Down
3 changes: 3 additions & 0 deletions changelog/18310.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:bug
secrets/transit: Honor `partial_success_response_code` on decryption failures.
```
17 changes: 17 additions & 0 deletions website/content/api-docs/secret/transit.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,15 @@ will be returned.
all nonces are unique for a given context. Failing to do so will severely
impact the ciphertext's security.

- `partial_failure_response_code` `(int: 400)` Ordinarily, if a batch item fails
to encrypt due to a bad input, but other batch items succeed, the HTTP response
code is 400 (Bad Request). Some applications may want to treat partial failures
differently. Providing the parameter returns the given response code integer
instead of a failed status code in this case. If all values fail an error
code is still returned. Be warned that some failures (such as failure to
decrypt) could be indicative of a security breach and should not be
ignored.

~>**NOTE:** All plaintext data **must be base64-encoded**. The reason for this
requirement is that Vault does not require that the plaintext is "text". It
could be a binary file such as a PDF or image. The easiest safe transport
Expand Down Expand Up @@ -653,6 +662,14 @@ This endpoint decrypts the provided ciphertext using the named key.
}
]
```
- `partial_failure_response_code` `(int: 400)` Ordinarily, if a batch item fails
to encrypt due to a bad input, but other batch items succeed, the HTTP response
code is 400 (Bad Request). Some applications may want to treat partial failures
differently. Providing the parameter returns the given response code integer
instead of a failed status code in this case. If all values fail an error
code is still returned. Be warned that some failures (such as failure to
decrypt) could be indicative of a security breach and should not be
>>>>>>> 81e0030538... Return the partial success code override for all batch error types (#18310)
### Sample Payload

Expand Down

0 comments on commit 2c76637

Please sign in to comment.