Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,13 @@
import com.amazonaws.services.sqs.model.SendMessageRequest;
import fish.payara.cloud.connectors.amazonsqs.api.AmazonSQSConnection;
import fish.payara.cloud.connectors.amazonsqs.api.AmazonSQSConnectionFactory;
import java.util.Date;

import javax.annotation.Resource;
import javax.ejb.Schedule;
import javax.ejb.Stateless;
import javax.resource.ConnectionFactoryDefinition;
import javax.resource.spi.TransactionSupport.TransactionSupportLevel;
import java.time.LocalTime;

/**
*
Expand All @@ -63,17 +64,23 @@
transactionSupport = TransactionSupportLevel.NoTransaction,
properties = {"awsAccessKeyId=${ENV=accessKey}",
"awsSecretKey=${ENV=secretKey}",
"region=eu-west-2"})
"awsSessionToken=${ENV=sessionToken}",
"profileName=${ENV=profileName}",
"region=${ENV=region}"})
@Stateless
public class NewTimerSessionBean {

@Resource(lookup="java:comp/env/SQSConnectionFactory")
AmazonSQSConnectionFactory factory;

@Schedule(second = "*/1", hour="*", minute="*")
@Schedule(second = "*/3", hour="*", minute="*")
public void myTimer() {
try (AmazonSQSConnection connection = factory.getConnection()) {
connection.sendMessage(new SendMessageRequest(System.getenv("queueURL"), "Hello World"));
} catch (Exception e) {}
String msg = "Hello World @ " + LocalTime.now();
System.out.println("<< Sending message: " + msg);
connection.sendMessage(new SendMessageRequest(System.getenv("queueURL"), msg));
} catch (Exception e) {
e.printStackTrace();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,23 +54,25 @@
@MessageDriven(activationConfig = {
@ActivationConfigProperty(propertyName = "awsAccessKeyId", propertyValue = "${ENV=accessKey}"),
@ActivationConfigProperty(propertyName = "awsSecretKey", propertyValue = "${ENV=secretKey}"),
@ActivationConfigProperty(propertyName = "queueURL", propertyValue = "${ENV=queueURL}"),
@ActivationConfigProperty(propertyName = "awsSessionToken", propertyValue = "${ENV=sessionToken}"),
@ActivationConfigProperty(propertyName = "profileName", propertyValue = "${ENV=profileName}"),
@ActivationConfigProperty(propertyName = "queueURL", propertyValue = "${ENV=queueURL}"),
@ActivationConfigProperty(propertyName = "pollInterval", propertyValue = "1000"),
@ActivationConfigProperty(propertyName = "region", propertyValue = "eu-west-2")
@ActivationConfigProperty(propertyName = "region", propertyValue = "${ENV=region}")
})
public class ReceiveSQSMessage implements AmazonSQSListener {

@OnSQSMessage
public void receiveMessage(Message message) {
System.out.println("Got message " + message.getBody());
System.out.println(">> Got message " + message.getBody());
Map<String,MessageAttributeValue> mattrs = message.getMessageAttributes();
for (String key : mattrs.keySet()) {
System.out.println("Got Message attribute " + key + "," + mattrs.get(key).getStringValue());
System.out.println(">> Got Message attribute " + key + "," + mattrs.get(key).getStringValue());
}

Map<String,String> attrs = message.getAttributes();
for (String key : attrs.keySet()) {
System.out.println("Got attribute " + key + "," + attrs.get(key));
System.out.println(">> Got attribute " + key + "," + attrs.get(key));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
awsSecretKey=
awsAccessKeyId=
awsSessionToken=
region=us-east-1
profileName=
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package fish.payara.cloud.connectors.amazonsqs.api;

import com.amazonaws.auth.*;
import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.util.StringUtils;

/**
* @author Martin Charlesworth
*/
public class AwsCredentialsProviderUtils {

/**
* Creates the appropriate type of {@link AWSCredentialsProvider} depending on the configuration provided.
*/
public static AWSCredentialsProvider getProvider(String accessKey,
String secretKey,
String sessionToken,
String profileName) {
AWSCredentialsProvider awsCredentialsProvider = null;
if (isValidParam(profileName)) {
// uses specified credentials profile
awsCredentialsProvider = new ProfileCredentialsProvider(profileName);

} else {
if (isValidParam(accessKey) && isValidParam(secretKey)) {
if (isValidParam(sessionToken)) {
// uses temporary session based credentials
awsCredentialsProvider = new AWSStaticCredentialsProvider(new BasicSessionCredentials(accessKey, secretKey, sessionToken));
} else {
// uses basic access key + secret key credentials
awsCredentialsProvider = new AWSStaticCredentialsProvider(new BasicAWSCredentials(accessKey, secretKey));
}
}
}
if (awsCredentialsProvider == null) {
// if neither credentials nor profile are provided, fall back on the default provider chain, which will
// eventually give us a EC2ContainerCredentialsProviderWrapper, if running in ECS.
awsCredentialsProvider = DefaultAWSCredentialsProviderChain.getInstance();
}

return awsCredentialsProvider;
}

private static boolean isValidParam(String value) {
return !StringUtils.isNullOrEmpty(value) && !value.startsWith("${ENV");
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,17 @@
*/
package fish.payara.cloud.connectors.amazonsqs.api.inbound;

import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.AWSCredentialsProvider;
import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.auth.*;
import com.amazonaws.util.StringUtils;
import fish.payara.cloud.connectors.amazonsqs.api.AmazonSQSListener;
import fish.payara.cloud.connectors.amazonsqs.api.AwsCredentialsProviderUtils;

import javax.resource.ResourceException;
import javax.resource.spi.Activation;
import javax.resource.spi.ActivationSpec;
import javax.resource.spi.InvalidPropertyException;
import javax.resource.spi.ResourceAdapter;
import java.util.logging.Logger;

/**
* Activation Specification for Amazon SQS
Expand All @@ -63,6 +63,7 @@ public class AmazonSQSActivationSpec implements ActivationSpec, AWSCredentialsPr

private String awsAccessKeyId;
private String awsSecretKey;
private String awsSessionToken;
private String queueURL;
private String region;
private Integer maxMessages = 10;
Expand All @@ -79,17 +80,8 @@ public void validate() throws InvalidPropertyException {
throw new InvalidPropertyException("region must be specified");
}

// Validate profileName if present, skip validation off other keys
if (StringUtils.isNullOrEmpty(profileName)) {

// validate keys if profileName isn't available
if (StringUtils.isNullOrEmpty(awsAccessKeyId)) {
throw new InvalidPropertyException("awsAccessKeyId must be specified");
}

if (StringUtils.isNullOrEmpty(awsSecretKey)) {
throw new InvalidPropertyException("awsSecretKey must be specified");
}
if (profileName != null && profileName.startsWith("${ENV")) {
throw new InvalidPropertyException("invalid profileName");
}

if (StringUtils.isNullOrEmpty(queueURL)) {
Expand Down Expand Up @@ -123,6 +115,14 @@ public void setAwsSecretKey(String awsSecretKey) {
this.awsSecretKey = awsSecretKey;
}

public String getAwsSessionToken() {
return awsSessionToken;
}

public void setAwsSessionToken(String awsSessionToken) {
this.awsSessionToken = awsSessionToken;
}

public String getQueueURL() {
return queueURL;
}
Expand Down Expand Up @@ -195,30 +195,19 @@ public void setProfileName(String profileName) {
this.profileName = profileName;
}

private boolean isValidProfile() {
return !StringUtils.isNullOrEmpty(profileName) && !profileName.startsWith("${ENV");
}

@Override
public AWSCredentials getCredentials() {
// Return Credentials based on what is present, profileName taking priority.
if (StringUtils.isNullOrEmpty(getProfileName())) {
return new AWSCredentials() {
@Override
public String getAWSAccessKeyId() {
return awsAccessKeyId;
}

@Override
public String getAWSSecretKey() {
return awsSecretKey;
}
};
} else {
return new ProfileCredentialsProvider(getProfileName()).getCredentials();
}
return AwsCredentialsProviderUtils.getProvider(awsAccessKeyId, awsSecretKey, awsSessionToken, profileName)
.getCredentials();
}

@Override
public void refresh() {

}


}
Original file line number Diff line number Diff line change
Expand Up @@ -39,19 +39,16 @@
*/
package fish.payara.cloud.connectors.amazonsqs.api.outbound;

import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.AWSCredentialsProvider;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.services.sqs.AmazonSQS;
import com.amazonaws.services.sqs.AmazonSQSClientBuilder;
import com.amazonaws.services.sqs.model.SendMessageBatchRequest;
import com.amazonaws.services.sqs.model.SendMessageBatchRequestEntry;
import com.amazonaws.services.sqs.model.SendMessageBatchResult;
import com.amazonaws.services.sqs.model.SendMessageRequest;
import com.amazonaws.services.sqs.model.SendMessageResult;
import com.amazonaws.util.StringUtils;
import fish.payara.cloud.connectors.amazonsqs.api.AmazonSQSConnection;
import fish.payara.cloud.connectors.amazonsqs.api.AwsCredentialsProviderUtils;

import javax.resource.NotSupportedException;
import javax.resource.ResourceException;
Expand Down Expand Up @@ -80,22 +77,12 @@ public class AmazonSQSManagedConnection implements ManagedConnection, AmazonSQSC
private final AmazonSQS sqsClient;

AmazonSQSManagedConnection(Subject subject, ConnectionRequestInfo cxRequestInfo, AmazonSQSManagedConnectionFactory aThis) {
AWSCredentialsProvider credentialsProvider;
if (StringUtils.isNullOrEmpty(aThis.getProfileName())) {
credentialsProvider = new AWSStaticCredentialsProvider(new AWSCredentials() {
@Override
public String getAWSAccessKeyId() {
return aThis.getAwsAccessKeyId();
}

@Override
public String getAWSSecretKey() {
return aThis.getAwsSecretKey();
}
});
} else {
credentialsProvider = new ProfileCredentialsProvider(aThis.getProfileName());
}

AWSCredentialsProvider credentialsProvider = AwsCredentialsProviderUtils.getProvider(
aThis.getAwsAccessKeyId(),
aThis.getAwsSecretKey(),
aThis.getAwsSessionToken(),
aThis.getProfileName());

sqsClient = AmazonSQSClientBuilder.standard().withRegion(aThis.getRegion()).withCredentials(credentialsProvider).build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ public class AmazonSQSManagedConnectionFactory implements ManagedConnectionFacto
@ConfigProperty(description = "AWS Access Key", type = String.class)
private String awsAccessKeyId;

@ConfigProperty(description = "AWS Session Token", type = String.class)
private String awsSessionToken;

@ConfigProperty(description = "Region hosting the queue", type = String.class)
private String region;

Expand All @@ -94,6 +97,14 @@ public void setAwsAccessKeyId(String awsAccessKey) {
this.awsAccessKeyId = awsAccessKey;
}

public String getAwsSessionToken() {
return awsSessionToken;
}

public void setAwsSessionToken(String awsSessionToken) {
this.awsSessionToken = awsSessionToken;
}

public String getRegion() {
return region;
}
Expand Down
38 changes: 35 additions & 3 deletions AmazonSQS/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,46 @@ To use the JCA adapter the AmazonSQSRAR-<version>.rar should be deployed to your

To deploy the JCA adapter on Payara Micro use the following commands.

The example uses a number of environment variables for connecting to your Amazon account.
To run the example, first set your queue ARN and AWS region:

```shell
export queueURL=<your SQS queue ARN>
export region=us-east-1
```

A number of different ways are supported to connect to your AWS account.

## AWS Profile

A profile from your ~/.aws/credentials file can be used:

```shell
export profileName="<your profile>"
```

## Session based credentials

Alternatively, temporary session keys can be used, if your AWS account uses federated login:

```shell
export accessKey="<your amazon access key>"
export secretKey="<your amazon secret key>"
export sessionToken="<your session token>"
```

## Basic Credentials

Standard access key ID and secret key credentials can be provided:

```shell
export accessKey="<your amazon access key>"
export queueURL="<URL of the SQS queue in your amazon account>"
export secretKey="<your amazon secret key>"
```

## DefaultAWSCredentialsProviderChain

If no credentials or profile are provided as environment variables, the [DefaultAWSCredentialsProviderChain](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/auth/DefaultAWSCredentialsProviderChain.html) will be used.

These environment variables must be set before running the example

```shell
Expand Down Expand Up @@ -87,7 +119,7 @@ It is also possible to send messages to the queue using a defined connection fac
A full example of this is shown below;
```java
try (AmazonSQSConnection connection = factory.getConnection()) {
connection.sendMessage(new SendMessageRequest("queueURL", "Hello World"));
connection.sendMessage(new SendMessageRequest("queueURL", "Hello World"));
} catch (Exception e) {}

```
Expand Down