Kotlin & DynamoDB: Unable to resolve host "dynamodb.us-east-1.amazonaws.com": No address associated with hostname - amazon-web-services

I'm trying to connect my Kotlin Android app to DynamoDB in AWS using Android Studio. My credential details are replaced in the code below and it is connecting to an AWS sandbox. The created database client is below:
val staticCredentials = StaticCredentialsProvider {
accessKeyId = MY_ACCESS_KEY_HERE
secretAccessKey = MY_SECRET_ACCESS_KEY
}
ddb = DynamoDbClient{
region = MY_REGION_HERE
credentialsProvider = staticCredentials
}
Then I attempted to create the table using this client following these steps :
val tableNameVal = "Users"
val attDef = AttributeDefinition {
attributeName = key
attributeType = ScalarAttributeType.S
}
val keySchemaVal = KeySchemaElement {
attributeName = key
keyType = KeyType.Hash
}
val provisionedVal = ProvisionedThroughput {
readCapacityUnits = 10
writeCapacityUnits = 10
}
val request = CreateTableRequest {
attributeDefinitions = listOf(attDef)
keySchema = listOf(keySchemaVal)
provisionedThroughput = provisionedVal
tableName = tableNameVal
}
var tableArn: String
val response = ddb.createTable(request)
ddb.waitUntilTableExists { // suspend call
tableName = tableNameVal
}
tableArn = response.tableDescription!!.tableArn.toString()
println("Table $tableArn is ready")
However when I do this, I get an error when the createTable method is called:
java.net.UnknownHostException: Unable to resolve host "dynamodb.us-east-1.amazonaws.com": No address associated with hostname
I've tried doing a scan instead but I also get the same error. I thought that with AWS, if you provide the correct credentials and region, it wouldn't need any extra endpoints yet I'm still getting this "no hostname" error. I've looked at other code in JS with similar issues but couldn't get it working. Any help would be appreciated.

Related

Problems with AWS SDK .NET

I am trying to retrieve images from my bucket to send to my mobile apps, I currently have the devices accessing AWS directly, however I am adding a layer of security and having my apps (IOS and Android) now make requests to my server which will then respond with DynamoDB and S3 data.
I am trying to follow the documentation and code samples provided by AWS for .Net and they worked seamlessly for DynamoDB, I am running into problems with S3.
S3 .NET Documentation
My problem is that if I provide no credentials, I get the error:
Failed to retrieve credentials from EC2 Instance Metadata Service
This is expected as I have IAM roles set up and only want my apps and this server (in the future, only this server) to have access to the buckets.
But when I provide the credentials, the same way I provided credentials for DynamoDB, my server waits forever and doesn't receive any responses from AWS.
Here is my C#:
<%# WebHandler Language="C#" Class="CheckaraRequestHandler" %>
using System;
using System.Web;
using System.Collections.Generic;
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.Model;
using Amazon.DynamoDBv2.DocumentModel;
using Amazon;
using Amazon.Runtime;
using Amazon.S3;
using Amazon.S3.Model;
using System.IO;
using System.Threading.Tasks;
public class CheckaraRequestHandler : IHttpHandler
{
private const string bucketName = "MY_BUCKET_NAME";
private static readonly RegionEndpoint bucketRegion = RegionEndpoint.USEast1;
public static IAmazonS3 client = new AmazonS3Client("MY_ACCESS_KEY", "MY_SECRET_KEY", RegionEndpoint.USEast1);
public void ProcessRequest(HttpContext context)
{
if (context.Request.HttpMethod.ToString() == "GET")
{
string userID = context.Request.QueryString["User"];
string Action = context.Request.QueryString["Action"];
if (userID == null)
{
context.Response.ContentType = "text/plain";
context.Response.Write("TRY AGAIN!");
return;
}
if (Action == "GetPhoto")
{
ReadObjectDataAsync(userID).Wait();
}
var client = new AmazonDynamoDBClient("MY_ACCESS_KEY", "MY_SECRET_KEY", RegionEndpoint.USEast1);
Console.WriteLine("Getting list of tables");
var table = Table.LoadTable(client, "TABLE_NAME");
var item = table.GetItem(userID);
if (item != null)
{
context.Response.ContentType = "application/json";
context.Response.Write(item.ToJson());
}
else
{
context.Response.ContentType = "text/plain";
context.Response.Write("0");
}
}
}
public bool IsReusable
{
get
{
return false;
}
}
static async Task ReadObjectDataAsync(string userID)
{
string responseBody = "";
try
{
string formattedKey = userID + "/" + userID + "_PROFILEPHOTO.jpeg";
//string formattedKey = userID + "_PROFILEPHOTO.jpeg";
//formattedKey = formattedKey.Replace(":", "%3A");
GetObjectRequest request = new GetObjectRequest
{
BucketName = bucketName,
Key = formattedKey
};
using (GetObjectResponse response = await client.GetObjectAsync(request))
using (Stream responseStream = response.ResponseStream)
using (StreamReader reader = new StreamReader(responseStream))
{
string title = response.Metadata["x-amz-meta-title"]; // Assume you have "title" as medata added to the object.
string contentType = response.Headers["Content-Type"];
Console.WriteLine("Object metadata, Title: {0}", title);
Console.WriteLine("Content type: {0}", contentType);
responseBody = reader.ReadToEnd(); // Now you process the response body.
}
}
catch (AmazonS3Exception e)
{
Console.WriteLine("Error encountered ***. Message:'{0}' when writing an object", e.Message);
}
catch (Exception e)
{
Console.WriteLine("Unknown encountered on server. Message:'{0}' when writing an object", e.Message);
}
}
}
When I debug, this line waits forever:
using (GetObjectResponse response = await client.GetObjectAsync(request))
This is the same line that throws the credentials error when I don't provide them. Is there something that I am missing here?
Any help would be greatly appreciated.
I suspect that the AWS .NET SDK has some isses with it specifically with the async call to S3.
The async call to dynamoDB works perfect, but the S3 one hangs forever.
What fixed my problem was simply removing the async functionality (even tho in the AWS docs, the async call is supposed to be used)
Before:
using (GetObjectResponse response = await client.GetObjectAsync(request))
After:
using (GetObjectResponse response = myClient.GetObject(request))
Hopefully this helps anyone else encountering this issue.

