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

feat: create a C++ sample plugin for HMAC cookie authorization. #117

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

Conversation

walves-cit
Copy link
Contributor

This plugin is a HMAC cookie authorization showcase.

Technically, this is performed by ensuring that the request has a valid HMAC cookie.

This examples contains only a C++ version.

@walves-cit walves-cit marked this pull request as ready for review September 9, 2024 19:37
@walves-cit walves-cit requested a review from a team as a code owner September 9, 2024 19:37
Copy link

snippet-bot bot commented Sep 9, 2024

Here is the summary of changes.

You are about to add 1 region tag.

This comment is generated by snippet-bot.
If you find problems with this result, please file an issue at:
https://github.com/googleapis/repo-automation-bots/issues.
To update this comment, add snippet-bot:force-run label or use the checkbox below:

  • Refresh this comment

# To avoid the error:
# library_pthread.js:26: #error "STANDALONE_WASM does not support shared memories yet".
# Disabling the pthreads avoids the inclusion of the library_pthread.js.
"-sUSE_PTHREADS=0",
Copy link
Collaborator

Choose a reason for hiding this comment

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

FWIW this will be fixed soon-ish in proxy-wasm/proxy-wasm-cpp-sdk#173 by setting threads = "off" in the Bazel transition.

Copy link
Contributor

Choose a reason for hiding this comment

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

@walves-cit can you remove the linkopts setting (per @martijneken 's comment above)? Also I think it can be removed from plugins/samples/jwt_auth/BUILD as well (in a separate PR)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Did not work. 😢
I've got the following error:

wasm-ld: error: --shared-memory is disallowed by lto.tmp because it was not compiled with 'atomics' or 'bulk-memory' features.

# To avoid the error:
# library_pthread.js:26: #error "STANDALONE_WASM does not support shared memories yet".
# Disabling the pthreads avoids the inclusion of the library_pthread.js.
"-sUSE_PTHREADS=0",
Copy link
Contributor

Choose a reason for hiding this comment

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

@walves-cit can you remove the linkopts setting (per @martijneken 's comment above)? Also I think it can be removed from plugins/samples/jwt_auth/BUILD as well (in a separate PR)


FilterHeadersStatus onRequestHeaders(uint32_t headers,
bool end_of_stream) override {
const auto token = getTokenFromCookie();
Copy link
Contributor

Choose a reason for hiding this comment

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

Expand type

return FilterHeadersStatus::ContinueAndEndStream;
}

const auto path = getRequestHeader(":path")->toString();
Copy link
Contributor

Choose a reason for hiding this comment

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

Using a cookie to hold a HMAC for a specific path seems unrealistic to me: for that case, you'd typically include the HMAC in the path, like in #114 . The main benefit / use case of cookie-based HMAC would be to give a client a (usually time-bounded) token that can be used across multiple URLs.

For this example, I'd propose using a simple example cookie that contains the values (client IP, expiration timestamp, hash(client IP, expiration timestamp, secret)). More concretely, let payload = the string client_ip + "," + expiration_timestamp, and then the cookie would be `base64(payload) + "." + base64(computeHmacSignature(payload)).

You can determine the client IP by parsing the X-Forwarded-For header, whose format is documented at https://cloud.google.com/load-balancing/docs/https#x-forwarded-for_header. If that header isn't present or fails parsing, reject the request.

Then you can verify a request by:

  1. obtaining client IP (reject if not present)
  2. obtaining cookie (reject if not present)
  3. Verify that cookie hash matches cookie payload (reject if no match)
  4. get current time by calling getCurrentTimeNanoseconds()
  5. Ensure that client IP matches cookie payload IP, and current time is earlier than cookie payload expiration time.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.... pls, take a look.
A lot of changes done 😅

}

// Helper function to convert binary data to a hexadecimal string.
std::string toHexString(const unsigned char* data, size_t length) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggest using absl::BytesToHexString

If that can't be used, suggest passing data and length as a string_view.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants