-
-
Notifications
You must be signed in to change notification settings - Fork 6.9k
Add support for several extended AWS SIGv4 options #19221
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
base: master
Are you sure you want to change the base?
Conversation
fea5a23 to
7777eab
Compare
include/curl/curl.h
Outdated
| /* The CA certificates as "blob" used to validate the peer certificate | ||
| this option is used only if SSL_VERIFYPEER is true */ | ||
| CURLOPT(CURLOPT_CAINFO_BLOB, CURLOPTTYPE_BLOB, 309), | ||
| CURLOPT(CURLOPT_CAINFO_BLOB, CURLOPTTYPE_BLOB, 312), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Existing option values need to remain the same for ABI compatibility.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, fixed
lib/http_aws_sigv4.c
Outdated
|
|
||
| #include "slist.h" | ||
|
|
||
| #define HMAC_SHA256(k, kl, d, dl, o) \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe move this to http_aws_sigv4a.h to avoid the duplicate definition in http_aws_sigv4a.c?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good idea
lib/http_aws_sigv4a.c
Outdated
| #include <openssl/ecdsa.h> | ||
| #include <openssl/bn.h> | ||
| #include <openssl/obj_mac.h> | ||
| #endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Noting that this adds another out-of-band crypto dependency, and part of the add features are OpenSSL-specific.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, this is to get ECDSA algorithm needed for generating an SIGv4A signature. You'll only need openssl for the X-Amz-Algorithm=ECDSA-P256-SHA256 (SIGV4A) support.
If you choose not to link with openssl then that only that algorithm won't work - but all the other options will (algorithm HMAC-SHA256, querystring & header mode, date overrides, etc).
We could make other changes later to enable alternate ECDSA providers (it doesn't have to be openssl)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Crypto functionality is better added by providing them in to the vtls/ layer so that they can be provided/powered by the at build-time selected TLS backend.
678dbed to
a909df8
Compare
d52938e to
bb85444
Compare
9ec53bd to
f392859
Compare
|
|
||
| When set to "ECDSA-P256-SHA256", uses AWS Signature Version 4A (SIGV4A) based on ECDSA P-256 signing. This supports multi-region/cross-region signing. | ||
|
|
||
| For more details on AWS signature algorithms, see the [AWS documentation](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_sigv-create-signed-request.html). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why and when would a user use a different algorithm than the default?
I think the text should be written to work stand-alone without URL. This is going to end up in a manpage that should try to entirely document the option.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll put some of the context I gave in the comment below into these docs to make it stand alone
|
|
||
| ## --aws-sigv4-mode | ||
|
|
||
| Specify the AWS SIGV4 signing mode. Valid values are "header" (default) and "querystring". |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We call the query part of a URL the query so I think that feels like a better name to use for this. The added string feels superfluous.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good, I can rename to query
lib/http_aws_sigv4a.c
Outdated
| #include <openssl/ecdsa.h> | ||
| #include <openssl/bn.h> | ||
| #include <openssl/obj_mac.h> | ||
| #endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Crypto functionality is better added by providing them in to the vtls/ layer so that they can be provided/powered by the at build-time selected TLS backend.
|
|
||
| for(i = 0; i < SIGV4A_PRIVATE_KEY_LENGTH; i++) { | ||
| volatile int a_digit = (int)a[i]; | ||
| volatile int b_digit = (int)b[i]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you can drop volatile from all the above lines.
| ALTSVC | ||
| Amz | ||
| amiga | ||
| amz |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this a string that should be quoted instead of accepted as word?
| CURLOPT(CURLOPT_AWS_SIGV4_ALGORITHM, CURLOPTTYPE_STRINGPOINT, 330), | ||
|
|
||
| /* AWS SigV4 signed headers list */ | ||
| CURLOPT(CURLOPT_AWS_SIGV4_SIGNEDHEADERS, CURLOPTTYPE_STRINGPOINT, 331), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would like us to consider a way how these config items either can be provided using the existing option, or be done using a single new one. Having four separate options for a fringe feature like AWS-sigv4 auth seems excessive to me!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wouldn't say they're fringe, these are actually for some popular options in the SDK signers and other signing software like Envoy & boto - but they are more complex options that you would see in a hello world example, for sure.
I'll give some more context on these & then try to describe what other options to configure this might look like.
- The SignedHeaders override lets you control what exactly gets signed, there's only a core set of headers (host & x-amz-*) you have to sign, all other headers are optional. This is actually a commonly used option in the SDKs.
It helps to be able to skip some headers because sometime they're added by layers of software clients don't control, so they can be tough for clients to sign. For example, lots of the http control headers like Content-Type, Accept, etc come from middleware/library layers where customers dont see the values directly to sign.
(With curl you have more control over the headers, but usually you need to reproduce what the actual clients are doing so that's the reason for the option.)
- The Algorithm option lets you generate signatures for either a single region (default) or multi-region (new feature).
The multi-region signature can be used in any region, so it makes failing requests over across regions possible - a request that fails in region A could be delivered to replica service in region B. Customers running proxy infrastructure are able to leverage this feature to implement resiliency strategies for multi-region deployments.
- The Mode option lets you generate signatures that go in the querystring instead of signatures that go in the Authorization header.
This used to generate things like presigned URLs for S3, using the querystring signing mode makes browser friendly URLs so can be found used with software download links. Its also useful when customers move something to AWS that already was using the Authorization header - for example, if you have an app with its own OIDC token you are moving behind ALB or VPC-Lattice you still enable AWS auth without having to change the app or its cients to make room in the Authorization header for the AWS signature.
- The SIGv4 option configures credential scope, region & provider
The sigv4 option configures credential scope, region as well as a "provider" name which is just a namespace for options (the amz in x-amz-date for instance). It looks like: "aws:amz:us-west-2:vpc-lattice-svcs"
Here's some alternative ways to expose the config. I think Alternative B might be the be best compromise, where its fewer parameters without cramming too many things into a single parameter. Lmk what you think.
Alternative A:
One way to expose this configuration is 0 new command line options. Instead we keep gluing things on to the existing sigv4 option.
So it could look like this to enable querystring mode:
"aws:amz:us-west-2:vpc-lattice-svcs:querystring"
Or like this to enable querystring mode with sigv4a algorithm.
"aws:amz:us-west-2:vpc-lattice-svcs:querystring:ECDSA-P256-SHA256"
Or like this to enable querystring mode, sigv4a algorithm & signed headers option.
"aws:amz:us-west-2:vpc-lattice-svcs:querystring:ECDSA-P256-SHA256:header1;header2;header3"
This would work - but one drawback are we have to pick an order for the options. In the example, signed headers is last, so if you want to set signed headers you also have to set mode and algorithm. The other is its hard to read, the string can get long and could have multiple : and ;'s since there'd be 6 options in it so doesn't feel very human friendly.
Alternative B:
Another option is fewer new options, 2 instead of 3. The CURLOPT_AWS_SIGV4_ALGORITHM & CURLOPT_AWS_SIGV4_MODE are both just flags, so we could merge algorithm flag into the mode flag
--aws-sigv4-mode=ECDSA-P256-SHA256-HEADER | ECDSA-P256-SHA256-QUERY | HMAC-SHA256-HEADER | HMAC-SHA256-QUERY
The signed headers option is a variable list like header1;header2;header3 so I wouldn't merge that one into mode, that could stay its own option.
Alternative C:
Another option is fewer new options, 1 instead of 3. We could tweak the format, but basically we'd just keep glueing things on mode option. That would look something like this:
--aws-sigv4-mode=ECDSA-P256-SHA256-HEADER;header0;header1;header2
Alternative D:
Trying to use query params or headers, like x-amz-security-token or x-amz-date overrides work is another strategy. This doesn't work very consistently though. The x-amz-algorithm and x-amz-signedheaders are query params when querystring mode - but they don't ever occur as header in header mode.
docs/libcurl/symbols-in-versions
Outdated
| CURLOPT_AWS_SIGV4 7.75.0 | ||
| CURLOPT_AWS_SIGV4_ALGORITHM 8.12.0 | ||
| CURLOPT_AWS_SIGV4_MODE 8.12.0 | ||
| CURLOPT_AWS_SIGV4_SIGNEDHEADERS 8.12.0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They can be added at earliest in 8.18.0
| } | ||
|
|
||
| /* Derive ECC private key from HMAC output */ | ||
| static int derive_ecc_private_key(unsigned char *private_key, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| static int derive_ecc_private_key(unsigned char *private_key, | |
| static bool derive_ecc_private_key(unsigned char *private_key, |
| { | ||
| /* Check if k0 > N-2 */ | ||
| if(compare_be_bytes(k0, n_minus_2) > 0) | ||
| return 0; /* Try next counter */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| return 0; /* Try next counter */ | |
| return FALSE; /* Try next counter */ |
etc
A new --aws-sigv4-mode option is added to select either the (default) header authentication mechanism, or the query string authenitcation mechanism. * https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_sigv-authentication-methods.html A new --aws-sigv4-algorithm option is added to select either the (default) HMAC-SHA256 signature algorithm used for standard single region SIGv4 signature, or the the ECDSA-P256-SHA256 signature algorithm used for multi-region SIGv4A signatures. * https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_sigv-create-signed-request.html A new --aws-sigv4-signedheaders option is added to select a specific set of headers to include in the signature. * https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_sigv-signing-elements.html The change also includes a few smaller updates: The --user parameter is updated to support optionaly specifing a security token. This is useful for querystring signing mode, where the parameter needs additional encoding that would be hard for users to do. (This security token can also still be specified explicitly in an X-Amz-Security-Token header instead when header signing mode) This includes an update to allow the X-Amz-Date or X-Amz-Date headers to control the date used for signing requests. This is useful when testing different scenarios with SIGv4 or SIGv4A.
f392859 to
a7f7a30
Compare
This change is backwards compatible with the existing aws-sigv4 support.
A new --aws-sigv4-mode option is added to select either the (default) header authentication mechanism, or the query string authenitcation mechanism.
A new --aws-sigv4-algorithm option is added to select either the (default) HMAC-SHA256 signature algorithm used for standard single region SIGv4 signature, or the the ECDSA-P256-SHA256 signature algorithm used for multi-region SIGv4A signatures.
A new --aws-sigv4-signedheaders option is added to select a specific set of headers to include in the signature.
The change also includes a few smaller updates:
The --user parameter is updated to support optionaly specifing a security token. This is useful for querystring signing mode, where the parameter needs additional encoding that would be hard for users to do. (This security token can also still be specified explicitly in an X-Amz-Security-Token header instead when header signing mode)
This includes an update to allow the X-Amz-Date or X-Amz-Date headers to control the date used for signing requests. This is useful when testing different scenarios with SIGv4 or SIGv4A.