Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

transitapi: add http handler enc/dec #1199

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

jmxnzo
Copy link
Contributor

@jmxnzo jmxnzo commented Jan 31, 2025

This PR adds basic http handling functionality for the encrypt and decrypt endpoints of the transit engine API, allowing the auto-unsealing process for user-managed Vaults. Additionally a cyclic cryptographic unit test, testing the implemented handler functions for encrypt and decrypt was added.

ToDo's

  • add logic to extract name parameter of URL, specifying the workloadSecretID
  • authorize transit engine requests to name parameter with client cert policy hash

@jmxnzo jmxnzo added no changelog PRs not listed in the release notes do not merge This shouldn't be merged at this point labels Jan 31, 2025
@jmxnzo jmxnzo marked this pull request as ready for review January 31, 2025 16:28
@jmxnzo jmxnzo requested a review from burgerdev as a code owner January 31, 2025 16:28
@jmxnzo jmxnzo changed the title transitapi: add hhtp handler enc/dec transitapi: add http handler enc/dec Jan 31, 2025
@@ -19,6 +19,11 @@ import (
"golang.org/x/crypto/hkdf"
)

// GetterSeedEngine describes a getter function to return a SeedEngine.
type GetterSeedEngine interface {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interfaces should be defined in the package they are used.

symmetricOpts symmetricOpts
}

// Note: In case only err is returned the resulting httpError will fallbback to InternalServerError status code 500.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you elaborate a bit more? Since this is not a function documentation, this floats a bit between the functions/code? Is is related to the function below?

Comment on lines +39 to +52
var status int
var httpError interface {
error
HTTPStatus() int
}
if errors.As(err, &httpError) {
status = httpError.HTTPStatus()
if status == 0 {
status = http.StatusInternalServerError
}
} else {
status = http.StatusInternalServerError
}
http.Error(w, err.Error(), status)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we also have w in the cryptFunc we can write the status code there. Though I'd like to go in the direction that the cryptFunc is a pure function that doesn't know about being in a http request, i.e., remove w and r from the arguments. Though I haven't found a good solution for that.


encryptionMapping.symmetricOpts = symmetricOpts{
convergent: false,
additionalData: []byte("test"),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left over from testing?

if err != nil {
return nil, err
}
gcm, err := cipher.NewGCM(aesCipher)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using the raw Go crypto libs feels a bit sharp. I think that tink doesn't have good support for this use-case. Have we checked that there isn't a good library for this?

if err != nil {
return httpError{error: err, status: http.StatusBadRequest}
}
encryptionMapping.symmetricOpts.nonce = ciphertextBytes[:12]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those inline numbers should definitely be constants, since

  1. The name documents the usage
  2. this makes sure that we keep using the same number in multiple places.

"bytes"
"encoding/json"
"io"
r "math/rand"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why naming the import here? Also single letter variables are usually reserved for either function receivers are variables with very limited scope

})
t.Run("decryption request handling", func(t *testing.T) {
decryptReqBody, err := createReqBodyJSON("ciphertext", ciphertext)
require.NoError(t, err)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of using require.NoError(t, err) we call require := require.New(t) in the first lines of a new test and then call require.NoError(err).


func TestCryptoAPICyclic(t *testing.T) {
t.Run("encrypt-decrypt handler", func(t *testing.T) {
for range 10 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the idea of calling the test 10 times? You can also run go tests multiple times by specifying -count 1000. Generally, using randomness in tests is also an anti-pattern, instead create crypto related things (keys etc) beforehand and use them as constants.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
do not merge This shouldn't be merged at this point no changelog PRs not listed in the release notes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants