Skip to content

feat(lambda-events): support X509 custom authorizer in IoT events#1114

Merged
jlizen merged 2 commits intoaws:mainfrom
flobz:feat/x509_iot_auth_req
Mar 4, 2026
Merged

feat(lambda-events): support X509 custom authorizer in IoT events#1114
jlizen merged 2 commits intoaws:mainfrom
flobz:feat/x509_iot_auth_req

Conversation

@flobz
Copy link
Contributor

@flobz flobz commented Mar 3, 2026

✍️ Description of changes:

  • Add default value to IoTCoreMqttContext.password to support X509/mutual TLS custom authorizers where AWS IoT does not send username or password fields.
  • Add x509_certificate_pem and principal_id fields to IoTCoreTlsContext for X509 certificate-based authentication. Add test fixture and test for the X509 authorizer payload.

🔏 By submitting this pull request

  • I confirm that I've ran cargo +nightly fmt.
  • I confirm that I've ran cargo clippy --fix.
  • I confirm that I've made a best effort attempt to update all relevant documentation.
  • I confirm that my contribution is made under the terms of the Apache 2.0 license.

Copy link
Collaborator

@jlizen jlizen left a comment

Choose a reason for hiding this comment

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

#[serde(default)]
pub server_name: Option<String>,
#[serde(default)]
pub x509_certificate_pem: Option<String>,
Copy link
Collaborator

Choose a reason for hiding this comment

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

pub client_id: Option<String>,
pub password: Base64Data,
#[serde(default)]
pub password: Option<Base64Data>,
Copy link
Collaborator

@jlizen jlizen Mar 3, 2026

Choose a reason for hiding this comment

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

This is indeed base64 data as described in the docs.

However, this is a breaking change to convert it from a String to Base64Data (which dereferences to Vec<u8>.

I sympathize with wanting to deserialize it directly as base64 with no extra hop, but I don't think we can justify this sort of breaking change when String would continue working fine, and is not really a "bug" insofar as String is a common base64 representation.

Is there a possibility of making it generic, with a default parameter instead?

Ie something like:

pub struct IoTCoreMqttContext<T = String> {
    ...
    #[serde(default)]
    pub password: Option<T>
}

and then passing that T with a default value up through other events that include this one? That would let you "opt it" to it by specifying it in your lambda event:

async fn function_handler(
    client: &aws_sdk_ses::Client,
    event: LambdaEvent<IoTCoreMqttContext<Base64Data>>,
) -> ..

It's a bit awkward, and we could certainly cut to just using the b64 data directly next major version, just that might be a moment.

Another option if you don't mind the extra hop is to expose a .as_base_64() helper that casts it after initial parsing.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm not sure to understand, I just make it optional it was already a Base64Data type.

Copy link
Collaborator

@jlizen jlizen Mar 4, 2026

Choose a reason for hiding this comment

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

Ah, my mistake, I read too quickly.

So the concern is, custom x509 authorizers don't send a password, which fails to parse against the existing schema?

Unfortunately this still is a breaking change for something that works for existing consumers, schema support for passwordless x509 support is more of an enhancement. So, the conclusion would be similar, except the generic would stay defaulting to Base64Data, while allowing the caller to declare in their handler IoTCoreCustomAuthorizerRequester<Option<Base64Data>>.

There are some alternatives like:

  • add a type alias for the generic with Option for ergonomics (similar to above but might be nicer to name?)
  • add a concrete IotCoreCustomAuthorizerRequestV2 that always uses option, no generic (and mark the old as deprecated and docs(hidden), but don't break it)
  • (bad idea, probably?) have some default for this base64 deserialization that resolves to an empty vec

Copy link
Collaborator

@jlizen jlizen Mar 4, 2026

Choose a reason for hiding this comment

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

You DO have impl Default available for Base64Data already, it looks like, so I wouldn't object to just annotating it with serde(default) without the option, if that is sufficient for your use case, to avoid failing deserializing and instead get the empty vec. It's not the best, fairly confusing. But that certainly is simpler than messing with generics.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ok it's done

Copy link
Collaborator

Choose a reason for hiding this comment

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

Looks good, but could we get a note on the semantics in the doc comment on field / struct? Specifically, this will result in it parsing a missing password as an empty vec, and then when reserialized it will show as password : "" (ie, empty string)

Copy link
Collaborator

Choose a reason for hiding this comment

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

I can take a look at merging this in tomorrow, though, which should get it in time to go out with our next release

Copy link
Contributor Author

Choose a reason for hiding this comment

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

it's done and thanks for your reactivity ! 😃

@flobz flobz force-pushed the feat/x509_iot_auth_req branch 2 times, most recently from c27b8d4 to 80aa551 Compare March 4, 2026 07:29
Make IoTCoreMqttContext.password optional to support X509/mutual TLS
custom authorizers where AWS IoT does not send username or password
fields. Add x509_certificate_pem and principal_id fields to
IoTCoreTlsContext for X509 certificate-based authentication. Add test
fixture and test for the X509 authorizer payload.
@flobz flobz force-pushed the feat/x509_iot_auth_req branch from 80aa551 to ea25ada Compare March 4, 2026 09:35
Copy link
Collaborator

@jlizen jlizen left a comment

Choose a reason for hiding this comment

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

Thanks for the contribution! This will go out next release.

@jlizen jlizen merged commit f0652ff into aws:main Mar 4, 2026
11 checks passed
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.

2 participants