From f27e5a86032a4c71d559aef2ef838e946bd0ca71 Mon Sep 17 00:00:00 2001 From: msailes Date: Wed, 6 Jan 2021 10:13:11 +0000 Subject: [PATCH 1/4] initial tests --- aws-lambda-java-events/pom.xml | 13 + .../runtime/events/IamPolicyResponse.java | 265 ++++++++++++++++++ .../runtime/events/IamPolicyResponseTest.java | 72 +++++ .../src/test/resources/allow-all.json | 17 ++ .../src/test/resources/allow-one.json | 17 ++ .../src/test/resources/deny-all.json | 17 ++ .../src/test/resources/deny-one.json | 17 ++ 7 files changed, 418 insertions(+) create mode 100644 aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/IamPolicyResponse.java create mode 100644 aws-lambda-java-events/src/test/java/com/amazonaws/services/lambda/runtime/events/IamPolicyResponseTest.java create mode 100644 aws-lambda-java-events/src/test/resources/allow-all.json create mode 100644 aws-lambda-java-events/src/test/resources/allow-one.json create mode 100644 aws-lambda-java-events/src/test/resources/deny-all.json create mode 100644 aws-lambda-java-events/src/test/resources/deny-one.json diff --git a/aws-lambda-java-events/pom.xml b/aws-lambda-java-events/pom.xml index 3d9be9bb..b88adbff 100644 --- a/aws-lambda-java-events/pom.xml +++ b/aws-lambda-java-events/pom.xml @@ -56,6 +56,19 @@ 5.7.0 test + + com.fasterxml.jackson.core + jackson-databind + 2.10.4 + test + + + net.javacrumbs.json-unit + json-unit-assertj + 2.22.0 + test + + org.projectlombok lombok diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/IamPolicyResponse.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/IamPolicyResponse.java new file mode 100644 index 00000000..99b6efd7 --- /dev/null +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/IamPolicyResponse.java @@ -0,0 +1,265 @@ +package com.amazonaws.services.lambda.runtime.events; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * IamPolicyResponse receives a set of allowed and denied methods and generates a valid + * AWS policy for the API Gateway authorizer. The constructor receives the calling + * user principal, the AWS account ID of the API owner, and an apiOptions object. + * The apiOptions can contain an API Gateway RestApi Id, a region for the RestApi, and a + * stage that calls should be allowed/denied for. For example + */ +public class IamPolicyResponse { + + public static final String VERSION = "Version"; + public static final String STATEMENT = "Statement"; + public static final String EFFECT = "Effect"; + public static final String ACTION = "Action"; + public static final String RESOURCE = "Resource"; + public static final String CONDITION = "Condition"; + + String principalId; + transient IamPolicyResponse.PolicyDocument policyDocumentObject; + Map policyDocument; + + public IamPolicyResponse(String principalId, IamPolicyResponse.PolicyDocument policyDocumentObject) { + this.principalId = principalId; + this.policyDocumentObject = policyDocumentObject; + } + + public IamPolicyResponse() { + } + + public String getPrincipalId() { + return principalId; + } + + public void setPrincipalId(String principalId) { + this.principalId = principalId; + } + + /** + * IAM Policies use capitalized field names, but Lambda by default will serialize object members using camel case + * + * This method implements a custom serializer to return the IAM Policy as a well-formed JSON document, with the correct field names + * + * @return IAM Policy as a well-formed JSON document + */ + public Map getPolicyDocument() { + Map serializablePolicy = new HashMap<>(); + serializablePolicy.put(VERSION, policyDocumentObject.version); + Statement[] statements = policyDocumentObject.getStatement(); + Map[] serializableStatementArray = new Map[statements.length]; + for (int i = 0; i < statements.length; i++) { + Map serializableStatement = new HashMap<>(); + IamPolicyResponse.Statement statement = statements[i]; + serializableStatement.put(EFFECT, statement.Effect); + serializableStatement.put(ACTION, statement.Action); + serializableStatement.put(RESOURCE, statement.getResource()); + serializableStatement.put(CONDITION, statement.getCondition()); + serializableStatementArray[i] = serializableStatement; + } + serializablePolicy.put(STATEMENT, serializableStatementArray); + return serializablePolicy; + } + + public void setPolicyDocument(PolicyDocument policyDocumentObject) { + this.policyDocumentObject = policyDocumentObject; + } + + /** + * PolicyDocument represents an IAM Policy, specifically for the execute-api:Invoke action + * in the context of a API Gateway Authorizer + * + * Initialize the PolicyDocument with + * the region where the RestApi is configured, + * the AWS Account ID that owns the RestApi, + * the RestApi identifier + * and the Stage on the RestApi that the Policy will apply to + */ + public static class PolicyDocument { + + static final String EXECUTE_API_ARN_FORMAT = "arn:aws:execute-api:%s:%s:%s/%s/%s/%s"; + + private String version = "2012-10-17"; + + private Statement allowStatement; + private Statement denyStatement; + private List statements; + + // context metadata + transient String region; + transient String awsAccountId; + transient String restApiId; + transient String stage; + + /** + * Creates a new PolicyDocument with the given context, + * and initializes two base Statement objects for allowing and denying access to API Gateway methods + * + * @param region the region where the RestApi is configured + * @param awsAccountId the AWS Account ID that owns the RestApi + * @param restApiId the RestApi identifier + * @param stage and the Stage on the RestApi that the Policy will apply to + */ + public PolicyDocument(String region, String awsAccountId, String restApiId, String stage) { + this.region = region; + this.awsAccountId = awsAccountId; + this.restApiId = restApiId; + this.stage = stage; + allowStatement = Statement.getEmptyInvokeStatement("Allow"); + denyStatement = Statement.getEmptyInvokeStatement("Deny"); + this.statements = new ArrayList<>(); + statements.add(allowStatement); + statements.add(denyStatement); + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public IamPolicyResponse.Statement[] getStatement() { + return statements.toArray(new IamPolicyResponse.Statement[statements.size()]); + } + + public void allowMethod(HttpMethod httpMethod, String resourcePath) { + addResourceToStatement(allowStatement, httpMethod, resourcePath); + } + + public void denyMethod(HttpMethod httpMethod, String resourcePath) { + addResourceToStatement(denyStatement, httpMethod, resourcePath); + } + + public void addStatement(IamPolicyResponse.Statement statement) { + statements.add(statement); + } + + private void addResourceToStatement(Statement statement, HttpMethod httpMethod, String resourcePath) { + // resourcePath must start with '/' + // to specify the root resource only, resourcePath should be an empty string + if (resourcePath.equals("/")) { + resourcePath = ""; + } + String resource = resourcePath.startsWith("/") ? resourcePath.substring(1) : resourcePath; + String method = httpMethod == HttpMethod.ALL ? "*" : httpMethod.toString(); + statement.addResource(String.format(EXECUTE_API_ARN_FORMAT, region, awsAccountId, restApiId, stage, method, resource)); + } + + // Static methods + + /** + * Generates a new PolicyDocument with a single statement that allows the requested method/resourcePath + * + * @param region API Gateway region + * @param awsAccountId AWS Account that owns the API Gateway RestApi + * @param restApiId RestApi identifier + * @param stage Stage name + * @param method HttpMethod to allow + * @param resourcePath Resource path to allow + * @return new PolicyDocument that allows the requested method/resourcePath + */ + public static PolicyDocument getAllowOnePolicy(String region, String awsAccountId, String restApiId, String stage, HttpMethod method, String resourcePath) { + IamPolicyResponse.PolicyDocument policyDocument = new IamPolicyResponse.PolicyDocument(region, awsAccountId, restApiId, stage); + policyDocument.allowMethod(method, resourcePath); + return policyDocument; + + } + + + /** + * Generates a new PolicyDocument with a single statement that denies the requested method/resourcePath + * + * @param region API Gateway region + * @param awsAccountId AWS Account that owns the API Gateway RestApi + * @param restApiId RestApi identifier + * @param stage Stage name + * @param method HttpMethod to deny + * @param resourcePath Resource path to deny + * @return new PolicyDocument that denies the requested method/resourcePath + */ + public static PolicyDocument getDenyOnePolicy(String region, String awsAccountId, String restApiId, String stage, HttpMethod method, String resourcePath) { + IamPolicyResponse.PolicyDocument policyDocument = new IamPolicyResponse.PolicyDocument(region, awsAccountId, restApiId, stage); + policyDocument.denyMethod(method, resourcePath); + return policyDocument; + + } + + public static IamPolicyResponse.PolicyDocument getAllowAllPolicy(String region, String awsAccountId, String restApiId, String stage) { + return getAllowOnePolicy(region, awsAccountId, restApiId, stage, HttpMethod.ALL, "*"); + } + + public static PolicyDocument getDenyAllPolicy(String region, String awsAccountId, String restApiId, String stage) { + return getDenyOnePolicy(region, awsAccountId, restApiId, stage, HttpMethod.ALL, "*"); + } + } + + public enum HttpMethod { + GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS, ALL + } + + static class Statement { + + String Effect; + String Action; + Map> Condition; + + private List resourceList; + + public Statement() { + + } + + public Statement(String effect, String action, List resourceList, Map> condition) { + this.Effect = effect; + this.Action = action; + this.resourceList = resourceList; + this.Condition = condition; + } + + public static Statement getEmptyInvokeStatement(String effect) { + return new Statement(effect, "execute-api:Invoke", new ArrayList<>(), new HashMap<>()); + } + + public String getEffect() { + return Effect; + } + + public void setEffect(String effect) { + this.Effect = effect; + } + + public String getAction() { + return Action; + } + + public void setAction(String action) { + this.Action = action; + } + + public String[] getResource() { + return resourceList.toArray(new String[resourceList.size()]); + } + + public void addResource(String resource) { + resourceList.add(resource); + } + + public Map> getCondition() { + return Condition; + } + + public void addCondition(String operator, String key, Object value) { + Condition.put(operator, Collections.singletonMap(key, value)); + } + + } + +} \ No newline at end of file diff --git a/aws-lambda-java-events/src/test/java/com/amazonaws/services/lambda/runtime/events/IamPolicyResponseTest.java b/aws-lambda-java-events/src/test/java/com/amazonaws/services/lambda/runtime/events/IamPolicyResponseTest.java new file mode 100644 index 00000000..4f35a2dc --- /dev/null +++ b/aws-lambda-java-events/src/test/java/com/amazonaws/services/lambda/runtime/events/IamPolicyResponseTest.java @@ -0,0 +1,72 @@ +package com.amazonaws.services.lambda.runtime.events; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import static net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson; + +public class IamPolicyResponseTest { + + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + public static final String REGION = "eu-west-1"; + public static final String AWS_ACCOUNT_ID = "123456789012"; + public static final String REST_API_ID = "1234abc"; + public static final String STAGE = "$deafult"; + public static final String PRINCIPAL_ID = "me"; + + @Test + public void testAllowAllStatement() throws JsonProcessingException { + IamPolicyResponse iamPolicyResponse = new IamPolicyResponse(PRINCIPAL_ID, IamPolicyResponse.PolicyDocument.getAllowAllPolicy(REGION, AWS_ACCOUNT_ID, REST_API_ID, STAGE)); + + String json = OBJECT_MAPPER.writeValueAsString(iamPolicyResponse); + + assertThatJson(json).isEqualTo(readResource("allow-all.json")); + } + + @Test + public void testAllowOneStatement() throws JsonProcessingException { + IamPolicyResponse iamPolicyResponse = new IamPolicyResponse(PRINCIPAL_ID, IamPolicyResponse.PolicyDocument.getAllowOnePolicy(REGION, AWS_ACCOUNT_ID, REST_API_ID, STAGE, IamPolicyResponse.HttpMethod.GET, "/test")); + + String json = OBJECT_MAPPER.writeValueAsString(iamPolicyResponse); + + assertThatJson(json).isEqualTo(readResource("allow-one.json")); + } + + @Test + public void testDenyAllStatement() throws JsonProcessingException { + IamPolicyResponse iamPolicyResponse = new IamPolicyResponse(PRINCIPAL_ID, IamPolicyResponse.PolicyDocument.getDenyAllPolicy(REGION, AWS_ACCOUNT_ID, REST_API_ID, STAGE)); + + String json = OBJECT_MAPPER.writeValueAsString(iamPolicyResponse); + System.out.println(json); + + assertThatJson(json).isEqualTo(readResource("deny-all.json")); + } + + @Test + public void testDenyOneStatement() throws JsonProcessingException { + IamPolicyResponse iamPolicyResponse = new IamPolicyResponse(PRINCIPAL_ID, IamPolicyResponse.PolicyDocument.getDenyOnePolicy(REGION, AWS_ACCOUNT_ID, REST_API_ID, STAGE, IamPolicyResponse.HttpMethod.GET, "/test")); + + String json = OBJECT_MAPPER.writeValueAsString(iamPolicyResponse); + System.out.println(json); + + assertThatJson(json).isEqualTo(readResource("deny-one.json")); + } + + private String readResource(String name) { + Path filePath = Paths.get("src", "test", "resources", name); + byte[] bytes = new byte[0]; + try { + bytes = Files.readAllBytes(filePath); + } catch (IOException e) { + e.printStackTrace(); + } + return new String(bytes, StandardCharsets.UTF_8); + } +} \ No newline at end of file diff --git a/aws-lambda-java-events/src/test/resources/allow-all.json b/aws-lambda-java-events/src/test/resources/allow-all.json new file mode 100644 index 00000000..bc0681ff --- /dev/null +++ b/aws-lambda-java-events/src/test/resources/allow-all.json @@ -0,0 +1,17 @@ +{ + "principalId": "me", + "policyDocument": { + "Version": "2012-10-17", + "Statement": [{ + "Condition": {}, + "Action": "execute-api:Invoke", + "Resource": ["arn:aws:execute-api:eu-west-1:123456789012:1234abc/$deafult/*/*"], + "Effect": "Allow" + }, { + "Condition": {}, + "Action": "execute-api:Invoke", + "Resource": [], + "Effect": "Deny" + }] + } +} \ No newline at end of file diff --git a/aws-lambda-java-events/src/test/resources/allow-one.json b/aws-lambda-java-events/src/test/resources/allow-one.json new file mode 100644 index 00000000..6dca0558 --- /dev/null +++ b/aws-lambda-java-events/src/test/resources/allow-one.json @@ -0,0 +1,17 @@ +{ + "principalId": "me", + "policyDocument": { + "Version": "2012-10-17", + "Statement": [{ + "Condition": {}, + "Action": "execute-api:Invoke", + "Resource": ["arn:aws:execute-api:eu-west-1:123456789012:1234abc/$deafult/GET/test"], + "Effect": "Allow" + }, { + "Condition": {}, + "Action": "execute-api:Invoke", + "Resource": [], + "Effect": "Deny" + }] + } +} \ No newline at end of file diff --git a/aws-lambda-java-events/src/test/resources/deny-all.json b/aws-lambda-java-events/src/test/resources/deny-all.json new file mode 100644 index 00000000..9db8813c --- /dev/null +++ b/aws-lambda-java-events/src/test/resources/deny-all.json @@ -0,0 +1,17 @@ +{ + "principalId": "me", + "policyDocument": { + "Version": "2012-10-17", + "Statement": [{ + "Condition": {}, + "Action": "execute-api:Invoke", + "Resource": [], + "Effect": "Allow" + }, { + "Condition": {}, + "Action": "execute-api:Invoke", + "Resource": ["arn:aws:execute-api:eu-west-1:123456789012:1234abc/$deafult/*/*"], + "Effect": "Deny" + }] + } +} \ No newline at end of file diff --git a/aws-lambda-java-events/src/test/resources/deny-one.json b/aws-lambda-java-events/src/test/resources/deny-one.json new file mode 100644 index 00000000..581f8c3d --- /dev/null +++ b/aws-lambda-java-events/src/test/resources/deny-one.json @@ -0,0 +1,17 @@ +{ + "principalId": "me", + "policyDocument": { + "Version": "2012-10-17", + "Statement": [{ + "Condition": {}, + "Action": "execute-api:Invoke", + "Resource": [], + "Effect": "Allow" + }, { + "Condition": {}, + "Action": "execute-api:Invoke", + "Resource": ["arn:aws:execute-api:eu-west-1:123456789012:1234abc/$deafult/GET/test"], + "Effect": "Deny" + }] + } +} \ No newline at end of file From 68ec120a09ccb746ad68c376b16adf85ab765aaf Mon Sep 17 00:00:00 2001 From: msailes Date: Fri, 8 Jan 2021 16:05:34 +0000 Subject: [PATCH 2/4] moved the code to use lombok annotations --- .../runtime/events/IamPolicyResponse.java | 295 ++++-------------- .../runtime/events/IamPolicyResponseTest.java | 47 +-- .../{ => iamPolicyResponses}/allow-all.json | 9 +- .../{ => iamPolicyResponses}/allow-one.json | 0 .../{ => iamPolicyResponses}/deny-all.json | 0 .../{ => iamPolicyResponses}/deny-one.json | 0 6 files changed, 70 insertions(+), 281 deletions(-) rename aws-lambda-java-events/src/test/resources/{ => iamPolicyResponses}/allow-all.json (64%) rename aws-lambda-java-events/src/test/resources/{ => iamPolicyResponses}/allow-one.json (100%) rename aws-lambda-java-events/src/test/resources/{ => iamPolicyResponses}/deny-all.json (100%) rename aws-lambda-java-events/src/test/resources/{ => iamPolicyResponses}/deny-one.json (100%) diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/IamPolicyResponse.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/IamPolicyResponse.java index 99b6efd7..d0823031 100644 --- a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/IamPolicyResponse.java +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/IamPolicyResponse.java @@ -1,265 +1,84 @@ package com.amazonaws.services.lambda.runtime.events; -import java.util.ArrayList; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; -/** - * IamPolicyResponse receives a set of allowed and denied methods and generates a valid - * AWS policy for the API Gateway authorizer. The constructor receives the calling - * user principal, the AWS account ID of the API owner, and an apiOptions object. - * The apiOptions can contain an API Gateway RestApi Id, a region for the RestApi, and a - * stage that calls should be allowed/denied for. For example - */ -public class IamPolicyResponse { - - public static final String VERSION = "Version"; - public static final String STATEMENT = "Statement"; - public static final String EFFECT = "Effect"; - public static final String ACTION = "Action"; - public static final String RESOURCE = "Resource"; - public static final String CONDITION = "Condition"; +@Data +@Builder(setterPrefix = "with") +@NoArgsConstructor +@AllArgsConstructor +public class IamPolicyResponse implements Serializable, Cloneable { - String principalId; - transient IamPolicyResponse.PolicyDocument policyDocumentObject; - Map policyDocument; + public static final String EXECUTE_API_INVOKE = "execute-api:Invoke"; + public static final String VERSION_2012_10_17 = "2012-10-17"; + public static final String ALLOW = "Allow"; + public static final String DENY = "Deny"; - public IamPolicyResponse(String principalId, IamPolicyResponse.PolicyDocument policyDocumentObject) { - this.principalId = principalId; - this.policyDocumentObject = policyDocumentObject; - } - - public IamPolicyResponse() { - } - - public String getPrincipalId() { - return principalId; - } - - public void setPrincipalId(String principalId) { - this.principalId = principalId; - } + private String principalId; + private PolicyDocument policyDocument; + private Map context; - /** - * IAM Policies use capitalized field names, but Lambda by default will serialize object members using camel case - * - * This method implements a custom serializer to return the IAM Policy as a well-formed JSON document, with the correct field names - * - * @return IAM Policy as a well-formed JSON document - */ public Map getPolicyDocument() { Map serializablePolicy = new HashMap<>(); - serializablePolicy.put(VERSION, policyDocumentObject.version); - Statement[] statements = policyDocumentObject.getStatement(); - Map[] serializableStatementArray = new Map[statements.length]; - for (int i = 0; i < statements.length; i++) { + serializablePolicy.put("Version", policyDocument.getVersion()); + + int numberOfStatements = policyDocument.getStatement().size(); + Map[] serializableStatementArray = new Map[numberOfStatements]; + for (int i = 0; i < numberOfStatements; i++) { + Statement statement = policyDocument.getStatement().get(i); Map serializableStatement = new HashMap<>(); - IamPolicyResponse.Statement statement = statements[i]; - serializableStatement.put(EFFECT, statement.Effect); - serializableStatement.put(ACTION, statement.Action); - serializableStatement.put(RESOURCE, statement.getResource()); - serializableStatement.put(CONDITION, statement.getCondition()); + serializableStatement.put("Effect", statement.getEffect()); + serializableStatement.put("Action", statement.getAction()); + serializableStatement.put("Resource", statement.getResource().toArray(new String[statement.getResource().size()])); +// serializableStatement.put(CONDITION, statement.getCondition()); serializableStatementArray[i] = serializableStatement; } - serializablePolicy.put(STATEMENT, serializableStatementArray); + serializablePolicy.put("Statement", serializableStatementArray); return serializablePolicy; } - public void setPolicyDocument(PolicyDocument policyDocumentObject) { - this.policyDocumentObject = policyDocumentObject; + public static Statement allowStatement(String resource) { + return Statement.builder() + .withEffect(ALLOW) + .withResource(Collections.singletonList(resource)) + .withAction(EXECUTE_API_INVOKE) + .build(); } - /** - * PolicyDocument represents an IAM Policy, specifically for the execute-api:Invoke action - * in the context of a API Gateway Authorizer - * - * Initialize the PolicyDocument with - * the region where the RestApi is configured, - * the AWS Account ID that owns the RestApi, - * the RestApi identifier - * and the Stage on the RestApi that the Policy will apply to - */ - public static class PolicyDocument { - - static final String EXECUTE_API_ARN_FORMAT = "arn:aws:execute-api:%s:%s:%s/%s/%s/%s"; - - private String version = "2012-10-17"; - - private Statement allowStatement; - private Statement denyStatement; - private List statements; - - // context metadata - transient String region; - transient String awsAccountId; - transient String restApiId; - transient String stage; - - /** - * Creates a new PolicyDocument with the given context, - * and initializes two base Statement objects for allowing and denying access to API Gateway methods - * - * @param region the region where the RestApi is configured - * @param awsAccountId the AWS Account ID that owns the RestApi - * @param restApiId the RestApi identifier - * @param stage and the Stage on the RestApi that the Policy will apply to - */ - public PolicyDocument(String region, String awsAccountId, String restApiId, String stage) { - this.region = region; - this.awsAccountId = awsAccountId; - this.restApiId = restApiId; - this.stage = stage; - allowStatement = Statement.getEmptyInvokeStatement("Allow"); - denyStatement = Statement.getEmptyInvokeStatement("Deny"); - this.statements = new ArrayList<>(); - statements.add(allowStatement); - statements.add(denyStatement); - } - - public String getVersion() { - return version; - } - - public void setVersion(String version) { - this.version = version; - } - - public IamPolicyResponse.Statement[] getStatement() { - return statements.toArray(new IamPolicyResponse.Statement[statements.size()]); - } - - public void allowMethod(HttpMethod httpMethod, String resourcePath) { - addResourceToStatement(allowStatement, httpMethod, resourcePath); - } - - public void denyMethod(HttpMethod httpMethod, String resourcePath) { - addResourceToStatement(denyStatement, httpMethod, resourcePath); - } - - public void addStatement(IamPolicyResponse.Statement statement) { - statements.add(statement); - } - - private void addResourceToStatement(Statement statement, HttpMethod httpMethod, String resourcePath) { - // resourcePath must start with '/' - // to specify the root resource only, resourcePath should be an empty string - if (resourcePath.equals("/")) { - resourcePath = ""; - } - String resource = resourcePath.startsWith("/") ? resourcePath.substring(1) : resourcePath; - String method = httpMethod == HttpMethod.ALL ? "*" : httpMethod.toString(); - statement.addResource(String.format(EXECUTE_API_ARN_FORMAT, region, awsAccountId, restApiId, stage, method, resource)); - } - - // Static methods - - /** - * Generates a new PolicyDocument with a single statement that allows the requested method/resourcePath - * - * @param region API Gateway region - * @param awsAccountId AWS Account that owns the API Gateway RestApi - * @param restApiId RestApi identifier - * @param stage Stage name - * @param method HttpMethod to allow - * @param resourcePath Resource path to allow - * @return new PolicyDocument that allows the requested method/resourcePath - */ - public static PolicyDocument getAllowOnePolicy(String region, String awsAccountId, String restApiId, String stage, HttpMethod method, String resourcePath) { - IamPolicyResponse.PolicyDocument policyDocument = new IamPolicyResponse.PolicyDocument(region, awsAccountId, restApiId, stage); - policyDocument.allowMethod(method, resourcePath); - return policyDocument; - - } - - - /** - * Generates a new PolicyDocument with a single statement that denies the requested method/resourcePath - * - * @param region API Gateway region - * @param awsAccountId AWS Account that owns the API Gateway RestApi - * @param restApiId RestApi identifier - * @param stage Stage name - * @param method HttpMethod to deny - * @param resourcePath Resource path to deny - * @return new PolicyDocument that denies the requested method/resourcePath - */ - public static PolicyDocument getDenyOnePolicy(String region, String awsAccountId, String restApiId, String stage, HttpMethod method, String resourcePath) { - IamPolicyResponse.PolicyDocument policyDocument = new IamPolicyResponse.PolicyDocument(region, awsAccountId, restApiId, stage); - policyDocument.denyMethod(method, resourcePath); - return policyDocument; - - } - - public static IamPolicyResponse.PolicyDocument getAllowAllPolicy(String region, String awsAccountId, String restApiId, String stage) { - return getAllowOnePolicy(region, awsAccountId, restApiId, stage, HttpMethod.ALL, "*"); - } - - public static PolicyDocument getDenyAllPolicy(String region, String awsAccountId, String restApiId, String stage) { - return getDenyOnePolicy(region, awsAccountId, restApiId, stage, HttpMethod.ALL, "*"); - } - } - - public enum HttpMethod { - GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS, ALL + public static Statement denyStatement(String resource) { + return Statement.builder() + .withEffect(DENY) + .withResource(Collections.singletonList(resource)) + .withAction(EXECUTE_API_INVOKE) + .build(); } - static class Statement { - - String Effect; - String Action; - Map> Condition; - - private List resourceList; - - public Statement() { - - } - - public Statement(String effect, String action, List resourceList, Map> condition) { - this.Effect = effect; - this.Action = action; - this.resourceList = resourceList; - this.Condition = condition; - } - - public static Statement getEmptyInvokeStatement(String effect) { - return new Statement(effect, "execute-api:Invoke", new ArrayList<>(), new HashMap<>()); - } - - public String getEffect() { - return Effect; - } - - public void setEffect(String effect) { - this.Effect = effect; - } - - public String getAction() { - return Action; - } - - public void setAction(String action) { - this.Action = action; - } + @Data + @Builder(setterPrefix = "with") + @NoArgsConstructor + @AllArgsConstructor + public static class PolicyDocument implements Serializable, Cloneable { - public String[] getResource() { - return resourceList.toArray(new String[resourceList.size()]); - } - - public void addResource(String resource) { - resourceList.add(resource); - } - - public Map> getCondition() { - return Condition; - } + private String version; + private List statement; + } - public void addCondition(String operator, String key, Object value) { - Condition.put(operator, Collections.singletonMap(key, value)); - } + @Data + @Builder(setterPrefix = "with") + @NoArgsConstructor + @AllArgsConstructor + public static class Statement implements Serializable, Cloneable { + private String action; + private String effect; + private List resource; } - } \ No newline at end of file diff --git a/aws-lambda-java-events/src/test/java/com/amazonaws/services/lambda/runtime/events/IamPolicyResponseTest.java b/aws-lambda-java-events/src/test/java/com/amazonaws/services/lambda/runtime/events/IamPolicyResponseTest.java index 4f35a2dc..b214aae1 100644 --- a/aws-lambda-java-events/src/test/java/com/amazonaws/services/lambda/runtime/events/IamPolicyResponseTest.java +++ b/aws-lambda-java-events/src/test/java/com/amazonaws/services/lambda/runtime/events/IamPolicyResponseTest.java @@ -10,53 +10,28 @@ import java.nio.file.Path; import java.nio.file.Paths; +import static com.amazonaws.services.lambda.runtime.events.IamPolicyResponse.VERSION_2012_10_17; +import static com.amazonaws.services.lambda.runtime.events.IamPolicyResponse.allowStatement; +import static java.util.Collections.singletonList; import static net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson; public class IamPolicyResponseTest { private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); - public static final String REGION = "eu-west-1"; - public static final String AWS_ACCOUNT_ID = "123456789012"; - public static final String REST_API_ID = "1234abc"; - public static final String STAGE = "$deafult"; - public static final String PRINCIPAL_ID = "me"; @Test public void testAllowAllStatement() throws JsonProcessingException { - IamPolicyResponse iamPolicyResponse = new IamPolicyResponse(PRINCIPAL_ID, IamPolicyResponse.PolicyDocument.getAllowAllPolicy(REGION, AWS_ACCOUNT_ID, REST_API_ID, STAGE)); + IamPolicyResponse iamPolicyResponse = IamPolicyResponse.builder() + .withPrincipalId("me") + .withPolicyDocument(IamPolicyResponse.PolicyDocument.builder() + .withVersion(VERSION_2012_10_17) + .withStatement(singletonList(allowStatement("arn:aws:execute-api:eu-west-1:123456789012:1234abc/$deafult/*/*"))) + .build()) + .build(); String json = OBJECT_MAPPER.writeValueAsString(iamPolicyResponse); - assertThatJson(json).isEqualTo(readResource("allow-all.json")); - } - - @Test - public void testAllowOneStatement() throws JsonProcessingException { - IamPolicyResponse iamPolicyResponse = new IamPolicyResponse(PRINCIPAL_ID, IamPolicyResponse.PolicyDocument.getAllowOnePolicy(REGION, AWS_ACCOUNT_ID, REST_API_ID, STAGE, IamPolicyResponse.HttpMethod.GET, "/test")); - - String json = OBJECT_MAPPER.writeValueAsString(iamPolicyResponse); - - assertThatJson(json).isEqualTo(readResource("allow-one.json")); - } - - @Test - public void testDenyAllStatement() throws JsonProcessingException { - IamPolicyResponse iamPolicyResponse = new IamPolicyResponse(PRINCIPAL_ID, IamPolicyResponse.PolicyDocument.getDenyAllPolicy(REGION, AWS_ACCOUNT_ID, REST_API_ID, STAGE)); - - String json = OBJECT_MAPPER.writeValueAsString(iamPolicyResponse); - System.out.println(json); - - assertThatJson(json).isEqualTo(readResource("deny-all.json")); - } - - @Test - public void testDenyOneStatement() throws JsonProcessingException { - IamPolicyResponse iamPolicyResponse = new IamPolicyResponse(PRINCIPAL_ID, IamPolicyResponse.PolicyDocument.getDenyOnePolicy(REGION, AWS_ACCOUNT_ID, REST_API_ID, STAGE, IamPolicyResponse.HttpMethod.GET, "/test")); - - String json = OBJECT_MAPPER.writeValueAsString(iamPolicyResponse); - System.out.println(json); - - assertThatJson(json).isEqualTo(readResource("deny-one.json")); + assertThatJson(json).isEqualTo(readResource("iamPolicyResponses/allow-all.json")); } private String readResource(String name) { diff --git a/aws-lambda-java-events/src/test/resources/allow-all.json b/aws-lambda-java-events/src/test/resources/iamPolicyResponses/allow-all.json similarity index 64% rename from aws-lambda-java-events/src/test/resources/allow-all.json rename to aws-lambda-java-events/src/test/resources/iamPolicyResponses/allow-all.json index bc0681ff..1945bbda 100644 --- a/aws-lambda-java-events/src/test/resources/allow-all.json +++ b/aws-lambda-java-events/src/test/resources/iamPolicyResponses/allow-all.json @@ -3,15 +3,10 @@ "policyDocument": { "Version": "2012-10-17", "Statement": [{ - "Condition": {}, "Action": "execute-api:Invoke", "Resource": ["arn:aws:execute-api:eu-west-1:123456789012:1234abc/$deafult/*/*"], "Effect": "Allow" - }, { - "Condition": {}, - "Action": "execute-api:Invoke", - "Resource": [], - "Effect": "Deny" }] - } + }, + "context":null } \ No newline at end of file diff --git a/aws-lambda-java-events/src/test/resources/allow-one.json b/aws-lambda-java-events/src/test/resources/iamPolicyResponses/allow-one.json similarity index 100% rename from aws-lambda-java-events/src/test/resources/allow-one.json rename to aws-lambda-java-events/src/test/resources/iamPolicyResponses/allow-one.json diff --git a/aws-lambda-java-events/src/test/resources/deny-all.json b/aws-lambda-java-events/src/test/resources/iamPolicyResponses/deny-all.json similarity index 100% rename from aws-lambda-java-events/src/test/resources/deny-all.json rename to aws-lambda-java-events/src/test/resources/iamPolicyResponses/deny-all.json diff --git a/aws-lambda-java-events/src/test/resources/deny-one.json b/aws-lambda-java-events/src/test/resources/iamPolicyResponses/deny-one.json similarity index 100% rename from aws-lambda-java-events/src/test/resources/deny-one.json rename to aws-lambda-java-events/src/test/resources/iamPolicyResponses/deny-one.json From f227956b79462070ffdc91f498c6c108ec4a3d52 Mon Sep 17 00:00:00 2001 From: msailes Date: Mon, 11 Jan 2021 09:55:59 +0000 Subject: [PATCH 3/4] added tests for deny statement --- .../runtime/events/IamPolicyResponse.java | 3 +-- .../runtime/events/IamPolicyResponseTest.java | 20 +++++++++++++++++-- .../iamPolicyResponses/allow-one.json | 17 ---------------- .../{allow-all.json => allow.json} | 0 .../iamPolicyResponses/deny-one.json | 17 ---------------- .../{deny-all.json => deny.json} | 9 ++------- 6 files changed, 21 insertions(+), 45 deletions(-) delete mode 100644 aws-lambda-java-events/src/test/resources/iamPolicyResponses/allow-one.json rename aws-lambda-java-events/src/test/resources/iamPolicyResponses/{allow-all.json => allow.json} (100%) delete mode 100644 aws-lambda-java-events/src/test/resources/iamPolicyResponses/deny-one.json rename aws-lambda-java-events/src/test/resources/iamPolicyResponses/{deny-all.json => deny.json} (63%) diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/IamPolicyResponse.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/IamPolicyResponse.java index d0823031..7d527602 100644 --- a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/IamPolicyResponse.java +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/IamPolicyResponse.java @@ -37,8 +37,7 @@ public Map getPolicyDocument() { Map serializableStatement = new HashMap<>(); serializableStatement.put("Effect", statement.getEffect()); serializableStatement.put("Action", statement.getAction()); - serializableStatement.put("Resource", statement.getResource().toArray(new String[statement.getResource().size()])); -// serializableStatement.put(CONDITION, statement.getCondition()); + serializableStatement.put("Resource", statement.getResource().toArray(new String[0])); serializableStatementArray[i] = serializableStatement; } serializablePolicy.put("Statement", serializableStatementArray); diff --git a/aws-lambda-java-events/src/test/java/com/amazonaws/services/lambda/runtime/events/IamPolicyResponseTest.java b/aws-lambda-java-events/src/test/java/com/amazonaws/services/lambda/runtime/events/IamPolicyResponseTest.java index b214aae1..cc014071 100644 --- a/aws-lambda-java-events/src/test/java/com/amazonaws/services/lambda/runtime/events/IamPolicyResponseTest.java +++ b/aws-lambda-java-events/src/test/java/com/amazonaws/services/lambda/runtime/events/IamPolicyResponseTest.java @@ -12,6 +12,7 @@ import static com.amazonaws.services.lambda.runtime.events.IamPolicyResponse.VERSION_2012_10_17; import static com.amazonaws.services.lambda.runtime.events.IamPolicyResponse.allowStatement; +import static com.amazonaws.services.lambda.runtime.events.IamPolicyResponse.denyStatement; import static java.util.Collections.singletonList; import static net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson; @@ -20,7 +21,7 @@ public class IamPolicyResponseTest { private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); @Test - public void testAllowAllStatement() throws JsonProcessingException { + public void testAllowStatement() throws JsonProcessingException { IamPolicyResponse iamPolicyResponse = IamPolicyResponse.builder() .withPrincipalId("me") .withPolicyDocument(IamPolicyResponse.PolicyDocument.builder() @@ -31,7 +32,22 @@ public void testAllowAllStatement() throws JsonProcessingException { String json = OBJECT_MAPPER.writeValueAsString(iamPolicyResponse); - assertThatJson(json).isEqualTo(readResource("iamPolicyResponses/allow-all.json")); + assertThatJson(json).isEqualTo(readResource("iamPolicyResponses/allow.json")); + } + + @Test + public void testDenyStatement() throws JsonProcessingException { + IamPolicyResponse iamPolicyResponse = IamPolicyResponse.builder() + .withPrincipalId("me") + .withPolicyDocument(IamPolicyResponse.PolicyDocument.builder() + .withVersion(VERSION_2012_10_17) + .withStatement(singletonList(denyStatement("arn:aws:execute-api:eu-west-1:123456789012:1234abc/$deafult/*/*"))) + .build()) + .build(); + + String json = OBJECT_MAPPER.writeValueAsString(iamPolicyResponse); + + assertThatJson(json).isEqualTo(readResource("iamPolicyResponses/deny.json")); } private String readResource(String name) { diff --git a/aws-lambda-java-events/src/test/resources/iamPolicyResponses/allow-one.json b/aws-lambda-java-events/src/test/resources/iamPolicyResponses/allow-one.json deleted file mode 100644 index 6dca0558..00000000 --- a/aws-lambda-java-events/src/test/resources/iamPolicyResponses/allow-one.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "principalId": "me", - "policyDocument": { - "Version": "2012-10-17", - "Statement": [{ - "Condition": {}, - "Action": "execute-api:Invoke", - "Resource": ["arn:aws:execute-api:eu-west-1:123456789012:1234abc/$deafult/GET/test"], - "Effect": "Allow" - }, { - "Condition": {}, - "Action": "execute-api:Invoke", - "Resource": [], - "Effect": "Deny" - }] - } -} \ No newline at end of file diff --git a/aws-lambda-java-events/src/test/resources/iamPolicyResponses/allow-all.json b/aws-lambda-java-events/src/test/resources/iamPolicyResponses/allow.json similarity index 100% rename from aws-lambda-java-events/src/test/resources/iamPolicyResponses/allow-all.json rename to aws-lambda-java-events/src/test/resources/iamPolicyResponses/allow.json diff --git a/aws-lambda-java-events/src/test/resources/iamPolicyResponses/deny-one.json b/aws-lambda-java-events/src/test/resources/iamPolicyResponses/deny-one.json deleted file mode 100644 index 581f8c3d..00000000 --- a/aws-lambda-java-events/src/test/resources/iamPolicyResponses/deny-one.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "principalId": "me", - "policyDocument": { - "Version": "2012-10-17", - "Statement": [{ - "Condition": {}, - "Action": "execute-api:Invoke", - "Resource": [], - "Effect": "Allow" - }, { - "Condition": {}, - "Action": "execute-api:Invoke", - "Resource": ["arn:aws:execute-api:eu-west-1:123456789012:1234abc/$deafult/GET/test"], - "Effect": "Deny" - }] - } -} \ No newline at end of file diff --git a/aws-lambda-java-events/src/test/resources/iamPolicyResponses/deny-all.json b/aws-lambda-java-events/src/test/resources/iamPolicyResponses/deny.json similarity index 63% rename from aws-lambda-java-events/src/test/resources/iamPolicyResponses/deny-all.json rename to aws-lambda-java-events/src/test/resources/iamPolicyResponses/deny.json index 9db8813c..bfaaad1f 100644 --- a/aws-lambda-java-events/src/test/resources/iamPolicyResponses/deny-all.json +++ b/aws-lambda-java-events/src/test/resources/iamPolicyResponses/deny.json @@ -3,15 +3,10 @@ "policyDocument": { "Version": "2012-10-17", "Statement": [{ - "Condition": {}, - "Action": "execute-api:Invoke", - "Resource": [], - "Effect": "Allow" - }, { - "Condition": {}, "Action": "execute-api:Invoke", "Resource": ["arn:aws:execute-api:eu-west-1:123456789012:1234abc/$deafult/*/*"], "Effect": "Deny" }] - } + }, + "context":null } \ No newline at end of file From 983e46a2eeb9f27aa43b47b4f10b0fc88ef86bc5 Mon Sep 17 00:00:00 2001 From: msailes Date: Mon, 11 Jan 2021 14:24:25 +0000 Subject: [PATCH 4/4] added support for IAM conditions --- .../runtime/events/IamPolicyResponse.java | 2 ++ .../runtime/events/IamPolicyResponseTest.java | 28 +++++++++++++++++++ .../allow-with-condition.json | 13 +++++++++ .../resources/iamPolicyResponses/allow.json | 3 +- .../resources/iamPolicyResponses/deny.json | 3 +- 5 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 aws-lambda-java-events/src/test/resources/iamPolicyResponses/allow-with-condition.json diff --git a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/IamPolicyResponse.java b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/IamPolicyResponse.java index 7d527602..a511836c 100644 --- a/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/IamPolicyResponse.java +++ b/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/IamPolicyResponse.java @@ -38,6 +38,7 @@ public Map getPolicyDocument() { serializableStatement.put("Effect", statement.getEffect()); serializableStatement.put("Action", statement.getAction()); serializableStatement.put("Resource", statement.getResource().toArray(new String[0])); + serializableStatement.put("Condition", statement.getCondition()); serializableStatementArray[i] = serializableStatement; } serializablePolicy.put("Statement", serializableStatementArray); @@ -79,5 +80,6 @@ public static class Statement implements Serializable, Cloneable { private String action; private String effect; private List resource; + private Map> condition; } } \ No newline at end of file diff --git a/aws-lambda-java-events/src/test/java/com/amazonaws/services/lambda/runtime/events/IamPolicyResponseTest.java b/aws-lambda-java-events/src/test/java/com/amazonaws/services/lambda/runtime/events/IamPolicyResponseTest.java index cc014071..4dbbb108 100644 --- a/aws-lambda-java-events/src/test/java/com/amazonaws/services/lambda/runtime/events/IamPolicyResponseTest.java +++ b/aws-lambda-java-events/src/test/java/com/amazonaws/services/lambda/runtime/events/IamPolicyResponseTest.java @@ -9,11 +9,16 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.HashMap; +import java.util.Map; +import static com.amazonaws.services.lambda.runtime.events.IamPolicyResponse.ALLOW; +import static com.amazonaws.services.lambda.runtime.events.IamPolicyResponse.EXECUTE_API_INVOKE; import static com.amazonaws.services.lambda.runtime.events.IamPolicyResponse.VERSION_2012_10_17; import static com.amazonaws.services.lambda.runtime.events.IamPolicyResponse.allowStatement; import static com.amazonaws.services.lambda.runtime.events.IamPolicyResponse.denyStatement; import static java.util.Collections.singletonList; +import static java.util.Collections.singletonMap; import static net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson; public class IamPolicyResponseTest { @@ -50,6 +55,29 @@ public void testDenyStatement() throws JsonProcessingException { assertThatJson(json).isEqualTo(readResource("iamPolicyResponses/deny.json")); } + @Test + public void testStatementWithCondition() throws JsonProcessingException { + Map> conditions = new HashMap<>(); + conditions.put("DateGreaterThan", singletonMap("aws:TokenIssueTime", "2020-01-01T00:00:01Z")); + + IamPolicyResponse iamPolicyResponse = IamPolicyResponse.builder() + .withPrincipalId("me") + .withPolicyDocument(IamPolicyResponse.PolicyDocument.builder() + .withVersion(VERSION_2012_10_17) + .withStatement(singletonList(IamPolicyResponse.Statement.builder() + .withAction(EXECUTE_API_INVOKE) + .withEffect(ALLOW) + .withResource(singletonList("arn:aws:execute-api:eu-west-1:123456789012:1234abc/$deafult/*/*")) + .withCondition(conditions) + .build())) + .build()) + .build(); + + String json = OBJECT_MAPPER.writeValueAsString(iamPolicyResponse); + + assertThatJson(json).isEqualTo(readResource("iamPolicyResponses/allow-with-condition.json")); + } + private String readResource(String name) { Path filePath = Paths.get("src", "test", "resources", name); byte[] bytes = new byte[0]; diff --git a/aws-lambda-java-events/src/test/resources/iamPolicyResponses/allow-with-condition.json b/aws-lambda-java-events/src/test/resources/iamPolicyResponses/allow-with-condition.json new file mode 100644 index 00000000..0541e410 --- /dev/null +++ b/aws-lambda-java-events/src/test/resources/iamPolicyResponses/allow-with-condition.json @@ -0,0 +1,13 @@ +{ + "principalId": "me", + "policyDocument": { + "Version": "2012-10-17", + "Statement": [{ + "Action": "execute-api:Invoke", + "Resource": ["arn:aws:execute-api:eu-west-1:123456789012:1234abc/$deafult/*/*"], + "Effect": "Allow", + "Condition": {"DateGreaterThan": {"aws:TokenIssueTime": "2020-01-01T00:00:01Z"}} + }] + }, + "context":null +} \ No newline at end of file diff --git a/aws-lambda-java-events/src/test/resources/iamPolicyResponses/allow.json b/aws-lambda-java-events/src/test/resources/iamPolicyResponses/allow.json index 1945bbda..7636502b 100644 --- a/aws-lambda-java-events/src/test/resources/iamPolicyResponses/allow.json +++ b/aws-lambda-java-events/src/test/resources/iamPolicyResponses/allow.json @@ -5,7 +5,8 @@ "Statement": [{ "Action": "execute-api:Invoke", "Resource": ["arn:aws:execute-api:eu-west-1:123456789012:1234abc/$deafult/*/*"], - "Effect": "Allow" + "Effect": "Allow", + "Condition": null }] }, "context":null diff --git a/aws-lambda-java-events/src/test/resources/iamPolicyResponses/deny.json b/aws-lambda-java-events/src/test/resources/iamPolicyResponses/deny.json index bfaaad1f..c5e360d3 100644 --- a/aws-lambda-java-events/src/test/resources/iamPolicyResponses/deny.json +++ b/aws-lambda-java-events/src/test/resources/iamPolicyResponses/deny.json @@ -5,7 +5,8 @@ "Statement": [{ "Action": "execute-api:Invoke", "Resource": ["arn:aws:execute-api:eu-west-1:123456789012:1234abc/$deafult/*/*"], - "Effect": "Deny" + "Effect": "Deny", + "Condition": null }] }, "context":null