Skip to content

Navigation Menu

Sign in
Sign up

fix(lambda-events): omit null IoT policy documents #1168

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

Open
IamPritamAcharya wants to merge 1 commit into aws:main
base: main
Choose a base branch
Loading
from IamPritamAcharya:fix/iot-authorizer-null-policy-documents
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions lambda-events/src/custom_serde/mod.rs
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use base64::Engine;
use serde::{
de::{Deserialize, Deserializer, Error as DeError},
ser::Serializer,
Serialize,
};

#[cfg(feature = "codebuild")]
Expand Down Expand Up @@ -57,6 +58,14 @@ where
serializer.serialize_str(&base64::engine::general_purpose::STANDARD.encode(value))
}

pub(crate) fn serialize_non_null<S, T>(values: &[Option<T>], serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
T: Serialize,
{
serializer.collect_seq(values.iter().flatten())
}

/// Deserializes any `Default` type, mapping JSON `null` to `T::default()`.
///
/// **Note** null-to-empty semantics are usually clear for container types (Map, Vec, etc).
Expand Down
73 changes: 72 additions & 1 deletion lambda-events/src/event/iot/mod.rs
View file Open in desktop
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
use crate::{custom_serde::serialize_headers, encodings::Base64Data, iam::IamPolicyDocument};
use crate::{
custom_serde::{serialize_headers, serialize_non_null},
encodings::Base64Data,
iam::IamPolicyDocument,
};
#[cfg(feature = "builders")]
use bon::Builder;
use http::HeaderMap;
Expand Down Expand Up @@ -141,6 +145,9 @@ pub struct IoTCoreCustomAuthorizerResponse {
pub principal_id: Option<String>,
pub disconnect_after_in_seconds: u32,
pub refresh_after_in_seconds: u32,
/// Policy documents returned to AWS IoT. `None` entries are omitted during serialization because AWS IoT rejects
/// null policy documents.
#[serde(serialize_with = "serialize_non_null")]
pub policy_documents: Vec<Option<IamPolicyDocument>>,
/// Catchall to catch any additional fields that were present but not explicitly defined by this struct.
/// Enabled with Cargo feature `catch-all-fields`.
Expand All @@ -156,6 +163,28 @@ pub struct IoTCoreCustomAuthorizerResponse {
mod test {
use super::*;

fn custom_auth_response_with_policy_documents(
policy_documents: Vec<Option<IamPolicyDocument>>,
) -> IoTCoreCustomAuthorizerResponse {
let data = include_bytes!("../../fixtures/example-iot-custom-auth-response.json");
let mut response: IoTCoreCustomAuthorizerResponse = serde_json::from_slice(data).unwrap();
response.policy_documents = policy_documents;
response
}

fn policy_document(version: &str) -> IamPolicyDocument {
serde_json::from_value(serde_json::json!({
"Version": version,
"Statement": []
}))
.unwrap()
}

fn serialized_policy_documents(policy_documents: Vec<Option<IamPolicyDocument>>) -> serde_json::Value {
let response = custom_auth_response_with_policy_documents(policy_documents);
serde_json::to_value(response).unwrap()["policyDocuments"].clone()
}

#[test]
#[cfg(feature = "iot")]
fn example_iot_custom_auth_request() {
Expand Down Expand Up @@ -185,4 +214,46 @@ mod test {
let reparsed: IoTCoreCustomAuthorizerResponse = serde_json::from_slice(output.as_bytes()).unwrap();
assert_eq!(parsed, reparsed);
}

#[test]
fn iot_custom_auth_response_serializes_policy_document() {
let policy = policy_document("2012年10月17日");

assert_eq!(
serde_json::json!([policy]),
serialized_policy_documents(vec![Some(policy)])
);
}

#[test]
fn iot_custom_auth_response_filters_none_policy_documents() {
let first_policy = policy_document("2012年10月17日");
let second_policy = policy_document("2008年10月17日");

assert_eq!(
serde_json::json!([first_policy, second_policy]),
serialized_policy_documents(vec![Some(first_policy), None, Some(second_policy)])
);
}

#[test]
fn iot_custom_auth_response_serializes_only_none_as_empty_array() {
assert_eq!(serde_json::json!([]), serialized_policy_documents(vec![None]));
}

#[test]
fn iot_custom_auth_response_serializes_empty_policy_documents_as_empty_array() {
assert_eq!(serde_json::json!([]), serialized_policy_documents(vec![]));
}

#[test]
fn iot_custom_auth_response_deserializes_null_policy_document() {
let response = custom_auth_response_with_policy_documents(vec![None]);
let mut serialized = serde_json::to_value(response).unwrap();
serialized["policyDocuments"] = serde_json::json!([null]);

let deserialized: IoTCoreCustomAuthorizerResponse = serde_json::from_value(serialized).unwrap();

assert_eq!(vec![None], deserialized.policy_documents);
}
}

AltStyle によって変換されたページ (->オリジナル) /