Amazon EC2 client builder without region - amazon-web-services

I am trying to connect to a client's AWS using the secret key, access key, and role-arn in a java application.
Using AmazonEC2ClientBuilder requires the region to be specified.
Is there any way or any API support where I can connect to a client's AWS without the need for the region ?
Thanks.

When you use the Amazon EC2 Java API (V2), you specify a region to tell the code which region your EC2 instances are you located in.
That is, if I have my EC2 instances in USA West 2, then I need to specify this region when creating a Service Client, as shown in this Java V2 code example that finds running Amazon EC2 instances in USA West 2. You code still works without a region, but will default to a region. The default region for an SDK is US-EAST-1
package com.example.ec2;
// snippet-start:[ec2.java2.running_instances.import]
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.ec2.Ec2Client;
import software.amazon.awssdk.services.ec2.model.Filter;
import software.amazon.awssdk.services.ec2.model.DescribeInstancesRequest;
import software.amazon.awssdk.services.ec2.model.DescribeInstancesResponse;
import software.amazon.awssdk.services.ec2.model.Reservation;
import software.amazon.awssdk.services.ec2.model.Instance;
import software.amazon.awssdk.services.ec2.model.Ec2Exception;
// snippet-end:[ec2.java2.running_instances.import]
/**
* To run this Java V2 code example, ensure that you have setup your development environment, including your credentials.
*
* For information, see this documentation topic:
*
* https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html
*/
public class FindRunningInstances {
public static void main(String[] args) {
Region region = Region.US_WEST_2;
Ec2Client ec2 = Ec2Client.builder()
.region(region)
.build();
findRunningEC2Instances(ec2);
ec2.close();
}
// snippet-start:[ec2.java2.running_instances.main]
// This method creates a Filter to find all running instances
public static void findRunningEC2Instances(Ec2Client ec2) {
try {
String nextToken = null;
do {
Filter filter = Filter.builder()
.name("instance-state-name")
.values("running")
.build();
DescribeInstancesRequest request = DescribeInstancesRequest.builder()
.filters(filter)
.build();
DescribeInstancesResponse response = ec2.describeInstances(request);
for (Reservation reservation : response.reservations()) {
for (Instance instance : reservation.instances()) {
System.out.printf(
"Found Reservation with id %s, " +
"AMI %s, " +
"type %s, " +
"state %s " +
"and monitoring state %s",
instance.instanceId(),
instance.imageId(),
instance.instanceType(),
instance.state().name(),
instance.monitoring().state());
System.out.println("");
}
}
nextToken = response.nextToken();
} while (nextToken != null);
} catch (Ec2Exception e) {
System.err.println(e.awsErrorDetails().errorMessage());
System.exit(1);
}
}
// snippet-end:[ec2.java2.running_instances.main]
}

Related

How to get the AWS EC2 Instance name using spring boot or any aws endpoint

Actually, I was looking to get the EC2 instance name,
I tried using EC2MetadataUtils class to get the metadata but in that response, the instance name is not there.
Could you please someone suggest any util class endpoint to get the name?
As luk2302 correctly states, the Name field is just a tag. The EC2 documentation has an example for how you can retrieve tags from the instance metadata:
https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-data-retrieval.html#instance-metadata-ex-7
You can use this Java code piece. EC2MetadataUtils does not currently allow to read tags by SDK.
Ec2Client ec2Client = Ec2Client.builder().build();
String instanceId = "i-qqweqweqwe";
DescribeInstancesRequest instanceRequest = DescribeInstancesRequest.builder()
.instanceIds(instanceId)
.build();
DescribeInstancesResponse describeInstancesResponse = ec2Client.describeInstances(instanceRequest);
if (describeInstancesResponse.reservations().size() > 0 && describeInstancesResponse.reservations().get(0).instances().size() > 0) {
List<Tag> tags = describeInstancesResponse.reservations().get(0).instances().get(0).tags();
Optional<String> name = tags.stream().filter(t -> t.key().equals("Name")).map(Tag::value).findFirst();
if (name.isPresent()) {
System.out.println(instanceId + " name is " + name);
}
}

S3Exception: The bucket you are attempting to access must be addressed using the specified endpoint

I know that there are many similar questions, and this one is no exception
But unfortunately I can't decide on the region for my case, how can I decide on the right region?
For example, when making a request to Postman, I encounter a similar error:
In my console i'm using EU (Frankfurt) eu-central-1 and also in terminal write smth like this:
heroku config:set region="eu-central-1"
And as I understand it, mine does not fit.
Also here is my AWS class:
class AmazonFileStorage : FileStorage {
private val client: S3Client
private val bucketName: String = System.getenv("bucketName")
init {
val region = System.getenv("region")
val accessKey = System.getenv("accessKey")
val secretKey = System.getenv("secretKey")
val credentials = AwsBasicCredentials.create(accessKey, secretKey)
val awsRegion = Region.of(region)
client = S3Client.builder()
.credentialsProvider(StaticCredentialsProvider.create(credentials))
.region(awsRegion)
.build() as S3Client
}
override suspend fun save(file: File): String =
withContext(Dispatchers.IO) {
client.putObject(
PutObjectRequest.builder().bucket(bucketName).key(file.name).acl(ObjectCannedACL.PUBLIC_READ).build(),
RequestBody.fromFile(file)
)
val request = GetUrlRequest.builder().bucket(bucketName).key(file.name).build()
client.utilities().getUrl(request).toExternalForm()
}
}
I think you may have the wrong region code; you do know that a Bucket is available in one and only one Region?
In your logging settings, set this scope to debug:
logging:
level:
org.apache.http.wire: debug
Then you should see something like this:
http-outgoing-0 >> "HEAD /somefile HTTP/1.1[\r][\n]"
http-outgoing-0 >> "Host: YOURBUCKETNAME.s3.eu-west-2.amazonaws.com[\r][\n]"
That log is from a bucket in the London region eu-west-2
To use Kotlin to interact with an Amazon S3 bucket (or other AWS services), consider using the AWS SDK for Kotlin. This SDK is meant for Kotlin developers. You are using the AWS SDK for Java.
To put an object into an Amazon S3 bucket using the AWS SDK for Kotlin, use this code. Notice the region that you want to use is specified in the code block where you define the aws.sdk.kotlin.services.s3.S3Client.
import aws.sdk.kotlin.services.s3.S3Client
import aws.sdk.kotlin.services.s3.model.PutObjectRequest
import aws.smithy.kotlin.runtime.content.asByteStream
import java.io.File
import kotlin.system.exitProcess
/**
Before running this Kotlin code example, set up your development environment,
including your credentials.
For more information, see the following documentation topic:
https://docs.aws.amazon.com/sdk-for-kotlin/latest/developer-guide/setup.html
*/
suspend fun main(args: Array<String>) {
val usage = """
Usage:
<bucketName> <objectKey> <objectPath>
Where:
bucketName - The Amazon S3 bucket to upload an object into.
objectKey - The object to upload (for example, book.pdf).
objectPath - The path where the file is located (for example, C:/AWS/book2.pdf).
"""
if (args.size != 3) {
println(usage)
exitProcess(0)
}
val bucketName = args[0]
val objectKey = args[1]
val objectPath = args[2]
putS3Object(bucketName, objectKey, objectPath)
}
suspend fun putS3Object(bucketName: String, objectKey: String, objectPath: String) {
val metadataVal = mutableMapOf<String, String>()
metadataVal["myVal"] = "test"
val request = PutObjectRequest {
bucket = bucketName
key = objectKey
metadata = metadataVal
body = File(objectPath).asByteStream()
}
S3Client { region = "us-east-1" }.use { s3 ->
val response = s3.putObject(request)
println("Tag information is ${response.eTag}")
}
}
You can find this Kotlin example and many more in the AWS Code Library here:
Amazon S3 examples using SDK for Kotlin
ALso you can read the Kotlin DEV guide too. The link is at the start of the Code Example.

AWS CDK - Connect a Network Load Balancer and a Neptune Cluster Endpoint together

For the past two days I've been struggling with exposing a Neptune endpoint to the public using an NLB in a single stack. The architecture was inspired by this document.
For the life of me I haven't been able to figure out how to obtain the IP address of the Neptune endpoint to use as the target of NLB's listener. The main issue resides in the conversion of the Neptune hostname to an IP address as required by NLB's target group IPTarget and how CDK synthesizes stacks before deployment.
I explored the use of CustomResources to no avail due to my limited familiarity with the topic (day 5 of my aws journey), and was hoping someone could point me in the right direction.
Here's my stack (CDK app repo here):
import { Construct } from "constructs";
import { Stack } from "aws-cdk-lib";
import * as ec2 from "aws-cdk-lib/aws-ec2";
import * as elbv2 from "aws-cdk-lib/aws-elasticloadbalancingv2";
import * as neptune from "#aws-cdk/aws-neptune-alpha";
import { Props } from "../../_config";
import createVPC from "../helpers/createVPC";
import createNeptuneCluster from "../helpers/createNeptuneCluster";
import createNLB from "../helpers/createNLB";
export class ABCGraphStack extends Stack {
public readonly vpc: ec2.Vpc;
public readonly subnets: {
public: ec2.ISubnet[];
private: ec2.ISubnet[];
isolated: ec2.ISubnet[];
};
public readonly neptuneCluster: neptune.DatabaseCluster;
public readonly neptuneReadEndpoint: neptune.Endpoint;
public readonly neptuneWriteEndpoint: neptune.Endpoint;
public readonly nlb: elbv2.NetworkLoadBalancer;
constructor(scope: Construct, id: string, props: Props) {
super(scope, id, props);
// Create VPC for use with Neptune
const { vpc, subnets } = createVPC(props, this);
this.vpc = vpc;
this.subnets = subnets;
// Create Neptune Cluster
this.neptuneCluster = createNeptuneCluster(
props,
this,
this.vpc,
this.subnets
);
// Update Neptune Security Group to allow-all-in
this.neptuneCluster.connections.allowDefaultPortFromAnyIpv4(
"Allow All Inbound to Neptune"
);
// Add an ordering dependency on VPC.
this.neptuneCluster.node.addDependency(this.vpc);
// Output the Neptune read/write addresses
this.neptuneReadEndpoint = this.neptuneCluster.clusterReadEndpoint;
this.neptuneWriteEndpoint = this.neptuneCluster.clusterEndpoint;
// HOW TO GET IP ADDRESS OF this.neptuneWriteEndpoint.hostname?
// Create Network Load Balancer
this.nlb = createNLB(props, this, this.vpc, "????????", 8182);
this.nlb.node.addDependency(this.neptuneCluster);
}
}

How to invoke secrets from AWS Secrets Manager into code to get the data from an Amazon DyanmoDB table

I have stored AWS IAM user Access key's and Secret keys in a secret of AWS Secrets Manager.
This secret is helpful to get the data from an Amazon DynamoDB table, and keys's having full access to the Amazon DynamoDB table. I need to use this secret in java/.Net code to retrieve the data from DynamoDB table.
Secretname: dynamodbtesting
Below is the sample key names which I used while creating secret.
{
"aws_access_key_id": "value",
"aws_secret_access_key": "secret value"
}
How to use secret in java/.Net code to get the date from DynamoDB table?
Note: I could see one sample code after creation of secret in secret manager, is it helpful?
When using the AWS Java SDK, when you build the client which accesses dynamodb, you can pass credentials explicitly:
https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/credentials.html#credentials-explicit
For example:
BasicAWSCredentials awsCreds = new BasicAWSCredentials("access_key_id", "secret_key_id");
AmazonS3 dynamodbClient = AmazonDynamoDBClientBuilder.standard()
.withCredentials(new AWSStaticCredentialsProvider(awsCreds))
.build();
To answer your question: "How to use secret in java"
You can use the Secrets Manager Java API V2 to retrive a secret. The following Java code shows you how to perform this use case:
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient;
import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueRequest;
import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueResponse;
import software.amazon.awssdk.services.secretsmanager.model.SecretsManagerException;
//snippet-end:[secretsmanager.java2.get_secret.import]
/**
* To run this AWS code example, ensure that you have setup your development environment, including your AWS credentials.
*
* For information, see this documentation topic:
*
*https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html
*/
public class GetSecretValue {
public static void main(String[] args) {
final String USAGE = "\n" +
"Usage:\n" +
" GetSecretValue <secretName> \n\n" +
"Where:\n" +
" secretName - the name of the secret (for example, tutorials/MyFirstSecret). \n";
if (args.length != 1) {
System.out.println(USAGE);
System.exit(1);
}
String secretName = args[0];
Region region = Region.US_EAST_1;
SecretsManagerClient secretsClient = SecretsManagerClient.builder()
.region(region)
.build();
getValue(secretsClient, secretName);
secretsClient.close();
}
//snippet-start:[secretsmanager.java2.get_secret.main]
public static void getValue(SecretsManagerClient secretsClient,String secretName) {
try {
GetSecretValueRequest valueRequest = GetSecretValueRequest.builder()
.secretId(secretName)
.build();
GetSecretValueResponse valueResponse = secretsClient.getSecretValue(valueRequest);
String secret = valueResponse.secretString();
System.out.println(secret);
} catch (SecretsManagerException e) {
System.err.println(e.awsErrorDetails().errorMessage());
System.exit(1);
}
}
//snippet-end:[secretsmanager.java2.get_secret.main]
}
You can find this example and others for this AWS Service here:
https://github.com/awsdocs/aws-doc-sdk-examples/tree/master/javav2/example_code/secretsmanager

How to request "Snapshot Log" through AWS Java SDK?

Is it possible to request "Snapshot Logs" through AWS SDK somehow?
It's possible to do it through AWS console:
Cross posted to Amazon forum.
Requesting a log snapshot is a 3 step process. First you have to do an environment information request:
elasticBeanstalk.requestEnvironmentInfo(
new RequestEnvironmentInfoRequest()
.withEnvironmentName(envionmentName)
.withInfoType("tail"));
Then you have to retreive the environment information:
final List<EnvironmentInfoDescription> envInfos =
elasticBeanstalk.retrieveEnvironmentInfo(
new RetrieveEnvironmentInfoRequest()
.withEnvironmentName(environmentName)
.withInfoType("tail")).getEnvironmentInfo();
This returns a list of environment info descriptions, with the EC2 instance id and the URL to an S3 object that contains the log snapshot. You can then retreive the logs with:
DefaultHttpClient client = new DefaultHttpClient();
DefaultHttpRequestRetryHandler retryhandler =
new DefaultHttpRequestRetryHandler(3, true);
client.setHttpRequestRetryHandler(retryhandler);
for (EnvironmentInfoDescription environmentInfoDescription : envInfos) {
System.out.println(environmentInfoDescription.getEc2InstanceId());
HttpGet rq = new HttpGet(environmentInfoDescription.getMessage());
try {
HttpResponse response = client.execute(rq);
InputStream content = response.getEntity().getContent();
System.out.println(IOUtils.toString(content));
} catch ( Exception e ) {
System.out.println("Exception fetching " +
environmentInfoDescription.getMessage());
}
}
I hope this helps!