Automatically rotate AppSync API key - aws-cloudformation

CloudFormation provides an AWS::AppSync::ApiKey resource type for creating an AppSync API key in a CloudFormation stack. The API key will expire. Is there a simple way to define a rotation schedule within CloudFormation? I don't see anything, but it seems like such an obvious use case that I'm not sure what good the AWS::AppSync::ApiKey resource type is without it.
Currently I have a lambda that runs on a schedule to generate a new key and store it in SecretsManager. This works, but it's an extra step, and I have to run the lambda manually the first time. I am open to alternatives.

You don’t want to create an AWS::AppSync::ApiKey. Instead make a AWS::SecretsManager::Secret and a AWS::SecretsManager::RotationSchedule. The RotationSchedule will let you use a lambda to automatically rotate the ApiKey and store it in the Secret.
Ultimately, the AWS::AppSync::ApiKey is of little practical use for you because you will need to deal with the expiration.

Related

Ansible: Check (GET) before Applying (POST/PUT) if applying is idempotent

I am writing roles in ansible, which use the ansible.builtin.uri method to do my bidding against the api of the service.
As I don't want to POST/PUT every time I run the Playbook, I check if the item I want to create already exists.
Does this make sense? In the end I introduce an extra step to GET the status, to skip the POST/PUT, where the POST/PUT itself would simply set what I want in the end.
For example, I wrote an Ansible Role which gives a User a role in Nexus.
Every time I run the Role, it first checks if the User already has the role and if not, it provides it.
If I don't check before and the User would already have the Role, it would simply apply it again.
But as I would like to know exactly whats going to happen, I believe it is better to explicitly check before applying.
What is the best practice for my scenario and are there any reasons against checking before or directly applying the changes?

Using Mirth Connect Destination Mappings for AWS Access Key Id results in Error

We use vault to store our credentials, I've successfully grabbed S3 Access key ID and Secret Access key using the vault API, and used channelMap.put to create mappings: ${access_key} and ${secret_key}.
aws_s3_file_writer
However when I use these in the S3 file writer I get the error:
"The AWS Access Key Id you provided does not exist in our records."
I know the Access Key Id is valid, it works if I plug it in directly in the S3 file writer destination.
I'd appreciate any help on this. thank you.
UPDATE: I had to convert the results to a string, that fixed it.
You can try using the variable to a higher map. You can use globalChannelMap, globalMap or configurationMap. I would use this last one since it can store password not in plain text mode. You are currently using a channelMap, it scope is only applied to the current message while it is traveling through the channel.
You can check more about variable maps and their scopes in Mirth User guide, Section Variable Maps, page 393. I think that part of the manual is really important to understand.
See my comment, it was a race condition between Vault, Mirth and AWS.

Best Practice for Operators to Receive Secrets in custom resource

I'm not finding any answers to this on Google but I may just not know what terms to search for.
In a CRD, is there a way to define a field in the spec that is a secret (and therefore shouldn't be stored in plain text)? For example, if the custom resource needs to have an API token included in it, how do you define that in the CRD?
One thought I had was to just have the user create a Secret outside of the CRD and then provide the secret's name in a custom resource field so the operator can query it from the K8s API on demand when needed (and obviously associated RBAC needs to be configured so the operator has read access to the Secret). So the field in the CRD would just be a normal string that is the name of the target Secret.
But is there a better way? Any existing best practices around this?
You do indeed just store the value in an actual Secret and reference it. You'll find the same pattern all over k8s. Then in your controller code you get your custom object, find the ref, get that secret, and then you have your data.

Dynamically generate cloudformation resources using CDK

I'm trying to dynamically generate SNS subscriptions in CDK based on what we have in mappings. What's the best way to do this here? I have mappings that essentially maps the SNS topic ARNs my queue want to subscribe to in each region/stage. The mapping looks something like this:
"Mappings":
"SomeArnMap":
"eu-west-1":
"beta":
- "arn:aws:sns:us-west-2:0123456789:topic1"
"gamma":
- "arn:aws:sns:us-west-2:0123456789:topic2"
- "arn:aws:sns:us-west-2:0123456789:topic3"
How do I write code in CDK that creates a subscription for each element in the list here? I can't get regular loop to work because we don't know the size of the list until deployment. After CDK synth, it would just give me tokens like #{Token[TOKEN.264]} for my topic ARN.
Is it even doable in CDK/CloudFormation? Thanks.
Since tokens aren't resolved during the runtime of aws-cdk code, usually you can use cfn intrinsic functions which declare some sort operation on the token in your template. These are accessible in #aws-cdk/core.fn. However, cfn doesn't have intrinsics for looping over values, only selecting values from a list/map.
If your cdk has these mappings in its output template and you just want to extract a value for reference when building another construct Fn.findInMap I believe should do that.
const importedTopic = Sns.Topic.fromTopicArn(this, "ImportedTopicId", Fn.findInMap("SomeArnMap", "eu-west-1", "beta"));
importedTopic.addSubscription(SomeSqsQueueOrSomething);

NDB urlsafe keys and REST api requests

I was wondering what others are doing to expose REST api endpoints with the datastore (using app engine standard). I want to use urlsafe keys but 1 - I'd rather not pass this data directly as it poses a security risk since app-engine to app-engine calls are exposed over a public ip, and 2 - the keys that are generated are very long and would not be great when multiple need to be passed as a query parameter to form a get request (and would probably exceed browser character limits).
I was thinking maybe using compression of some sort to compress the urlsafe keys which would solve both 1 and 2, but want to see if there is a better way to create REST endpoints. Or if some type of compression method is already baked into ndb?
Google uses HTTPS internally so I'm not sure you need to worry about it.
Also, you should probably design your app so that keys are not secret info and such that it is safe to expose them.
I use key IDs for my REST calls, which I believe are 12 digit numbers. That works as long as you know the entity type. If you need to specify the entity type, you could add another parameter to your API call.