0

I'm trying to use the AWS SNS Java SDK on an application that is hosted on a EC2 machine. For the SNS SDK, the way to provide credentials is different than other SDKs, like S3. I did not specify any credentials chain mechanism, and on my local machine it seems it extracts the credentials from the .aws/credentials file by default.

I have updated my credentials from my EC2 machine, which are located at ~/.aws/credentials. However, when running my application on EC2, I'm getting the following error when trying to publish a message to SNS:

software.amazon.awssdk.services.sns.model.SnsException: The security token included in the request is invalid. (Service: Sns, Status Code: 403, Request ID: 3177217e-e32d-5df5-ab2a-783f74fb6209, Extended Request ID: null)

Things I have tried so far:

  • I have given 777 permissions to the .aws folder.
  • Checked the $HOME variable, it outputs: /home/ec2-user. To me it seems alright.
  • Tried to hardcode the AWS credentials from the code, but the SDK doesn't seem to permit to specify the session token.
  • I must mention that I had the same issues with S3, yet that SDK allowed me to fully specify the credentials from the code.

I have imported the SNS SDK as follows:

pom.xml

...
<dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>software.amazon.awssdk</groupId>
                <artifactId>bom</artifactId>
                <version>2.16.29</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
</dependencyManagement>

...

<dependency>
            <groupId>software.amazon.awssdk</groupId>
            <artifactId>sns</artifactId>
</dependency>

The bare minimum SNS Java code:

SnsClient client = SnsClient.builder()
            .region(Region.US_EAST_1)
            .build();
    try {
        PublishRequest request = PublishRequest.builder()
                .message("message")
                .topicArn("topicName")
                .build();
        PublishResponse result = client.publish(request);
        System.out.println("Published: " + message + " " + result.messageId() + " Message sent. Status was " + result.sdkHttpResponse().statusCode());
    } catch (SnsException e){
        e.printStackTrace();
    }

Do you have any idea what could be going on? Thank you!

I. S.
  • 103
  • 1
  • 5

1 Answers1

0

One thing you can try to see if it works when using the SNS Service on an EC2 instance is to set environment variables. When I deploy a web app onto an EC2 instance (using Elastic Beanstalk) that uses SNS Java V2 API, I have done this and it works fine.

private SnsClient getSnsClient() {

    Region region = Region.US_WEST_2;
    SnsClient snsClient = SnsClient.builder()
            .credentialsProvider(EnvironmentVariableCredentialsProvider.create())
            .region(region)
            .build();

    return snsClient;
 }
smac2020
  • 9,637
  • 4
  • 24
  • 38
  • Did you test the creds in a Java main example on your dev machine to make sure they are valid? – smac2020 Jun 14 '21 at 18:59
  • Yes, it works. On the EC2, I have set the environment variables from the ~/.bash_profile. At least it could have said that the security token has expired.. – I. S. Jun 14 '21 at 19:31
  • SO your creds work on the local dev but do not work on EC2 - even when using env vars? – smac2020 Jun 14 '21 at 19:36
  • Yes. The system on the local dev uses Windows if that makes any difference. The application is deployed as a web-archive under Payara. The web-archive is built on the local dev machine, but again, I don't see how that would influence in any way.. – I. S. Jun 14 '21 at 19:38
  • Today I'll try the same thing on a new EC2 machine. Also, is there a way to log the credentials that the SDKs attempt to use? – I. S. Jun 15 '21 at 04:33