Exception when trying to connect to AWS Athena using JAVA API

I'm trying to execute query in AWS Athena using Java API:
public class AthenaClientFactory
{
String accessKey = "access";
String secretKey = "secret";
BasicAWSCredentials awsCredentials = new
BasicAWSCredentials(accessKey, secretKey);
private final AmazonAthenaClientBuilder builder = AmazonAthenaClientBuilder.standard()
.withRegion(Regions.US_WEST_1)
.withCredentials(new AWSStaticCredentialsProvider(awsCredentials))
.withClientConfiguration(new ClientConfiguration().withClientExecutionTimeout(10));
public AmazonAthena createClient()
{
return builder.build();
}
}
private static String submitAthenaQuery(AmazonAthena client) {
QueryExecutionContext queryExecutionContext = new QueryExecutionContext().withDatabase("my_db");
ResultConfiguration resultConfiguration = new ResultConfiguration().withOutputLocation("my_bucket");
StartQueryExecutionRequest startQueryExecutionRequest = new StartQueryExecutionRequest()
.withQueryString("select * from my_db limit 3;")
.withQueryExecutionContext(queryExecutionContext)
.withResultConfiguration(resultConfiguration);
StartQueryExecutionResult startQueryExecutionResult = client.startQueryExecution(startQueryExecutionRequest);
return startQueryExecutionResult.getQueryExecutionId();
}
public void run() throws InterruptedException {
AthenaClientFactory factory = new AthenaClientFactory();
AmazonAthena client = factory.createClient();
String queryExecutionId = submitAthenaQuery(client);
}
But I get an exception from startQueryExecutionResult.
The exception is:
Client execution did not complete before the specified timeout
configuration.
Has anyone encountered something similar?
The problem was in withClientExecutionTimeout(10).
Increasing this number to 5000 solved the issue

Instance created via Service Account unable to use Google Cloud Speech API - authentication error

