Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
ba7a33c
Changed ContainerRequest creation to use the method for the headers.…
sapessi Oct 31, 2018
53ffdf9
Fixes issue where headers were treated as case sensitive after deseri…
eirikjak Dec 16, 2018
0fdd8cf
Fix get multivalue query parameter
superweijiafeng Dec 18, 2018
e182e73
Removing unused unnecessary imports
sergioescala Dec 18, 2018
d745453
Fixing typos
sergioescala Dec 18, 2018
123e3b4
Bump in slf4j version and temporary exclusion to fix build
sapessi Dec 20, 2018
e8754bf
Fixed issue with multipart uploads
sapessi Dec 20, 2018
9bf5e7a
Removed unused imports
sapessi Dec 20, 2018
591e359
Move unused imports
sapessi Dec 20, 2018
00787d4
Merge branch 'superweijiafeng-patch-1' into core
sapessi Dec 20, 2018
2be72a5
Added tests for issue #217
sapessi Dec 20, 2018
3d8b655
Added proxiable property to ServletRequest, Context, and Response sup…
sapessi Dec 20, 2018
d3cc501
Experimental ALB support to address issue #214
sapessi Dec 20, 2018
daf286b
Updated samples to reflect the changes in the ALB support issue (#214)
sapessi Dec 20, 2018
3b40604
Added SpringBoot 2 sample to address issue #181
sapessi Dec 20, 2018
59cae60
Addded SpringBoot 2 archetype to close #181
sapessi Dec 20, 2018
b37433a
Added Gradle build to samples as requested in #212
sapessi Dec 21, 2018
22edc6e
Switched samples to maven assembly plugin. Beginning to address #133
sapessi Dec 21, 2018
7aa9b06
Updated archetypes to use assembly plugin and added a gradle build fi…
sapessi Dec 21, 2018
82fddf2
New build process that should test all samples and archetypes includi…
sapessi Dec 21, 2018
bf8f032
Fixed build warning by removing references to the file system root /
sapessi Dec 22, 2018
9d4da29
Build script update to fail on errors from maven or gradle. Switched …
sapessi Dec 22, 2018
452d07a
Added basic security context ALB tests for #214
sapessi Dec 22, 2018
516fd51
Added comments as suggested in #167
sapessi Dec 22, 2018
4f1e70d
Merging changes from PR #216
sapessi Dec 22, 2018
2a21df4
Merge branch 'removing-unused-unnecessary-imports' PR #219 into core
sapessi Dec 22, 2018
a2dab34
Merge branch 'fixing-typos' of PR #220 into core
sapessi Dec 22, 2018
27b3907
Fixed conflicts with PR merges
sapessi Dec 22, 2018
8d49f64
Removed commented-out code from the path validator
sapessi Dec 22, 2018
6dba79b
Trying to manually install gradle 5 in build environment
sapessi Dec 22, 2018
f710f31
Switched to wget and final url for gradle 5
sapessi Dec 22, 2018
2c52bd0
Fixed type in assembly output file name
sapessi Dec 22, 2018
9ab50f7
Additional changes and unit tests for ALB support (#214). Turns out t…
sapessi Dec 26, 2018
3961897
Fix build
sapessi Dec 26, 2018
5f3e2af
More details on the slf4j vulnerability suppression
sapessi Dec 26, 2018
38871ca
Bump version of dependency check plugin
sapessi Dec 26, 2018
8af1e48
Fixed suppression for latest version of dep check plugin
sapessi Dec 26, 2018
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
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ release.properties
dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties
.gradle/
gradle/
build/
gradlew*

# Exclude maven wrapper
!/.mvn/wrapper/maven-wrapper.jar
14 changes: 12 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
language: java
dist: trusty
jdk:
- oraclejdk8
script: mvn install
- openjdk8
addons:
apt:
update: true
before_install:
- wget https://services.gradle.org/distributions/gradle-5.0-bin.zip
- mkdir /opt/gradle
- unzip -d /opt/gradle gradle-5.0-bin.zip
- export GRADLE=/opt/gradle/gradle-5.0/bin/gradle
install: true
script: ./travis.sh
18 changes: 16 additions & 2 deletions aws-serverless-java-container-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,23 @@
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.5.3</version>
<version>4.5.6</version>
<scope>compile</scope>
</dependency>

<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.6</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
<version>4.4.10</version>
<scope>compile</scope>
</dependency>
</dependencies>

<build>
Expand Down Expand Up @@ -162,7 +176,7 @@
<plugin>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-maven</artifactId>
<version>3.3.2</version>
<version>${dependencyCheck.version}</version>
<configuration>
<skipProvidedScope>true</skipProvidedScope>
<suppressionFiles>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,9 @@
import com.amazonaws.serverless.proxy.internal.LambdaContainerHandler;
import com.amazonaws.serverless.proxy.model.AwsProxyResponse;
import com.amazonaws.serverless.proxy.model.ErrorModel;
import com.amazonaws.serverless.proxy.model.MultiValuedTreeMap;
import com.amazonaws.serverless.proxy.model.Headers;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonValueFormat;
import com.fasterxml.jackson.databind.ser.std.JsonValueSerializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -30,8 +27,6 @@

import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;

/**
* Default implementation of the <code>ExceptionHandler</code> object that returns AwsProxyResponse objects.
Expand All @@ -58,7 +53,7 @@ public class AwsProxyExceptionHandler
// Variables - Private - Static
//-------------------------------------------------------------

private static MultiValuedTreeMap<String, String> headers = new MultiValuedTreeMap<>(String.CASE_INSENSITIVE_ORDER);
private static Headers headers = new Headers();

//-------------------------------------------------------------
// Constructors
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
import javax.ws.rs.core.SecurityContext;

/**
* Default impolementation of <code>SecurityContextWriter</code>. Creates a SecurityContext object based on an API Gateway
* Default implementation of <code>SecurityContextWriter</code>. Creates a SecurityContext object based on an API Gateway
* event and the Lambda context. This returns the default <code>AwsProxySecurityContext</code> instance.
*/
public class AwsProxySecurityContextWriter implements SecurityContextWriter<AwsProxyRequest> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
* handled by the client applications directly within the container and a valid HTTP response is expected. This handler
* is used for exceptions thrown by the library while marshalling and unmarshalling requests and responses.
*
* The interface delcares two methods. A typed <code>handle</code> method for requests that are being proxied using a
* The interface declares two methods. A typed <code>handle</code> method for requests that are being proxied using a
* request and response type <code>LambdaContainerHandler</code>, and a stream-based
* <code>handle</code> method for <a href="http://docs.aws.amazon.com/lambda/latest/dg/java-handler-io-type-stream.html" target="_blank">
* Lambda's <code>RequestStreamHandler</code></a>.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
* object that supports requests for the AWS_PROXY integration.
*
* @param <RequestType> The type for the AWS Lambda event
* @param <ContainerRequestType> The type for the undelying container request object
* @param <ContainerRequestType> The type for the underlying container request object
*/
public abstract class RequestReader<RequestType, ContainerRequestType> {

Expand All @@ -45,6 +45,11 @@ public abstract class RequestReader<RequestType, ContainerRequestType> {
*/
public static final String API_GATEWAY_STAGE_VARS_PROPERTY = "com.amazonaws.apigateway.stage.variables";

/**
* The key for the <strong>ALB context</strong> property in the PropertiesDelegate object
*/
public static final String ALB_CONTEXT_PROPERTY = "com.amazonaws.alb.request.context";

/**
* The key to store the entire API Gateway event
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
* or a <code>ResponseReader</code> implementation. For example, the Jersey library passes the response reader object to
* the default implementation of this class.
*
* @param <ContainerResponseType> The response object expceted from the underlying container
* @param <ContainerResponseType> The response object expected from the underlying container
* @param <ResponseType> The type for the Lambda function return value
*/
public abstract class ResponseWriter<ContainerResponseType, ResponseType> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,23 @@
*/
package com.amazonaws.serverless.proxy.internal.jaxrs;

import com.amazonaws.serverless.proxy.internal.LambdaContainerHandler;
import com.amazonaws.serverless.proxy.model.AwsProxyRequest;
import com.amazonaws.serverless.proxy.model.CognitoAuthorizerClaims;
import com.amazonaws.services.lambda.runtime.Context;

import com.fasterxml.jackson.core.type.TypeReference;

import javax.ws.rs.core.SecurityContext;

import java.io.IOException;
import java.security.Principal;
import java.util.Base64;
import java.util.Map;

import static com.amazonaws.serverless.proxy.model.AwsProxyRequest.*;
import static com.amazonaws.serverless.proxy.model.AwsProxyRequest.RequestSource.API_GATEWAY;


/**
* default implementation of the <code>SecurityContext</code> object. This class supports 3 API Gateway's authorization methods:
Expand All @@ -31,12 +42,15 @@ public class AwsProxySecurityContext
implements SecurityContext {

//-------------------------------------------------------------
// Constants - Private
// Constants - Package
//-------------------------------------------------------------

private static final String AUTH_SCHEME_CUSTOM = "CUSTOM_AUTHORIZER";
private static final String AUTH_SCHEME_COGNITO_POOL = "COGNITO_USER_POOL";
private static final String AUTH_SCHEME_AWS_IAM = "AWS_IAM";
static final String AUTH_SCHEME_CUSTOM = "CUSTOM_AUTHORIZER";
static final String AUTH_SCHEME_COGNITO_POOL = "COGNITO_USER_POOL";
static final String AUTH_SCHEME_AWS_IAM = "AWS_IAM";

static final String ALB_ACESS_TOKEN_HEADER = "x-amzn-oidc-accesstoken";
static final String ALB_IDENTITY_HEADER = "x-amzn-oidc-identity";


//-------------------------------------------------------------
Expand Down Expand Up @@ -78,7 +92,12 @@ public Principal getUserPrincipal() {
if (getAuthenticationScheme().equals(AUTH_SCHEME_CUSTOM) || getAuthenticationScheme().equals(AUTH_SCHEME_AWS_IAM)) {
return () -> {
if (getAuthenticationScheme().equals(AUTH_SCHEME_CUSTOM)) {
return event.getRequestContext().getAuthorizer().getPrincipalId();
switch (event.getRequestSource()) {
case API_GATEWAY:
return event.getRequestContext().getAuthorizer().getPrincipalId();
case ALB:
return event.getMultiValueHeaders().getFirst(ALB_IDENTITY_HEADER);
}
} else if (getAuthenticationScheme().equals(AUTH_SCHEME_AWS_IAM)) {
// if we received credentials from Cognito Federated Identities then we return the identity id
if (event.getRequestContext().getIdentity().getCognitoIdentityId() != null) {
Expand Down Expand Up @@ -112,15 +131,24 @@ public boolean isSecure() {


public String getAuthenticationScheme() {
if (event.getRequestContext().getAuthorizer() != null && event.getRequestContext().getAuthorizer().getClaims() != null && event.getRequestContext().getAuthorizer().getClaims().getSubject() != null) {
return AUTH_SCHEME_COGNITO_POOL;
} else if (event.getRequestContext().getAuthorizer() != null) {
return AUTH_SCHEME_CUSTOM;
} else if (event.getRequestContext().getIdentity().getAccessKey() != null) {
return AUTH_SCHEME_AWS_IAM;
} else {
return null;
switch (event.getRequestSource()) {
case API_GATEWAY:
if (event.getRequestContext().getAuthorizer() != null && event.getRequestContext().getAuthorizer().getClaims() != null
&& event.getRequestContext().getAuthorizer().getClaims().getSubject() != null) {
return AUTH_SCHEME_COGNITO_POOL;
} else if (event.getRequestContext().getAuthorizer() != null) {
return AUTH_SCHEME_CUSTOM;
} else if (event.getRequestContext().getIdentity().getAccessKey() != null) {
return AUTH_SCHEME_AWS_IAM;
} else {
return null;
}
case ALB:
if (event.getMultiValueHeaders().containsKey(ALB_ACESS_TOKEN_HEADER)) {
return AUTH_SCHEME_CUSTOM;
}
}
return null;
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@


import com.amazonaws.serverless.proxy.LogFormatter;
import com.amazonaws.serverless.proxy.model.ApiGatewayRequestContext;
import com.amazonaws.serverless.proxy.model.AwsProxyRequest;
import com.amazonaws.serverless.proxy.model.AwsProxyRequestContext;

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;

Expand All @@ -19,6 +20,7 @@
import java.util.Locale;

import static com.amazonaws.serverless.proxy.RequestReader.API_GATEWAY_CONTEXT_PROPERTY;
import static com.amazonaws.serverless.proxy.RequestReader.API_GATEWAY_EVENT_PROPERTY;
import static java.time.temporal.ChronoField.DAY_OF_MONTH;
import static java.time.temporal.ChronoField.HOUR_OF_DAY;
import static java.time.temporal.ChronoField.MINUTE_OF_HOUR;
Expand Down Expand Up @@ -64,14 +66,15 @@ public ApacheCombinedServletLogFormatter() {
public String format(ContainerRequestType servletRequest, ContainerResponseType servletResponse, SecurityContext ctx) {
//LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"" combined
StringBuilder logLineBuilder = new StringBuilder();
ApiGatewayRequestContext gatewayContext = (ApiGatewayRequestContext)servletRequest.getAttribute(API_GATEWAY_CONTEXT_PROPERTY);
AwsProxyRequest req = (AwsProxyRequest)servletRequest.getAttribute(API_GATEWAY_EVENT_PROPERTY);
AwsProxyRequestContext gatewayContext = req.getRequestContext();

// %h
logLineBuilder.append(servletRequest.getRemoteAddr());
logLineBuilder.append(" ");

// %l
if (gatewayContext != null) {
if (gatewayContext != null && req.getRequestSource() == AwsProxyRequest.RequestSource.API_GATEWAY) {
if (gatewayContext.getIdentity().getUserArn() != null) {
logLineBuilder.append(gatewayContext.getIdentity().getUserArn());
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,11 @@

import com.amazonaws.serverless.proxy.RequestReader;
import com.amazonaws.serverless.proxy.internal.SecurityUtils;
import com.amazonaws.serverless.proxy.model.ApiGatewayRequestContext;
import com.amazonaws.serverless.proxy.model.AwsProxyRequestContext;
import com.amazonaws.serverless.proxy.model.ContainerConfig;
import com.amazonaws.serverless.proxy.model.MultiValuedTreeMap;
import com.amazonaws.services.lambda.runtime.Context;

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -34,16 +33,13 @@
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.format.DateTimeFormatter;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
Expand Down Expand Up @@ -92,7 +88,7 @@ public abstract class AwsHttpServletRequest implements HttpServletRequest {
//-------------------------------------------------------------

/**
* Protected constructors for implemnenting classes. This should be called first with the context received from
* Protected constructors for implementing classes. This should be called first with the context received from
* AWS Lambda
* @param lambdaContext The Lambda function context. This object is used for utility methods such as log
*/
Expand All @@ -116,7 +112,7 @@ public String getRequestedSessionId() {
public HttpSession getSession(boolean b) {
log.debug("Trying to access session. Lambda functions are stateless and should not rely on the session");
if (b && null == this.session) {
ApiGatewayRequestContext requestContext = (ApiGatewayRequestContext) getAttribute(RequestReader.API_GATEWAY_CONTEXT_PROPERTY);
AwsProxyRequestContext requestContext = (AwsProxyRequestContext) getAttribute(RequestReader.API_GATEWAY_CONTEXT_PROPERTY);
this.session = new AwsHttpSession(requestContext.getRequestId());
}
return this.session;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
package com.amazonaws.serverless.proxy.internal.servlet;

import com.amazonaws.serverless.proxy.internal.SecurityUtils;
import com.amazonaws.serverless.proxy.model.MultiValuedTreeMap;
import com.amazonaws.serverless.proxy.model.AwsProxyRequest;
import com.amazonaws.serverless.proxy.model.Headers;

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import org.slf4j.Logger;
Expand All @@ -33,6 +34,9 @@
import java.util.*;
import java.util.concurrent.CountDownLatch;

import static com.amazonaws.serverless.proxy.RequestReader.API_GATEWAY_EVENT_PROPERTY;


/**
* Basic implementation of the <code>HttpServletResponse</code> object. This is used by the <code>AwsProxyHttpServletResponseWriter</code>
* to generate an <code>AwsProxyResponse</code> object. We have an additional <code>getAwsResponseHeaders()</code> method
Expand All @@ -52,7 +56,7 @@ public class AwsHttpServletResponse
// Variables - Private
//-------------------------------------------------------------

private MultiValuedTreeMap<String, String> headers = new MultiValuedTreeMap<>(String.CASE_INSENSITIVE_ORDER);
private Headers headers = new Headers();
private int statusCode;
private String statusMessage;
private String responseBody;
Expand Down Expand Up @@ -404,7 +408,7 @@ public boolean isCommitted() {

@Override
public void reset() {
headers = new MultiValuedTreeMap<>();
headers = new Headers();
responseBody = null;
writer = null;
bodyOutputStream = new ByteArrayOutputStream();
Expand Down Expand Up @@ -439,10 +443,14 @@ byte[] getAwsResponseBodyBytes() {
}


MultiValuedTreeMap<String, String> getAwsResponseHeaders() {
Headers getAwsResponseHeaders() {
return headers;
}

AwsProxyRequest getAwsProxyRequest() {
return (AwsProxyRequest)request.getAttribute(API_GATEWAY_EVENT_PROPERTY);
}


//-------------------------------------------------------------
// Methods - Private
Expand Down
Loading