Region isn't specified and can't be deduced from endpoint - amazon-web-services

I am getting issues when I implemented Custom Domain on AWS API and generated Android SDK ... now when I make authenticated calls to my API - SDK shows a error as follows:
Region isn't specified and can't be deduced from endpoint
What shall I do to remove this issue. I am sure its due to the custom domain implementation - because if I remove the custom domain mapping and then generate SDK - all calls are work again.

Since you use a custom domain the region isn't part of the endpoint, therefore you have to provide the region to the ApiClientFactory explicitly.
Something like:
ApiClientFactory f = new ApiClientFactory()
.credentialsProvider(credentialsProvider)
.region("us-east-1") // or whatever region you have :)
.endpoint("https://myendpoint");

Related

AWS: KMSClient vs KMSClientBuilder

In the AWS SDK https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/kms/package-summary.html the KMS has two different types of clients. A regular client and a client builder. What is the purpose of them both? When do you choose one over the other?
I'm trying to implement envelope encryption using KMS. I want to be able to hit the KMS endpoint and encrypt the payload. Which client library should I be using?
There is only one client type: KmsClient.
It can be created in 2 ways:
Using the KmsClientBuilder returned by KmsClient.builder() to modify properties and ultimately do .Build for your customised version of the client - this KmsClientBuilder is an instance of DefaultKmsClientBuilder, which is currently the only class that implements the client builder interface.
Using the KmsClient returned by KmsClient.create(), which is exactly the equivalent (and a shortcut) to new DefaultKmsClientBuilder().build() - this method returns a client set up with the region & credentials already loaded from the respective default provider chain, for applications that don't require further customisation.
This is how the above looks like in code:
final KmsClient defaultKmsClient = KmsClient.create();
final KmsClient alsoDefaultKmsClientButLonger = KmsClient.builder().build();
final KmsClient customisedKmsClient = KmsClient.builder()
.region(...)
.credentialsProvider(...)
.httpClient(...)
.endpointOverride(...)
...
In conclusion, use KmsClient.create() if you do not require a particular configuration, as the default region and creds should be sufficient in most cases.
If not, then customise it via an instance of the builder (which can only be accessed via the KmsClient.builder() method since KmsClientBuilder is an interface).
They are not 'different'.
The builder ultimately is what creates the client.

FHIR works on AWS server not allowing to keep customized id as primary key

We are working for FHIR(Fast Healthcare Interoperability Resources).
We have followed “FHIR works on AWS” and deployed the CloudFormation template given by AWS in our AWS environment.Following is the template that we have deployed
https://docs.aws.amazon.com/solutions/latest/fhir-works-on-aws/aws-cloudformation-template.html
Requirement : we want to maintain client specific/customized ids as primary key in the server.
Problem : server not allowing us to override or mainain client specific (customized ) ids as primary key .Infact , in the runtime, it is generating its own ids and ignoring the id given by us.
The FHIR spec allows for you to define your own IDs when using "update as create". This is when you create a new resource in the server, but use a PUT (update) request to the ID you want to create, such as Patient/1, instead of a POST (create) request to the resource URL. The server should return a 201 Created status instead of 200 OK. For more information see https://hl7.org/fhir/http.html#upsert
Not every FHIR server supports this, but if AWS does this is likely how it would work. The field in the CapabilityStatement for this feature is CapabilityStatement.rest.resource.updateCreate
EDIT:
This is possible by modifying the parameters passed to the DynamoDbDataService constructor in the deployment repo's src/config.ts
By default supportUpdateCreate, the second parameter, is set to false
const dynamoDbDataService = new DynamoDbDataService(DynamoDb, false, { enableMultiTenancy });
but you can set it to true to enable this functionality
const dynamoDbDataService = new DynamoDbDataService(DynamoDb, true, { enableMultiTenancy });

Cross-Account Lambdas to API Gateway Setup

So the scenario is we have 3 different accounts(EDGE, PROD, DEV). I want to create some APIs in EDGE account and integrate them with lambdas in DEV and PROD Account respectively.
I have 2 different stages of API : dev/prod and also have defined integration of API : LAMBDA with target = ${stageVariables.LAMBDA}.
When I mention the full ARN of LAMBDA in stage variables it shows the following error after api hit:
{
"message": "1 validation error detected: Value \'arn:aws:lambda:ap-south-1:XXEDGEACCOUNTXX:function:arn:aws:lambda:ap-south-1:XXDEVACCOUNTXX:function:funcName\' at \'functionName\' failed to satisfy constraint: Member must satisfy regular expression pattern: (arn:(aws[a-zA-Z-]*)?:lambda:)?([a-z]{2}((-gov)|(-iso(b?)))?-[a-z]+-\\d{1}:)?(\\d{12}:)?(function:)?([a-zA-Z0-9-_\\.]+)(:(\\$LATEST|[a-zA-Z0-9-_]+))?"
}
with
target = arn:aws:lambda:ap-south-1:${stageVariables.ACC}:function:${stageVariables.LAMBDA}/invocations
I get error of invalid function ARN or URI while saving it..
Please help.
PS. Permissions policy are attached perfectly fine. Issue is API gateway check Lambda in own account only that's why read only function name and keep account number fixed.
There is a mistake in the below statement
target = arn:aws:lambda:ap-south-1:${stageVariables.ACC}:function:${stageVariables.LAMBDA}/invocations
${stageVariables.LAMBDA} in the above statement is getting resolved to the lambda function arn. Hence there is a validation error.
arn:aws:lambda:ap-south-1:XXEDGEACCOUNTXX:function:arn:aws:lambda:ap-south-1:XXDEVACCOUNTXX:function:funcName
Also, noticed that the target arn your building is incorrect and should be of the below form
A stage variable can be used in place of a Lambda function name, or version/alias, as shown in the following examples.
arn:aws:apigateway:<region>:lambda:path/2015-03-31/functions/arn:aws:lambda:<region>:<account_id>:function:${stageVariables.<function_variable_name>}/invocations
arn:aws:apigateway:<region>:lambda:path/2015-03-31/functions/arn:aws:lambda:<region>:<account_id>:function:<function_name>:${stageVariables.<version_variable_name>}/invocations
For more information can go through this link
https://docs.aws.amazon.com/apigateway/latest/developerguide/aws-api-gateway-stage-variables-reference.html

