Skip to content

Commit

Permalink
Merge pull request #815 from jonife/iam
Browse files Browse the repository at this point in the history
Add support for IAM Authorizers in combination with 2.0 payload
  • Loading branch information
deki authored Mar 27, 2024
2 parents 79b6d34 + bae6801 commit 8d18990
Show file tree
Hide file tree
Showing 3 changed files with 176 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,21 @@
public class HttpApiV2AuthorizerMap extends HashMap<String, Object> {
private static final String JWT_KEY = "jwt";
private static final String LAMBDA_KEY = "lambda";
private static final String IAM_KEY = "iam";
private static final long serialVersionUID = 42L;

public HttpApiV2JwtAuthorizer getJwtAuthorizer() {
return (HttpApiV2JwtAuthorizer)get(JWT_KEY);
return (HttpApiV2JwtAuthorizer) get(JWT_KEY);
}

public Map<String, Object> getLambdaAuthorizerContext() {
return (Map<String, Object>) get(LAMBDA_KEY);
}

public HttpApiV2IamAuthorizer getIamAuthorizer() {
return (HttpApiV2IamAuthorizer) get(IAM_KEY);
}

public boolean isJwt() {
return containsKey(JWT_KEY);
}
Expand All @@ -52,10 +57,18 @@ public boolean isLambda() {
return containsKey(LAMBDA_KEY);
}

public boolean isIam() {
return containsKey(IAM_KEY);
}

public void putJwtAuthorizer(HttpApiV2JwtAuthorizer jwt) {
put(JWT_KEY, jwt);
}

public void putIamAuthorizer(HttpApiV2IamAuthorizer iam) {
put(IAM_KEY, iam);
}

public static class HttpApiV2AuthorizerDeserializer extends StdDeserializer<HttpApiV2AuthorizerMap> {
private static final long serialVersionUID = 42L;

Expand All @@ -64,18 +77,25 @@ public HttpApiV2AuthorizerDeserializer() {
}

@Override
public HttpApiV2AuthorizerMap deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
public HttpApiV2AuthorizerMap deserialize(JsonParser jsonParser, DeserializationContext deserializationContext)
throws IOException, JsonProcessingException {
HttpApiV2AuthorizerMap map = new HttpApiV2AuthorizerMap();
JsonNode node = jsonParser.getCodec().readTree(jsonParser);
if (node.has(JWT_KEY)) {
HttpApiV2JwtAuthorizer authorizer = LambdaContainerHandler.getObjectMapper().treeToValue(node.get(JWT_KEY), HttpApiV2JwtAuthorizer.class);
HttpApiV2JwtAuthorizer authorizer = LambdaContainerHandler.getObjectMapper()
.treeToValue(node.get(JWT_KEY), HttpApiV2JwtAuthorizer.class);
map.putJwtAuthorizer(authorizer);
}
if (node.has(LAMBDA_KEY)) {
Map<String, Object> context = LambdaContainerHandler.getObjectMapper().treeToValue(node.get(LAMBDA_KEY),
TypeFactory.defaultInstance().constructMapType(HashMap.class, String.class, Object.class));
map.put(LAMBDA_KEY, context);
}
if (node.has(IAM_KEY)) {
HttpApiV2IamAuthorizer iam_authorizer = LambdaContainerHandler.getObjectMapper()
.treeToValue(node.get(IAM_KEY), HttpApiV2IamAuthorizer.class);
map.putIamAuthorizer(iam_authorizer);
}
// we ignore other, unknown values
return map;
}
Expand All @@ -89,14 +109,18 @@ public HttpApiV2AuthorizerSerializer() {
}

@Override
public void serialize(HttpApiV2AuthorizerMap httpApiV2AuthorizerMap, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
public void serialize(HttpApiV2AuthorizerMap httpApiV2AuthorizerMap, JsonGenerator jsonGenerator,
SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeStartObject();
if (httpApiV2AuthorizerMap.isJwt()) {
jsonGenerator.writeObjectField(JWT_KEY, httpApiV2AuthorizerMap.getJwtAuthorizer());
}
if (httpApiV2AuthorizerMap.isLambda()) {
jsonGenerator.writeObjectField(LAMBDA_KEY, httpApiV2AuthorizerMap.getLambdaAuthorizerContext());
}
if (httpApiV2AuthorizerMap.isIam()) {
jsonGenerator.writeObjectField(IAM_KEY, httpApiV2AuthorizerMap.get(IAM_KEY));
}
jsonGenerator.writeEndObject();
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package com.amazonaws.serverless.proxy.model;

public class HttpApiV2IamAuthorizer {
public String accessKey;
public String accountId;
public String callerId;
public String cognitoIdentity;
public String principalOrgId;
public String userArn;
public String userId;

public String getAccessKey() {
return accessKey;
}

public String getAccountId() {
return accountId;
}

public String getCallerId() {
return callerId;
}

public String getCognitoIdentity() {
return cognitoIdentity;
}

public String getPrincipalOrgId() {
return principalOrgId;
}

public String getUserArn() {
return userArn;
}

public String getUserId() {
return userId;
}

public void setAccessKey(String accessKey) {
this.accessKey = accessKey;
}

public void setAccountId(String accountId) {
this.accountId = accountId;
}

public void setCallerId(String callerId) {
this.callerId = callerId;
}

public void setCognitoIdentity(String cognitoIdentity) {
this.cognitoIdentity = cognitoIdentity;
}

public void setPrincipalOrgId(String principalOrgId) {
this.principalOrgId = principalOrgId;
}

public void setUserArn(String userArn) {
this.userArn = userArn;
}

public void setUserId(String userId) {
this.userId = userId;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -129,11 +129,55 @@ public class HttpApiV2ProxyRequestTest {
" \"isBase64Encoded\": false,\n" +
" \"stageVariables\": {\"stageVariable1\": \"value1\", \"stageVariable2\": \"value2\"}\n" +
" }\n";
private static final String IAM_AUTHORIZER = "{\n" +
" \"version\": \"2.0\",\n" +
" \"routeKey\": \"$default\",\n" +
" \"rawPath\": \"/my/path\",\n" +
" \"rawQueryString\": \"parameter1=value1&parameter1=value2&parameter2=value\",\n" +
" \"cookies\": [ \"cookie1\", \"cookie2\" ],\n" +
" \"headers\": {\n" +
" \"Header1\": \"value1\",\n" +
" \"Header2\": \"value2\"\n" +
" },\n" +
" \"queryStringParameters\": { \"parameter1\": \"value1,value2\", \"parameter2\": \"value\" },\n" +
" \"requestContext\": {\n" +
" \"accountId\": \"123456789012\",\n" +
" \"apiId\": \"api-id\",\n" +
" \"authorizer\": { \"iam\": {\n" +
" \"accessKey\": \"AKIAIOSFODNN7EXAMPLE\",\n" +
" \"accountId\": \"123456789012\",\n" +
" \"callerId\": \"AIDACKCEVSQ6C2EXAMPLE\",\n" +
" \"cognitoIdentity\": null,\n" +
" \"principalOrgId\": \"AIDACKCEVSQORGEXAMPLE\",\n" +
" \"userArn\": \"arn:aws:iam::111122223333:user/example-user\",\n" +
" \"userId\": \"AIDACOSFODNN7EXAMPLE2\"\n" +
" }" +
" },\n" +
" \"domainName\": \"id.execute-api.us-east-1.amazonaws.com\",\n" +
" \"domainPrefix\": \"id\",\n" +
" \"http\": {\n" +
" \"method\": \"POST\",\n" +
" \"path\": \"/my/path\",\n" +
" \"protocol\": \"HTTP/1.1\",\n" +
" \"sourceIp\": \"IP\",\n" +
" \"userAgent\": \"agent\"\n" +
" },\n" +
" \"requestId\": \"id\",\n" +
" \"routeKey\": \"$default\",\n" +
" \"stage\": \"$default\",\n" +
" \"time\": \"12/Mar/2020:19:03:58 +0000\",\n" +
" \"timeEpoch\": 1583348638390\n" +
" },\n" +
" \"body\": \"Hello from Lambda\",\n" +
" \"isBase64Encoded\": false,\n" +
" \"stageVariables\": {\"stageVariable1\": \"value1\", \"stageVariable2\": \"value2\"}\n" +
" }\n";

@Test
void deserialize_fromJsonString_authorizerPopulatedCorrectly() {
try {
HttpApiV2ProxyRequest req = LambdaContainerHandler.getObjectMapper().readValue(BASE_PROXY_REQUEST, HttpApiV2ProxyRequest.class);
HttpApiV2ProxyRequest req = LambdaContainerHandler.getObjectMapper().readValue(BASE_PROXY_REQUEST,
HttpApiV2ProxyRequest.class);
assertTrue(req.getRequestContext().getAuthorizer().getJwtAuthorizer().getClaims().containsKey("claim1"));
assertEquals(2, req.getRequestContext().getAuthorizer().getJwtAuthorizer().getScopes().size());
assertEquals(RequestSource.API_GATEWAY, req.getRequestSource());
Expand All @@ -146,10 +190,12 @@ void deserialize_fromJsonString_authorizerPopulatedCorrectly() {
@Test
void deserialize_fromJsonString_authorizerEmptyMap() {
try {
HttpApiV2ProxyRequest req = LambdaContainerHandler.getObjectMapper().readValue(NO_AUTH_PROXY, HttpApiV2ProxyRequest.class);
HttpApiV2ProxyRequest req = LambdaContainerHandler.getObjectMapper().readValue(NO_AUTH_PROXY,
HttpApiV2ProxyRequest.class);
assertNotNull(req.getRequestContext().getAuthorizer());
assertFalse(req.getRequestContext().getAuthorizer().isJwt());
assertFalse(req.getRequestContext().getAuthorizer().isLambda());
assertFalse(req.getRequestContext().getAuthorizer().isIam());
} catch (JsonProcessingException e) {
e.printStackTrace();
fail("Exception while parsing request" + e.getMessage());
Expand All @@ -159,7 +205,8 @@ void deserialize_fromJsonString_authorizerEmptyMap() {
@Test
void deserialize_fromJsonString_lambdaAuthorizer() {
try {
HttpApiV2ProxyRequest req = LambdaContainerHandler.getObjectMapper().readValue(LAMBDA_AUTHORIZER, HttpApiV2ProxyRequest.class);
HttpApiV2ProxyRequest req = LambdaContainerHandler.getObjectMapper().readValue(LAMBDA_AUTHORIZER,
HttpApiV2ProxyRequest.class);
assertNotNull(req.getRequestContext().getAuthorizer());
assertFalse(req.getRequestContext().getAuthorizer().isJwt());
assertTrue(req.getRequestContext().getAuthorizer().isLambda());
Expand All @@ -171,10 +218,38 @@ void deserialize_fromJsonString_lambdaAuthorizer() {
}
}

@Test
void deserialize_fromJsonString_iamAuthorizer() {
try {
HttpApiV2ProxyRequest req = LambdaContainerHandler.getObjectMapper().readValue(IAM_AUTHORIZER,
HttpApiV2ProxyRequest.class);
assertNotNull(req.getRequestContext().getAuthorizer());
assertFalse(req.getRequestContext().getAuthorizer().isJwt());
assertFalse(req.getRequestContext().getAuthorizer().isLambda());
assertTrue(req.getRequestContext().getAuthorizer().isIam());
assertEquals("AKIAIOSFODNN7EXAMPLE",
req.getRequestContext().getAuthorizer().getIamAuthorizer().getAccessKey());
assertEquals("123456789012", req.getRequestContext().getAuthorizer().getIamAuthorizer().getAccountId());
assertEquals("AIDACKCEVSQ6C2EXAMPLE",
req.getRequestContext().getAuthorizer().getIamAuthorizer().getCallerId());
assertNull(req.getRequestContext().getAuthorizer().getIamAuthorizer().getCognitoIdentity());
assertEquals("AIDACKCEVSQORGEXAMPLE",
req.getRequestContext().getAuthorizer().getIamAuthorizer().getPrincipalOrgId());
assertEquals("arn:aws:iam::111122223333:user/example-user",
req.getRequestContext().getAuthorizer().getIamAuthorizer().getUserArn());
assertEquals("AIDACOSFODNN7EXAMPLE2",
req.getRequestContext().getAuthorizer().getIamAuthorizer().getUserId());
} catch (JsonProcessingException e) {
e.printStackTrace();
fail("Exception while parsing request" + e.getMessage());
}
}

@Test
void deserialize_fromJsonString_isBase64EncodedPopulates() {
try {
HttpApiV2ProxyRequest req = LambdaContainerHandler.getObjectMapper().readValue(BASE_PROXY_REQUEST, HttpApiV2ProxyRequest.class);
HttpApiV2ProxyRequest req = LambdaContainerHandler.getObjectMapper().readValue(BASE_PROXY_REQUEST,
HttpApiV2ProxyRequest.class);
assertFalse(req.isBase64Encoded());
req = LambdaContainerHandler.getObjectMapper().readValue(NO_AUTH_PROXY, HttpApiV2ProxyRequest.class);
assertTrue(req.isBase64Encoded());
Expand Down Expand Up @@ -207,4 +282,4 @@ void serialize_toJsonString_authorizerPopulatesCorrectly() {
fail("Exception while serializing request" + e.getMessage());
}
}
}
}

0 comments on commit 8d18990

Please sign in to comment.