diff --git a/java/datastax-v4/connection-EKS-SigV4/.DS_Store b/java/datastax-v4/connection-EKS-SigV4/.DS_Store new file mode 100644 index 0000000..5008ddf Binary files /dev/null and b/java/datastax-v4/connection-EKS-SigV4/.DS_Store differ diff --git a/java/datastax-v4/connection-EKS-SigV4/Dockerfile b/java/datastax-v4/connection-EKS-SigV4/Dockerfile new file mode 100644 index 0000000..e73cff4 --- /dev/null +++ b/java/datastax-v4/connection-EKS-SigV4/Dockerfile @@ -0,0 +1,27 @@ +# Start with a base image containing Java runtime +FROM --platform=linux/amd64 openjdk:17-jdk-alpine + +# Make port 8080 available to the world outside this container +EXPOSE 8080 + +# Add a volume pointing to /tmp +VOLUME /tmp + +# The application's jar file +ARG JAR_FILE=target/mykeyspacessigv4springbootapp-1.0-SNAPSHOT.jar + +# Add the application's jar to the container +COPY ${JAR_FILE} app.jar + +# Add the truststore to the container +COPY cassandra_truststore.jks /usr/app/cassandra_truststore.jks + +# Add the application's properties to the container +COPY src/main/resources/application.conf /usr/app/application.conf + +# Add the application's logback configuration to the container +COPY src/main/resources/logback.xml /usr/app/logback.xml + +# Run the jar file +ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"] + diff --git a/java/datastax-v4/connection-EKS-SigV4/README.md b/java/datastax-v4/connection-EKS-SigV4/README.md new file mode 100644 index 0000000..2b5a87c --- /dev/null +++ b/java/datastax-v4/connection-EKS-SigV4/README.md @@ -0,0 +1,98 @@ +# Connection to Amazon Keyspaces from Amazon EKS using SigV4 Authentication + +This example demonstrates how to connect to Amazon Keyspaces from an Amazon EKS cluster using SigV4 authentication. + +## Prerequisites + +- Amazon EKS cluster +- Amazon Keyspaces +- AWS CLI +- kubectl +- Docker +- Amazon ECR + +## Setup + +### Clone the Repository + +```shell +git clone https://github.com/naveenkantamneni/amazon-keyspaces-examples.git +``` + +## Create Keyspace and Table in Amazon Keyspaces + +``` +CREATE KEYSPACE aws WITH replication = {'class': 'SimpleStrategy', 'replication_factor': '3'} AND durable_writes = true; +CREATE TABLE aws.user ( + username text PRIMARY KEY, + fname text, + last_update_date timestamp, + lname text +); +``` + +## Create your Amazon EKS Cluster by following steps in below page +https://docs.aws.amazon.com/eks/latest/userguide/getting-started-eksctl.html + +## Create an OIDC provider for your EKS cluster by following instructions on below page +https://docs.aws.amazon.com/eks/latest/userguide/enable-iam-roles-for-service-accounts.html + +## Create a Kubernetes Service Account to assume an IAM role by following the instructions on below page. Follow Instructions under AWS CLI section and make sure to add IAM Policy "AmazonKeyspacesFullAccess" to your IAM Role in step "g" +https://docs.aws.amazon.com/eks/latest/userguide/associate-service-account-role.html + +## Confirm that the "AmazonKeyspacesFullAccess" policy that you attached to your role in a previous step is attached to the role. + +``` +aws iam list-attached-role-policies --role-name myeks-servicerole-assumewebid +``` + +An example output is as follows + +``` +{ + "AttachedPolicies": [ + { + "PolicyName": "AmazonKeyspacesFullAccess", + "PolicyArn": "arn:aws:iam::aws:policy/AmazonKeyspacesFullAccess" + } + ] +} +``` + +## Create your Amazon ECR repository +``` +aws ecr create-repository --repository-name +``` + +## Navigate to the base Directory, Modify the Dockerfile as needed and build the Docker Image. Make sure to use your AWS Account ID, AWS Region where ECR repository created, ECR repository name and your tag during build + +``` +cd amazon-keyspaces-examples/java/datastax-v4/connection-EKS-SigV4 +docker build -t .dkr.ecr..amazonaws.com/: . +``` + +## Retrieve Authentication Token to push the image to ECR +``` +aws ecr get-login-password --region | docker login --username AWS --password-stdin .dkr.ecr..amazonaws.com +``` + +## Push Docker Image to Amazon ECR repository +``` +docker push .dkr.ecr..amazonaws.com/: +``` + +## Modify deployment.yaml with relevant information and Deploy Application to Amazon EKS +``` +kubectl apply -f deployment.yaml +``` + +## Check the POD status +``` +kubectl get pods -n +``` + +### Optional, Validate Logs to ensure connectivity to Amazon Keyspaces +``` +kubectl logs -f -n +``` + diff --git a/java/datastax-v4/connection-EKS-SigV4/cassandra_truststore.jks b/java/datastax-v4/connection-EKS-SigV4/cassandra_truststore.jks new file mode 100644 index 0000000..ce4b9fa Binary files /dev/null and b/java/datastax-v4/connection-EKS-SigV4/cassandra_truststore.jks differ diff --git a/java/datastax-v4/connection-EKS-SigV4/deployment.yaml b/java/datastax-v4/connection-EKS-SigV4/deployment.yaml new file mode 100644 index 0000000..500c675 --- /dev/null +++ b/java/datastax-v4/connection-EKS-SigV4/deployment.yaml @@ -0,0 +1,33 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: mykeyspacessigv4springbootapp + namespace: +spec: + replicas: 1 + selector: + matchLabels: + app: mykeyspacessigv4springbootapp + template: + metadata: + labels: + app: mykeyspacessigv4springbootapp + spec: + serviceAccountName: + containers: + - name: + image: .dkr.ecr..amazonaws.com/: + ports: + - containerPort: 8080 + env: + - name: CASSANDRA_HOST + value: ":9142" + - name: CASSANDRA_DC + value: "" + - name: AWS_WEB_IDENTITY_TOKEN_FILE + value: /var/run/secrets/eks.amazonaws.com/serviceaccount/token + - name: AWS_ROLE_ARN + value: "arn:aws:iam:::role/" + - name: AWS_REGION + value: "" + diff --git a/java/datastax-v4/connection-EKS-SigV4/pom.xml b/java/datastax-v4/connection-EKS-SigV4/pom.xml new file mode 100644 index 0000000..67f9c1c --- /dev/null +++ b/java/datastax-v4/connection-EKS-SigV4/pom.xml @@ -0,0 +1,76 @@ + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 3.1.1 + + + com.example + mykeyspacessigv4springbootapp + 1.0-SNAPSHOT + jar + + + UTF-8 + 17 + + + + + com.datastax.oss + java-driver-core + 4.15.0 + + + software.aws.mcs + aws-sigv4-auth-cassandra-java-driver-plugin + 4.0.3 + + + org.slf4j + slf4j-api + 2.0.5 + + + org.springframework.boot + spring-boot-starter-data-cassandra + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-test + test + + + javax.annotation + javax.annotation-api + 1.3.2 + + + com.amazonaws + aws-java-sdk-sts + 1.11.717 + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + 17 + + + + + diff --git a/java/datastax-v4/connection-EKS-SigV4/src/.DS_Store b/java/datastax-v4/connection-EKS-SigV4/src/.DS_Store new file mode 100644 index 0000000..5ea7480 Binary files /dev/null and b/java/datastax-v4/connection-EKS-SigV4/src/.DS_Store differ diff --git a/java/datastax-v4/connection-EKS-SigV4/src/main/.DS_Store b/java/datastax-v4/connection-EKS-SigV4/src/main/.DS_Store new file mode 100644 index 0000000..d4cbecc Binary files /dev/null and b/java/datastax-v4/connection-EKS-SigV4/src/main/.DS_Store differ diff --git a/java/datastax-v4/connection-EKS-SigV4/src/main/java/com/example/mykeyspacessigv4springbootapp/Mykeyspacessigv4springbootappApplication.java b/java/datastax-v4/connection-EKS-SigV4/src/main/java/com/example/mykeyspacessigv4springbootapp/Mykeyspacessigv4springbootappApplication.java new file mode 100644 index 0000000..c2b36b4 --- /dev/null +++ b/java/datastax-v4/connection-EKS-SigV4/src/main/java/com/example/mykeyspacessigv4springbootapp/Mykeyspacessigv4springbootappApplication.java @@ -0,0 +1,73 @@ +package com.example.mykeyspacessigv4springbootapp; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.core.io.ClassPathResource; +import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; + +import javax.annotation.PreDestroy; +import java.io.File; +import java.net.InetSocketAddress; +import java.security.NoSuchAlgorithmException; +import java.time.LocalDate; +import javax.net.ssl.SSLContext; + +import com.datastax.oss.driver.api.core.CqlSession; +import com.datastax.oss.driver.api.core.ConsistencyLevel; +import com.datastax.oss.driver.api.core.cql.SimpleStatement; +import com.datastax.oss.driver.api.core.config.DriverConfigLoader; +import software.aws.mcs.auth.SigV4AuthProvider; + +@SpringBootApplication +public class Mykeyspacessigv4springbootappApplication { + + private CqlSession session; + + public static void main(String[] args) { + SpringApplication.run(Mykeyspacessigv4springbootappApplication.class, args); + } + + @Bean + public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { + PropertySourcesPlaceholderConfigurer properties = new PropertySourcesPlaceholderConfigurer(); + properties.setLocation(new ClassPathResource("application.conf")); + properties.setIgnoreResourceNotFound(false); + properties.setIgnoreUnresolvablePlaceholders(false); + return properties; + } + + @Bean + public CqlSession cqlSession() throws NoSuchAlgorithmException { + String cassandraHost = System.getenv("CASSANDRA_HOST"); + String cassandraDC = System.getenv("CASSANDRA_DC"); + + var builder = CqlSession.builder() + .addContactPoint(new InetSocketAddress(cassandraHost.split(":")[0], Integer.parseInt(cassandraHost.split(":")[1]))) + .withAuthProvider(new SigV4AuthProvider(cassandraDC)) + .withLocalDatacenter(cassandraDC) + .withSslContext(SSLContext.getDefault()) + .withConfigLoader(DriverConfigLoader.fromClasspath("application.conf")); + + session = builder.build(); + + // Insert statement + String query = "INSERT INTO aws.user (username,fname,last_update_date,lname) VALUES ('test','random',dateOf(now()),'k')"; + SimpleStatement statement = SimpleStatement.newInstance(query).setConsistencyLevel(ConsistencyLevel.LOCAL_QUORUM); + session.execute(statement); + System.out.println("Insert operation was successful. The following row was added:"); + System.out.println("Username: test"); + System.out.println("First Name: random"); + System.out.println("Last Update Date: " + LocalDate.now()); + System.out.println("Last Name: k"); + + return session; + } + + @PreDestroy + public void preDestroy() { + if (session != null) { + session.close(); + } + } +} diff --git a/java/datastax-v4/connection-EKS-SigV4/src/main/resources/application.conf b/java/datastax-v4/connection-EKS-SigV4/src/main/resources/application.conf new file mode 100644 index 0000000..b75fa68 --- /dev/null +++ b/java/datastax-v4/connection-EKS-SigV4/src/main/resources/application.conf @@ -0,0 +1,17 @@ +datastax-java-driver { + basic.contact-points = ["cassandra.us-east-1.amazonaws.com:9142"] + basic.load-balancing-policy.local-datacenter = "us-east-1" + advanced.auth-provider { + class = software.aws.mcs.auth.SigV4AuthProvider + aws-region = "us-east-1" + } + advanced.ssl-engine-factory { + class = DefaultSslEngineFactory + truststore-path = "/usr/app/cassandra_truststore.jks" + truststore-password = "test" + } +} +cassandra { + host = ${?CASSANDRA_HOST} + dc = ${?CASSANDRA_DC} +} diff --git a/java/datastax-v4/connection-EKS-SigV4/src/main/resources/logback.xml b/java/datastax-v4/connection-EKS-SigV4/src/main/resources/logback.xml new file mode 100644 index 0000000..9f31eed --- /dev/null +++ b/java/datastax-v4/connection-EKS-SigV4/src/main/resources/logback.xml @@ -0,0 +1,13 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + diff --git a/java/datastax-v4/connection-EKS-SigV4/src/test/java/com/example/mykeyspacessigv4springbootapp/Mykeyspacessigv4springbootappApplicationTests.java b/java/datastax-v4/connection-EKS-SigV4/src/test/java/com/example/mykeyspacessigv4springbootapp/Mykeyspacessigv4springbootappApplicationTests.java new file mode 100644 index 0000000..6c44092 --- /dev/null +++ b/java/datastax-v4/connection-EKS-SigV4/src/test/java/com/example/mykeyspacessigv4springbootapp/Mykeyspacessigv4springbootappApplicationTests.java @@ -0,0 +1,13 @@ +package com.example.mykeyspacessigv4springbootapp; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class Mykeyspacessigv4springbootappApplicationTests { + + @Test + void contextLoads() { + } + +}