Amazon Lambda - Alias specific environment variables

I am using AWS Lambda and can use Alias feature to point to multiple code promotion stages that we have (e.g. dev, qa, prod etc). I have setup the alias the same name as stages. Most of these functions gets triggered from S3 or SNS which has a different instance for each stage.
How can I setup a alias based environment variable so the function can get the specific info. The env vars setup in the base function(typically dev) gets carried over to all alias which does not work for deployment.
I know how to use stage variables in API gateway but the current use is not via gateway.
I don't believe there is a way to achieve what you are trying to. You would need to publish three versions of your Lambda function each with the correct environment variables and point each of your aliases to the correct version of the function.
You could use the description fields to help describe the versions before you point the aliases to them too, to make the changes more understandable.
I also find it interesting this isn't part of the plan for aliases, however you do have the context available in your code - Context.InvokedFunctionArn
I think the MINDSET is that you may call, for example, a S3 bucket and have a prefix of TEST or DEV or PROD (based on context InvokedFunctionArn you know which alias). Given this context and security based on the ARN you can use bucket policy / IAM to restrict your TEST ARN can only reach TEST s3 prefix files. That solves security between environments.
NOTE: I disagree with this model and think environment variables should be in he aliases, and if not specified in the alias fall back to what is in the version.
Although this works, the complexity around extra conditions on prefix, etc. is something many times will be misconfigured - Having a separate bucket seems much safer and matches the Serverless Application Model documentation better.
EDIT I'll leave this answer here as it may help some people but note that I found AspNetCoreStartupMode.FirstRequest caused longer cold starts by a few seconds.
I added some code to the LambdaEntryPoint to get the alias at Startup which means you can use it to load environment specific config:
public class LambdaEntryPoint : Amazon.Lambda.AspNetCoreServer.APIGatewayProxyFunction
{
private ILambdaContext LambdaContext;
public LambdaEntryPoint()
: base(AspNetCoreStartupMode.FirstRequest)
{
}
[LambdaSerializer(typeof(Amazon.Lambda.Serialization.Json.JsonSerializer))]
public override async Task<APIGatewayProxyResponse> FunctionHandlerAsync(APIGatewayProxyRequest request, ILambdaContext lambdaContext)
{
LambdaContext = lambdaContext;
return await base.FunctionHandlerAsync(request, lambdaContext);
}
protected override void Init(IWebHostBuilder builder)
{
var alias = LambdaContext?.InvokedFunctionArn.Substring(LambdaContext.InvokedFunctionArn.LastIndexOf(":") + 1);
// Do stuff based on the environment
builder
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.AddJsonFile($"appsettings.{alias}.json", optional: true, reloadOnChange: true);
})
.UseStartup<Startup>();
}
}
I've added a gist here: https://gist.github.com/secretorange/710375bc62bbc1f32e05822f55d4e8d3
The lambda context has invoked_function_arn – The Amazon Resource Name (ARN) that's used to invoke the function. Indicates if the invoker specified a version number or alias.
You can then use the alias to find the variables via Systems Manager parameter store, instead of environment variables.

Amazon Web Services - CreateDBSnapshot

I am completely new to Amazon Web Services, however, I did get an account and I am able to browse our list of servers. I am trying to create a database backup programmatically using .NET. I have installed AWS for .NET and I have built and run the sample Empty console program.
I can see that I can create an instance of the RDS service with the following line:
AmazonRDS rds = AWSClientFactory.CreateAmazonRDSClient(RegionEndPoint.USEast1);
However, I notice that the rds.CreateDBSnapshot(); needs a request object but I don't see anything like CreateDBSnapshotRequest in the reference .dll, can anyone help with a working example?
Like you said CreateDBSnapshotRequest is the parameter you have to pass to this function.
CreateDBSnapshotRequest is defined in the Amazon.RDS.Model namespace within the AWSSDK.dll assembly (version 1.5.25.0)
Within CreateDBSnapshotRequest you must pass the the DB Instance Identifier (for example mydbinstance-1), that you defined when you invoked the CreateDBInstance (or one of it's related methods) and the identifier for the snapshot you wish to generate (example: my-snapshot-id) for this DB Instance.
edit / example
Well there are a couple ways to achieve this, here's one example - hope it clears up your doubts
using Amazon.RDS;
using Amazon.RDS.Model;
...
...
//gets the credentials from the default configuration
AmazonRDS rdsClient = AWSClientFactory.CreateAmazonRDSClient();
CreateDBSnapshotRequest dbSnapshotRequest = new CreateDBSnapshotRequest();
dbSnapshotRequest.DBInstanceIdentifier = "my-oracle-instance";
dbSnapshotRequest.DBSnapshotIdentifier = "daily-snapshot";
rdsClient.CreateDBSnapshot(dbSnapshotRequest);
Dont't forget that the DB Instance (in the example my-oracle-instance) must exist (duh :) and must be in the available state, like this: