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

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

Related

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 Assume Role via .Net SDK gives Access Denied but works with CLI

I am trying to upload a file in S3 by AWS Assume Role. When I am trying to access it from CLI it works fine but from .Net SDK it gives me Access Denied error.
Here are the steps I followed in CLI -
Setup the access key/secret key for user using aws configure
Assume the Role - “aws sts assume-role --role-arn "arn:aws:iam::1010101010:role/Test-Account-Role" --role-session-name AWSCLI-Session”
Take the access key / secret key / session token from the assumed role and setup an AWS profile. The credentials are printed out/returned from the assumed role.
Switch to the assume role profile: “set AWS_PROFILE=”
Verify that the user has the role: “aws sts get-caller-identity”
Access the bucket using ls or cp or rm command - Works Successfully.
Now I am trying to access it from .Net core App -
Here is the code snippet- Note that I am using same Access and Secret key as CLI from my local.
try
{
var region = RegionEndpoint.GetBySystemName(awsRegion);
SessionAWSCredentials tempCredentials = await GetTemporaryCredentialsAsync(awsAccessKey, awsSecretKey, region, roleARN);
//Use the temp credentials received to create the new client
IAmazonS3 client = new AmazonS3Client(tempCredentials, region);
TransferUtility utility = new TransferUtility(client);
// making a TransferUtilityUploadRequest instance
TransferUtilityUploadRequest request = new TransferUtilityUploadRequest
{
BucketName = bucketName,
Key = $"{subFolder}/{fileName}",
FilePath = localFilePath
utility.Upload(request); //transfer
fileUploadedSuccessfully = true;
}
catch (AmazonS3Exception ex)
{
// HandleException
}
catch (Exception ex)
{
// HandleException
}
The method to get temp credentials is as follow - GetTemporaryCredentialsAsync
private static async Task<SessionAWSCredentials> GetTemporaryCredentialsAsync(string awsAccessKey, string awsSecretKey, RegionEndpoint region, string roleARN)
{
using (var stsClient = new AmazonSecurityTokenServiceClient(awsAccessKey, awsSecretKey, region))
{
var getSessionTokenRequest = new GetSessionTokenRequest
{
DurationSeconds = 7200
};
await stsClient.AssumeRoleAsync(
new AssumeRoleRequest()
{
RoleArn = roleARN,
RoleSessionName = "mySession"
});
GetSessionTokenResponse sessionTokenResponse =
await stsClient.GetSessionTokenAsync(getSessionTokenRequest);
Credentials credentials = sessionTokenResponse.Credentials;
var sessionCredentials =
new SessionAWSCredentials(credentials.AccessKeyId,
credentials.SecretAccessKey,
credentials.SessionToken);
return sessionCredentials;
}
}
I am getting back the temp credentials but it gives me Access Denied while uploading the file. Not sure if I am missing anything here.
Also noted that the token generated via SDK is shorter than that from CLI. I tried pasting these temp credentials to local profile and then tried to access the bucket and getting the Access Denied error then too.
There is an AWS .NET V3 example that shows this exact use case. To assume a role, you use a AmazonSecurityTokenServiceClient. In this example, the user assumes the role that allows the role to be used to list all S3 buckets. See this .NET scenario here.
https://github.com/awsdocs/aws-doc-sdk-examples/blob/main/dotnetv3/IAM/IAM_Basics_Scenario/IAM_Basics_Scenario/IAM_Basics.cs

Amazon EC2 client builder without region

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]
}

How to set up Amazon DynamoDB Client on AWS (JAVA)

Trying to set up a client for my Amazon DynamoDB in Java 8 and am running into this error when I try to run my lambda function locally. I am trying to connect to Amazon DynamoDB and I already have set up in AWS Management Console.
Error trying to commit audit record:com.amazonaws.services.dynamodbv2.model.AmazonDynamoDBException: The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details. (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: InvalidSignatureException;
I am still new to AWS and trying to understand how it works. I am sure the credentials I provided matched the ones I have.
AmazonDynamoDB client = AmazonDynamoDBClient.builder()
.withRegion("us-east-2")
.withCredentials(new AWSStaticCredentialsProvider(new
BasicAWSCredentials("key","private key")))
.build();
DynamoDB dynamoDB = new DynamoDB(client);
Table table = dynamoDB.getTable("tableName")
Maybe you can try out changing according to example in AWS docs, without explicitly setting credential provider.
https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/CodeSamples.Java.html
This is my code for creating a table and this is working:
BasicAWSCredentials awsCreds = new BasicAWSCredentials("access_key_id", "secret_key_id");
AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard()
.withRegion(Regions.US_EAST_1)
.withCredentials(new AWSStaticCredentialsProvider(awsCreds))
.build();
// AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard()
// .withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration("http://localhost:8000", "us-west-2"))
// .build();
DynamoDB dynamoDB = new DynamoDB(client);
String tableName = "Songs";
try {
System.out.println("Attempting to create table; please wait...");
Table table = dynamoDB.createTable(tableName,
Arrays.asList(
new KeySchemaElement("year", KeyType.HASH), // Partition
// key
new KeySchemaElement("title", KeyType.RANGE)), // Sort key
Arrays.asList(new AttributeDefinition("year", ScalarAttributeType.N),
new AttributeDefinition("title", ScalarAttributeType.S)),
new ProvisionedThroughput(10L, 10L));
table.waitForActive();
System.out.println("Success. Table status: " + table.getDescription().getTableStatus());
} catch (Exception e) {
System.err.println("Unable to create table: ");
System.err.println(e.getMessage());
}

DynamoDB Connection Biulding using AWS Java SDK by getting Keys from the user at runtime

I'm trying to connect to DynamoDB by getting AccessID and SecretKey from the user. AmazonDynamoDBClient has been depreciated and the replacement don't allow me to get credentials from the user and make a connection to DynamoDB. Here is my code snippet. The solution I'm getting is to keep the keys in a local file. I don't need this.
DynamoDB dynamoDB = null;
try {
System.out.println(1);
BasicAWSCredentials awsCreds = new BasicAWSCredentials(upDoc.getAccID(), upDoc.getAccKey());
System.out.println(2);
//AmazonDynamoDBClient is depreciated
AmazonDynamoDBClient client = new AmazonDynamoDBClient(awsCreds).withRegion(Regions.US_EAST_2);
System.out.println(3);
dynamoDB = new DynamoDB(client);
writer.append("Access Granted By AWS DynamoDB \n");
}catch(AmazonDynamoDBException e) {
writer.append("Access Denied By AWS DynamoDB \n");
writer.close();
return "Error occured. Kindly check logs to get the actual cause!";
}
Use AmazonDynamoDBClientBuilder
BasicAWSCredentials awsCreds = new BasicAWSCredentials(upDoc.getAccID(), upDoc.getAccKey());
AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().withRegion(Regions.US_EAST_2).withCredentials(awsCreds).build();