From 44e6168d8f393d404765bd4535aadf8e12940019 Mon Sep 17 00:00:00 2001 From: RWCoder Date: Mon, 27 Oct 2025 21:25:54 -0400 Subject: [PATCH 1/3] Add NotResource field for custom authorizer IAM policy --- .../APIGatewayCustomAuthorizerPolicy.cs | 10 ++- .../Amazon.Lambda.APIGatewayEvents.csproj | 2 +- .../TestCallingWebAPI.cs | 7 +- .../test/EventsTests.Shared/EventTests.cs | 66 +++++++++++++++++++ 4 files changed, 80 insertions(+), 5 deletions(-) diff --git a/Libraries/src/Amazon.Lambda.APIGatewayEvents/APIGatewayCustomAuthorizerPolicy.cs b/Libraries/src/Amazon.Lambda.APIGatewayEvents/APIGatewayCustomAuthorizerPolicy.cs index 2e0d796f0..59fd940f3 100644 --- a/Libraries/src/Amazon.Lambda.APIGatewayEvents/APIGatewayCustomAuthorizerPolicy.cs +++ b/Libraries/src/Amazon.Lambda.APIGatewayEvents/APIGatewayCustomAuthorizerPolicy.cs @@ -1,4 +1,4 @@ -namespace Amazon.Lambda.APIGatewayEvents +namespace Amazon.Lambda.APIGatewayEvents { using System.Collections.Generic; @@ -52,6 +52,14 @@ public class IAMPolicyStatement #endif public HashSet Resource { get; set; } + /// + /// Gets or sets the resources the statement does not apply to. + /// +#if NETCOREAPP3_1_OR_GREATER + [System.Text.Json.Serialization.JsonPropertyName("NotResource")] +#endif + public HashSet NotResource { get; set; } + /// /// Gets or sets the conditions for when a policy is in effect. /// https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_condition.html diff --git a/Libraries/src/Amazon.Lambda.APIGatewayEvents/Amazon.Lambda.APIGatewayEvents.csproj b/Libraries/src/Amazon.Lambda.APIGatewayEvents/Amazon.Lambda.APIGatewayEvents.csproj index 6b7ee52d8..bcd4f3591 100644 --- a/Libraries/src/Amazon.Lambda.APIGatewayEvents/Amazon.Lambda.APIGatewayEvents.csproj +++ b/Libraries/src/Amazon.Lambda.APIGatewayEvents/Amazon.Lambda.APIGatewayEvents.csproj @@ -6,7 +6,7 @@ netstandard2.0;netcoreapp3.1;net8.0 Amazon Lambda .NET Core support - API Gateway package. Amazon.Lambda.APIGatewayEvents - 2.7.1 + 2.7.2 Amazon.Lambda.APIGatewayEvents Amazon.Lambda.APIGatewayEvents AWS;Amazon;Lambda diff --git a/Libraries/test/Amazon.Lambda.AspNetCoreServer.Test/TestCallingWebAPI.cs b/Libraries/test/Amazon.Lambda.AspNetCoreServer.Test/TestCallingWebAPI.cs index f1f7f63c9..042b2e46b 100644 --- a/Libraries/test/Amazon.Lambda.AspNetCoreServer.Test/TestCallingWebAPI.cs +++ b/Libraries/test/Amazon.Lambda.AspNetCoreServer.Test/TestCallingWebAPI.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.IO.Compression; @@ -221,10 +221,11 @@ public void TestCustomAuthorizerSerialization() var json = JsonSerializer.Serialize(response, new JsonSerializerOptions { - Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping + Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping, + DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull }); Assert.NotNull(json); - var expected = "{\"principalId\":\"com.amazon.someuser\",\"policyDocument\":{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Action\":[\"execute-api:Invoke\"],\"Resource\":[\"arn:aws:execute-api:us-west-2:1234567890:apit123d45/Prod/GET/*\"],\"Condition\":null}]},\"context\":{\"stringKey\":\"Hey I'm a string\",\"boolKey\":true,\"numKey\":9},\"usageIdentifierKey\":null}"; + var expected = "{\"principalId\":\"com.amazon.someuser\",\"policyDocument\":{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Action\":[\"execute-api:Invoke\"],\"Resource\":[\"arn:aws:execute-api:us-west-2:1234567890:apit123d45/Prod/GET/*\"]}]},\"context\":{\"stringKey\":\"Hey I'm a string\",\"boolKey\":true,\"numKey\":9}}"; Assert.Equal(expected, json); } diff --git a/Libraries/test/EventsTests.Shared/EventTests.cs b/Libraries/test/EventsTests.Shared/EventTests.cs index 24ee824bd..f52472265 100644 --- a/Libraries/test/EventsTests.Shared/EventTests.cs +++ b/Libraries/test/EventsTests.Shared/EventTests.cs @@ -2165,6 +2165,72 @@ public void APIGatewayAuthorizerWithMultiValueIAMConditionResponseTest(Type seri Assert.Equal("arn:aws:iam::XXXXXXXXXXXX:user/User2", root["policyDocument"]["Statement"][0]["Condition"]["ArnLike"]["aws:PrincipalArn"][1]); } + [Theory] + [InlineData(typeof(JsonSerializer))] +#if NETCOREAPP3_1_OR_GREATER + [InlineData(typeof(Amazon.Lambda.Serialization.SystemTextJson.LambdaJsonSerializer))] + [InlineData(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))] +#endif + public void APIGatewayAuthorizerResponseNotResourceTest(Type serializerType) + { + var serializer = Activator.CreateInstance(serializerType) as ILambdaSerializer; + var context = new APIGatewayCustomAuthorizerContextOutput(); + context["field1"] = "value1"; + context["field2"] = "value2"; + + var response = new APIGatewayCustomAuthorizerResponse + { + PrincipalID = "prin1", + UsageIdentifierKey = "usageKey", + Context = context, + PolicyDocument = new APIGatewayCustomAuthorizerPolicy + { + Version = "2012-10-17", + Statement = new List + { + new APIGatewayCustomAuthorizerPolicy.IAMPolicyStatement + { + Action = new HashSet{ "execute-api:Invoke" }, + Effect = "Deny", + NotResource = new HashSet + { + "arn:aws:execute-api:us-east-1:1234567890:abcdef1234/Prod/GET/resource1", + "arn:aws:execute-api:us-east-1:1234567890:abcdef1234/Prod/GET/resource2" + } + } + } + } + }; + + string serializedJson; + using (MemoryStream stream = new MemoryStream()) + { + serializer.Serialize(response, stream); + + stream.Position = 0; + serializedJson = Encoding.UTF8.GetString(stream.ToArray()); + } + + JObject root = Newtonsoft.Json.JsonConvert.DeserializeObject(serializedJson) as JObject; + + Assert.Equal("prin1", root["principalId"]); + Assert.Equal("usageKey", root["usageIdentifierKey"]); + Assert.Equal("value1", root["context"]["field1"]); + Assert.Equal("value2", root["context"]["field2"]); + + Assert.Equal("2012-10-17", root["policyDocument"]["Version"]); + Assert.Equal("execute-api:Invoke", root["policyDocument"]["Statement"][0]["Action"][0]); + Assert.Equal("Deny", root["policyDocument"]["Statement"][0]["Effect"]); + + var allowedResources = root["policyDocument"]["Statement"][0]["NotResource"]; + Assert.Equal(2, allowedResources.Count()); + Assert.Contains("arn:aws:execute-api:us-east-1:1234567890:abcdef1234/Prod/GET/resource1", allowedResources); + Assert.Contains("arn:aws:execute-api:us-east-1:1234567890:abcdef1234/Prod/GET/resource2", allowedResources); + + Assert.Null(root["policyDocument"]["Statement"][0]["Condition"]); + Assert.Null(root["policyDocument"]["Statement"][0]["Resource"]); + } + [Theory] [InlineData(typeof(JsonSerializer))] #if NETCOREAPP3_1_OR_GREATER From d4bf7253981d86886fdd3f0c35ba5a0c7fd8238f Mon Sep 17 00:00:00 2001 From: RWCoder Date: Tue, 28 Oct 2025 19:01:56 -0400 Subject: [PATCH 2/3] Created change file --- .../changes/b0df0353-6e47-4548-94a7-45b42f67b910.json | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .autover/changes/b0df0353-6e47-4548-94a7-45b42f67b910.json diff --git a/.autover/changes/b0df0353-6e47-4548-94a7-45b42f67b910.json b/.autover/changes/b0df0353-6e47-4548-94a7-45b42f67b910.json new file mode 100644 index 000000000..147f21333 --- /dev/null +++ b/.autover/changes/b0df0353-6e47-4548-94a7-45b42f67b910.json @@ -0,0 +1,11 @@ +{ + "Projects": [ + { + "Name": "Amazon.Lambda.APIGatewayEvents", + "Type": "Patch", + "ChangelogMessages": [ + "Added NotResource field to APIGatewayCustomAuthorizerPolicy.IAMPolicyStatement" + ] + } + ] +} \ No newline at end of file From 80e2fc5b8237ac3fb58a8141007622e7e163cae3 Mon Sep 17 00:00:00 2001 From: RWCoder Date: Tue, 28 Oct 2025 20:02:12 -0400 Subject: [PATCH 3/3] Revert manual version bump --- .../Amazon.Lambda.APIGatewayEvents.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Libraries/src/Amazon.Lambda.APIGatewayEvents/Amazon.Lambda.APIGatewayEvents.csproj b/Libraries/src/Amazon.Lambda.APIGatewayEvents/Amazon.Lambda.APIGatewayEvents.csproj index bcd4f3591..6b7ee52d8 100644 --- a/Libraries/src/Amazon.Lambda.APIGatewayEvents/Amazon.Lambda.APIGatewayEvents.csproj +++ b/Libraries/src/Amazon.Lambda.APIGatewayEvents/Amazon.Lambda.APIGatewayEvents.csproj @@ -6,7 +6,7 @@ netstandard2.0;netcoreapp3.1;net8.0 Amazon Lambda .NET Core support - API Gateway package. Amazon.Lambda.APIGatewayEvents - 2.7.2 + 2.7.1 Amazon.Lambda.APIGatewayEvents Amazon.Lambda.APIGatewayEvents AWS;Amazon;Lambda