Categories
AWS Java

Getting Started with AWS

Create an IAM user

I want to start with some practical experiences in AWS, so I go to https://aws.amazon.com, login with my Root user and open the Identity and Access Management (IAM ), where I create aa new IAM user, that I call “MyFirstProgrammaticAccessTestUser”, because the user is of access type Programmatic access. For now, I do not add the user to any group and add only one tag (that I name tag-key) to the user.
AWS is warning, that this user has not permissons, but this is fine for now, I will add any permission as soon as the user needs one.
Finally I note down the user name, Access key ID and the secret access key.

Set up AWS credentials and region

I am working on a Windows machine, so I create a folder .aws in C:\Users\USERNAME. In this folder I create a file credentials:

[default]
aws_access_key_id = your_access_key_id
aws_secret_access_key = your_secret_access_key

To set the default AWS Region I have to create another file in .aws folder: config:

[default]
region = eu-central-1

Additionally I have to set this information as environment variables.

I am really not sure, if this is the correct way to set this environment variables, but hey, this is only a test.

AWS SDK

I have to go to https://github.com/aws/aws-sdk-java-v2 to get the Clone with HTTPS URL.
Then open Eclipse and use the IMPORT dialog to import the project from GIT.
After checkout use the Configure -> Convert to Maven project dialog.
Then I tried Run as -> Maven install. But this results in a Build Failure:

[ERROR] Failed to execute goal com.github.spotbugs:spotbugs-maven-plugin:3.1.11:spotbugs (spotbugs) on project annotations: Execution spotbugs of goal com.github.spotbugs:spotbugs-maven-plugin:3.1.11:spotbugs failed: java.lang.IllegalArgumentException: Unsupported class file major version 57 -> [Help 1]

I found a clue, that I have to use Java 11 instead of my Java 13. So I downloaded a Java 11 JDK and added it to my Eclipse.
But unfortunately I have no clue, how to tell the embedded Eclipse Maven to use this Java 11 instead of Java 13. Great….NOT

Next try: Start a WSL Bash. Need to install Java and Maven first:

sudo apt install -y openjdk-11-jre maven
cd /mnt/[...]/aws-sdk-java-v2
mvn clean install

Now it took 15 minutes to run until it ends wit an ERROR: There are test failures.

While I was waiting for the WSL-Maven to finish, I figured out, how to tell the Eclipse-Maven to run with the Java 11: I have to create a new Run Configuration where I explicite select the JRE:

The Eclipse-Maven also ends with an ERROR: There are test failures.

But for today I am fine with this result.

Create an AWS Maven Project

I create a new Maven project in Eclipse where I pull in the entire AWS SDK. This is not a good choice for a real world application, where you should only pull in components you need, but for a test project it’s a good start.
This is my pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>test</groupId>
	<artifactId>aws</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>

	<properties>
		<java.version>1.8</java.version>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<aws.java.sdk.version>2.14.7</aws.java.sdk.version>
	</properties>

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>software.amazon.awssdk</groupId>
				<artifactId>bom</artifactId>
				<version>${aws.java.sdk.version}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

	<dependencies>
		<dependency>
			<groupId>software.amazon.awssdk</groupId>
			<artifactId>aws-sdk-java</artifactId>
			<version>${aws.java.sdk.version}</version>
		</dependency>
		<dependency>
			<groupId>org.apache.tomcat</groupId>
			<artifactId>tomcat-catalina</artifactId>
			<version>8.5.33</version>
			<scope>provided</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.8.0</version>
				<configuration>
					<source>${java.version}</source>
					<target>${java.version}</target>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-war-plugin</artifactId>
				<version>3.2.2</version>
				<configuration>
					<failOnMissingWebXml>false</failOnMissingWebXml>
					<warName>ROOT</warName>
					<wtpContextName>ROOT</wtpContextName>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

Add AWS SDK Logging

I wanted to add some logging so I put Log4J Libs dependencies to pom.xml and create a log4j2.xml file for configuration in src/main/resources folder.

log4j2.xml:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
  <Appenders>
    <Console name="ConsoleAppender" target="SYSTEM_OUT">
      <PatternLayout pattern="%d{YYYY-MM-dd HH:mm:ss} [%t] %-5p %c:%L - %m%n" />
    </Console>
  </Appenders>

  <Loggers>
    <Root level="WARN">
     <AppenderRef ref="ConsoleAppender"/>
    </Root>
    <Logger name="software.amazon.awssdk" level="WARN" />
    <Logger name="software.amazon.awssdk.request" level="DEBUG" />
    <Logger name="org.apache.http.wire" level="DEBUG" />
  </Loggers>
</Configuration>

pom.xml:

	<properties>
		<org.apache.logging.log4j.version>2.13.3</org.apache.logging.log4j.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.apache.logging.log4j</groupId>
			<artifactId>log4j-core</artifactId>
			<version>${org.apache.logging.log4j.version}</version>
		</dependency>
		<dependency>
			<groupId>org.apache.logging.log4j</groupId>
			<artifactId>log4j-api</artifactId>
			<version>${org.apache.logging.log4j.version}</version>
		</dependency>
		<dependency>
			<groupId>org.apache.logging.log4j</groupId>
			<artifactId>log4j-slf4j-impl</artifactId>
			<version>${org.apache.logging.log4j.version}</version>
		</dependency>
	</dependencies>

First Test Application

A fist simple Test application to get some CloudeWatch metrics:

package aws;

import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.cloudwatch.CloudWatchClient;
import software.amazon.awssdk.services.cloudwatch.model.ListMetricsRequest;
import software.amazon.awssdk.services.cloudwatch.model.ListMetricsResponse;
import software.amazon.awssdk.services.cloudwatch.model.Metric;

public class TestMain {

	public static void main(String[] args) {
		String namespace = "<metric-namespace>";
		Region region = Region.EU_CENTRAL_1;
		CloudWatchClient cw = CloudWatchClient.builder()
                .region(region)
                .build();
		listMets(cw, namespace) ;
	}
	public static void listMets( CloudWatchClient cw, String namespace) {

        boolean done = false;
        String nextToken = null;

        while(!done) {

            ListMetricsResponse response;

            if (nextToken == null) {
                ListMetricsRequest request = ListMetricsRequest.builder()
                        .namespace(namespace)
                        .build();

                response = cw.listMetrics(request);
            } else {
                ListMetricsRequest request = ListMetricsRequest.builder()
                        .namespace(namespace)
                        .nextToken(nextToken)
                        .build();

                response = cw.listMetrics(request);
            }

            for (Metric metric : response.metrics()) {
                System.out.printf(
                        "Retrieved metric %s", metric.metricName());
                System.out.println();
            }

            if(response.nextToken() == null) {
                done = true;
            } else {
                nextToken = response.nextToken();
            }
        }
    }
}

Result:

020-09-01 19:23:07 [main] DEBUG software.amazon.awssdk.request:84 - Sending Request: DefaultSdkHttpFullRequest(httpMethod=POST, protocol=https, host=monitoring.eu-central-1.amazonaws.com, encodedPath=, headers=[amz-sdk-invocation-id, Content-Length, Content-Type, User-Agent], queryParameters=[])
2020-09-01 19:23:08 [main] DEBUG software.amazon.awssdk.request:84 - Received error response: software.amazon.awssdk.services.cloudwatch.model.CloudWatchException: User: arn:aws:iam::175335015168:user/MyFirstProgrammaticAccessTestUser is not authorized to perform: cloudwatch:ListMetrics (Service: CloudWatch, Status Code: 403, Request ID: 75f02535-28c7-49c8-930a-b8d8449c625a, Extended Request ID: null)
Exception in thread "main" software.amazon.awssdk.services.cloudwatch.model.CloudWatchException: User: arn:aws:iam::175335015168:user/MyFirstProgrammaticAccessTestUser is not authorized to perform: cloudwatch:ListMetrics (Service: CloudWatch, Status Code: 403, Request ID: 75f02535-28c7-49c8-930a-b8d8449c625a, Extended Request ID: null)
	at software.amazon.awssdk.core.internal.http.CombinedResponseHandler.handleErrorResponse(CombinedResponseHandler.java:123)
	at software.amazon.awssdk.core.internal.http.CombinedResponseHandler.handleResponse(CombinedResponseHandler.java:79)
	at software.amazon.awssdk.core.internal.http.CombinedResponseHandler.handle(CombinedResponseHandler.java:59)
	at software.amazon.awssdk.core.internal.http.CombinedResponseHandler.handle(CombinedResponseHandler.java:40)
	at software.amazon.awssdk.core.internal.http.pipeline.stages.HandleResponseStage.execute(HandleResponseStage.java:40)
	at software.amazon.awssdk.core.internal.http.pipeline.stages.HandleResponseStage.execute(HandleResponseStage.java:30)
	at software.amazon.awssdk.core.internal.http.pipeline.RequestPipelineBuilder$ComposingRequestPipelineStage.execute(RequestPipelineBuilder.java:206)
	at software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallAttemptTimeoutTrackingStage.execute(ApiCallAttemptTimeoutTrackingStage.java:73)
	at software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallAttemptTimeoutTrackingStage.execute(ApiCallAttemptTimeoutTrackingStage.java:42)
	at software.amazon.awssdk.core.internal.http.pipeline.stages.TimeoutExceptionHandlingStage.execute(TimeoutExceptionHandlingStage.java:77)
	at software.amazon.awssdk.core.internal.http.pipeline.stages.TimeoutExceptionHandlingStage.execute(TimeoutExceptionHandlingStage.java:39)
	at software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallAttemptMetricCollectionStage.execute(ApiCallAttemptMetricCollectionStage.java:50)
	at software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallAttemptMetricCollectionStage.execute(ApiCallAttemptMetricCollectionStage.java:36)
	at software.amazon.awssdk.core.internal.http.pipeline.stages.RetryableStage.execute(RetryableStage.java:64)
	at software.amazon.awssdk.core.internal.http.pipeline.stages.RetryableStage.execute(RetryableStage.java:34)
	at software.amazon.awssdk.core.internal.http.pipeline.RequestPipelineBuilder$ComposingRequestPipelineStage.execute(RequestPipelineBuilder.java:206)
	at software.amazon.awssdk.core.internal.http.StreamManagingStage.execute(StreamManagingStage.java:56)
	at software.amazon.awssdk.core.internal.http.StreamManagingStage.execute(StreamManagingStage.java:36)
	at software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallTimeoutTrackingStage.executeWithTimer(ApiCallTimeoutTrackingStage.java:80)
	at software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallTimeoutTrackingStage.execute(ApiCallTimeoutTrackingStage.java:60)
	at software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallTimeoutTrackingStage.execute(ApiCallTimeoutTrackingStage.java:42)
	at software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallMetricCollectionStage.execute(ApiCallMetricCollectionStage.java:48)
	at software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallMetricCollectionStage.execute(ApiCallMetricCollectionStage.java:31)
	at software.amazon.awssdk.core.internal.http.pipeline.RequestPipelineBuilder$ComposingRequestPipelineStage.execute(RequestPipelineBuilder.java:206)
	at software.amazon.awssdk.core.internal.http.pipeline.RequestPipelineBuilder$ComposingRequestPipelineStage.execute(RequestPipelineBuilder.java:206)
	at software.amazon.awssdk.core.internal.http.pipeline.stages.ExecutionFailureExceptionReportingStage.execute(ExecutionFailureExceptionReportingStage.java:37)
	at software.amazon.awssdk.core.internal.http.pipeline.stages.ExecutionFailureExceptionReportingStage.execute(ExecutionFailureExceptionReportingStage.java:26)
	at software.amazon.awssdk.core.internal.http.AmazonSyncHttpClient$RequestExecutionBuilderImpl.execute(AmazonSyncHttpClient.java:193)
	at software.amazon.awssdk.core.internal.handler.BaseSyncClientHandler.invoke(BaseSyncClientHandler.java:128)
	at software.amazon.awssdk.core.internal.handler.BaseSyncClientHandler.doExecute(BaseSyncClientHandler.java:154)
	at software.amazon.awssdk.core.internal.handler.BaseSyncClientHandler.lambda$execute$1(BaseSyncClientHandler.java:107)
	at software.amazon.awssdk.core.internal.handler.BaseSyncClientHandler.measureApiCallSuccess(BaseSyncClientHandler.java:162)
	at software.amazon.awssdk.core.internal.handler.BaseSyncClientHandler.execute(BaseSyncClientHandler.java:91)
	at software.amazon.awssdk.core.client.handler.SdkSyncClientHandler.execute(SdkSyncClientHandler.java:45)
	at software.amazon.awssdk.awscore.client.handler.AwsSyncClientHandler.execute(AwsSyncClientHandler.java:55)
	at software.amazon.awssdk.services.cloudwatch.DefaultCloudWatchClient.listMetrics(DefaultCloudWatchClient.java:1877)
	at aws.TestMain.listMets(TestMain.java:33)
	at aws.TestMain.main(TestMain.java:17)

So the Error is:

user/MyFirstProgrammaticAccessTestUser is not authorized to perform: cloudwatch:ListMetrics

I try to solve this by going back to the IAM console and add the user to a new created group with attached policy “CloudWatchFullAccess”.

Result:

2020-09-01 19:38:27 [main] DEBUG software.amazon.awssdk.request:84 - Sending Request: DefaultSdkHttpFullRequest(httpMethod=POST, protocol=https, host=monitoring.eu-central-1.amazonaws.com, encodedPath=, headers=[amz-sdk-invocation-id, Content-Length, Content-Type, User-Agent], queryParameters=[])
2020-09-01 19:38:28 [main] DEBUG software.amazon.awssdk.request:84 - Received successful response: 200

So this worked, this was quite intuitive 🙂
The result is empty, I guess because of the metric-namespace that I initaly set with placeholder name. I looked into my CloudWatch Dashboard, but could not find any metric with data. I guess, I have to create a metric and find a way to create data for the metric. TBC

One reply on “Getting Started with AWS”

Leave a Reply

Your email address will not be published. Required fields are marked *