I followed Google's Quick-Start documentation for the Speech API to enable billing and API for an account. This account has authorized a service account to create Compute instances on its behalf. After creating an instance on the child account, hosting a binary to use the Speech API, I am unable to successfully use the example C# code provided by Google in the C# speech example:
try
{
var speech = SpeechClient.Create();
var response = speech.Recognize(new RecognitionConfig()
{
Encoding = RecognitionConfig.Types.AudioEncoding.Linear16,
LanguageCode = "en"
}, RecognitionAudio.FromFile(audioFiles[0]));
foreach (var result in response.Results)
{
foreach (var alternative in result.Alternatives)
{
Debug.WriteLine(alternative.Transcript);
}
}
} catch (Exception ex)
// ...
}
Requests fail on the SpeechClient.Create() line with the following error:
--------------------------- Grpc.Core.RpcException: Status(StatusCode=Unauthenticated, Detail="Exception occured in
metadata credentials plugin.")
at
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task
task)
at
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task
task)
at Grpc.Core.Internal.AsyncCall`2.UnaryCall(TRequest msg)
at
Grpc.Core.Calls.BlockingUnaryCall[TRequest,TResponse](CallInvocationDetails`2
call, TRequest req)
at
Grpc.Core.DefaultCallInvoker.BlockingUnaryCall[TRequest,TResponse](Method`2
method, String host, CallOptions options, TRequest request)
at
Grpc.Core.Internal.InterceptingCallInvoker.BlockingUnaryCall[TRequest,TResponse](Method`2
method, String host, CallOptions options, TRequest request)
at
Google.Cloud.Speech.V1.Speech.SpeechClient.Recognize(RecognizeRequest
request, CallOptions options)
at
Google.Api.Gax.Grpc.ApiCall.<>c__DisplayClass0_0`2.b__1(TRequest
req, CallSettings cs)
at
Google.Api.Gax.Grpc.ApiCallRetryExtensions.<>c__DisplayClass1_0`2.b__0(TRequest
request, CallSettings callSettings)
at Google.Api.Gax.Grpc.ApiCall`2.Sync(TRequest request,
CallSettings perCallCallSettings)
at
Google.Cloud.Speech.V1.SpeechClientImpl.Recognize(RecognizeRequest
request, CallSettings callSettings)
at Google.Cloud.Speech.V1.SpeechClient.Recognize(RecognitionConfig
config, RecognitionAudio audio, CallSettings callSettings)
at Rc2Solver.frmMain.RecognizeWordsGoogleSpeechApi() in
C:\Users\jorda\Google
Drive\VSProjects\Rc2Solver\Rc2Solver\frmMain.cs:line 1770
--------------------------- OK
I have verified that the Speech API is activated. Here is the scope that the service account uses when creating the Compute instances:
credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(me)
{
Scopes = new[] { ComputeService.Scope.Compute, ComputeService.Scope.CloudPlatform }
}.FromPrivateKey(yk)
);
I have found no information or code online about specifically authorizing or authenticating the Speech API for service account actors. Any help is appreciated.
It turns out the issue was that the Cloud Compute instances needed to be created with a ServiceAccount parameter specified. Otherwise the Cloud instances were not part of a ServiceAccount default credential, which is referenced by the SpeechClient.Create() call. Here is the proper way to create an instance attached to a service account, and it will use the SA tied to the project ID:
service = new ComputeService(new BaseClientService.Initializer() {
HttpClientInitializer = credential,
ApplicationName = "YourAppName"
});
string MyProjectId = "example-project-27172";
var project = await service.Projects.Get(MyProjectId).ExecuteAsync();
ServiceAccount servAcct = new ServiceAccount() {
Email = project.DefaultServiceAccount,
Scopes = new [] {
"https://www.googleapis.com/auth/cloud-platform"
}
};
Instance instance = new Instance() {
MachineType = service.BaseUri + MyProjectId + "/zones/" + targetZone + "/machineTypes/" + "g1-small",
Name = name,
Description = name,
Disks = attachedDisks,
NetworkInterfaces = networkInterfaces,
ServiceAccounts = new [] {
servAcct
},
Metadata = md
};
batchRequest.Queue < Instance > (service.Instances.Insert(instance, MyProjectId, targetZone),
(content, error, i, message) => {
if (error != null) {
AddEventMsg("Error creating instance " + name + ": " + error.ToString());
} else {
AddEventMsg("Instance " + name + " created");
}
});

Simple DB policy being ignored?

I'm trying to use AWS IAM to generate temporary tokens for a mobile app. I'm using the AWS C# SDK.
Here's my code...
The token generating service
public string GetIAMKey(string deviceId)
{
//fetch IAM key...
var credentials = new BasicAWSCredentials("MyKey", "MyAccessId");
var sts = new AmazonSecurityTokenServiceClient(credentials);
var tokenRequest = new GetFederationTokenRequest();
tokenRequest.Name = deviceId;
tokenRequest.Policy = File.ReadAllText(HostingEnvironment.MapPath("~/policy.txt"));
tokenRequest.DurationSeconds = 129600;
var tokenResult = sts.GetFederationToken(tokenRequest);
var details = new IAMDetails { SessionToken = tokenResult.GetFederationTokenResult.Credentials.SessionToken, AccessKeyId = tokenResult.GetFederationTokenResult.Credentials.AccessKeyId, SecretAccessKey = tokenResult.GetFederationTokenResult.Credentials.SecretAccessKey, };
return JsonConvert.SerializeObject(details);
}
The client
var iamkey = Storage.LoadPersistent<IAMDetails>("iamkey");
var simpleDBClient = new AmazonSimpleDBClient(iamkey.AccessKeyId, iamkey.SecretAccessKey, iamkey.SessionToken);
try
{
var details = await simpleDBClient.SelectAsync(new SelectRequest { SelectExpression = "select * from mydomain" });
return null;
}
catch (Exception ex)
{
Storage.ClearPersistent("iamkey");
}
The policy file contents
{ "Statement":[{ "Effect":"Allow", "Action":"sdb:* ", "Resource":"arn:aws:sdb:eu-west-1:* :domain/mydomain*" } ]}
I keep getting the following error...
User (arn:aws:sts::myaccountid:federated-user/654321) does not have permission to perform (sdb:Select) on resource (arn:aws:sdb:us-east-1:myaccountid:domain/mydomain)
Notice that my policy file clearly specifies two things
region should be eu-west-1
allowed action is a wild-card, ie, allow everything
But the exception thrown claims that my user doesn't have permission to us-east-1
Any ideas as to why I'm getting this error?
Ok figured it out.
You have to set the region endpoint on your call to the service from the client.
So
var simpleDBClient = new AmazonSimpleDBClient(iamkey.AccessKeyId, iamkey.SecretAccessKey, iamkey.SessionToken, Amazon.RegionEndpoint.EUWest1);

Amazon API ItemSearch returns (400) Bad Request

I'm using a simple example from Amazon documentation for ItemSearch and I get a strange error:
"The remote server returned an unexpected response: (400) Bad Request."
This is the code:
public static void Main()
{
//Remember to create an instance of the amazon service, including you Access ID.
AWSECommerceServicePortTypeClient service = new AWSECommerceServicePortTypeClient(new BasicHttpBinding(),
new EndpointAddress(
"http://webservices.amazon.com/onca/soap?Service=AWSECommerceService"));
AWSECommerceServicePortTypeClient client = new AWSECommerceServicePortTypeClient(
new BasicHttpBinding(),
new EndpointAddress("http://webservices.amazon.com/onca/soap?Service=AWSECommerceService"));
// prepare an ItemSearch request
ItemSearchRequest request = new ItemSearchRequest();
request.SearchIndex = "Books";
request.Title = "Harry+Potter";
request.ResponseGroup = new string[] { "Small" };
ItemSearch itemSearch = new ItemSearch();
itemSearch.Request = new ItemSearchRequest[] { request };
itemSearch.AWSAccessKeyId = accessKeyId;
// issue the ItemSearch request
try
{
ItemSearchResponse response = client.ItemSearch(itemSearch);
// write out the results
foreach (var item in response.Items[0].Item)
{
Console.WriteLine(item.ItemAttributes.Title);
}
}
catch(Exception e)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(e.Message);
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine("Press any key to quit...");
Clipboard.SetText(e.Message);
}
Console.ReadKey();
What is wrong?
You receive this message because your request is not signed. Starting from August 2009 all requests must be signed.
Here you can see at the example about how to sign amazon requests:
http://developer.amazonwebservices.com/connect/entry.jspa?externalID=2480&categoryID=14