Authenticating and Running an EC2 Instance: AWS - amazon-web-services

I am attempting to create an EC2 instance and then add it to my Auto Scaling group. I am having a lot of issues trying to authenticate. I am looking for a simple way to authenticate a request using my access key to simply start an instance. What I have tried so far:
//Authenticate AWS:
var myCredentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId:'us-west-2:IdentityPoolID'
});
var myConfig = new AWS.Config({
credentials: myCredentials, region: 'us-west-2'
});
AWS.config = myConfig
var minInst = 1;
var maxInst = 3;
var ec2 = new AWS.EC2();
//Set up parameters for EC2 Instances:
var params = {
ImageId: 'ami-6e1a0117',
MaxCount: minInst,
MinCount: maxInst,
InstanceInitiatedShutdownBehavior: 'terminate',
InstanceType: 't2.micro',
Monitoring: {
Enabled: false
},
NetworkInterfaces: [{
AssociatePublicIpAddress: true,
DeleteOnTermination: true,
}],
Placement: {
AvailabilityZone: 'us-west-2',
},
SecurityGroupIds: [
'sg-b0307ccd',
],
SecurityGroups: [
'CAB432Assignment2SG',
],
};
ec2.runInstances(params, function(err, data) {
if (err){
console.log(err, err.stack); //An error occurred
}
else{
console.log(data); //Successful Response
}
});
I know this code is wrong. I just don't know to fix it. The error I get is:
CredentialsError: Missing credentials in config
Any help would be greatly appreciated.

Delete this section of code entirely:
//Authenticate AWS:
var myCredentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId:'us-west-2:IdentityPoolID'
});
var myConfig = new AWS.Config({
credentials: myCredentials, region: 'us-west-2'
});
AWS.config = myConfig
Change this:
var ec2 = new AWS.EC2();
To this:
var ec2 = new AWS.EC2({region: 'us-west-2'});
Then go read this page in the Setting Credentials in Node.js documentation. In particular, you need to do one of the following:
Add an IAM role to your EC2 instance, if this is running on EC2.
Add an IAM execution role to your Lambda function if this is running on Lambda.
Create either a ~/.aws/credentials file with your keys. This can be done with the aws configure command if you have the AWS CLI installed.
Set the keys as environment variables.

Related

Could not find a value associated with JSONKey in SecretString

I want to make RDS and proxy with credential
However, I bumped into this error.
14:32:32 | CREATE_FAILED | AWS::RDS::DBCluster | DatabaseB269D8BB
Could not find a value associated with JSONKey in SecretString
My script is like this below.
const rdsCredentials: rds.Credentials = rds.Credentials.fromGeneratedSecret(dbInfos['user'],{secretName:`cdk-st-${targetEnv}-db-secret`});
const dbCluster = new rds.DatabaseCluster(this, 'Database', {
parameterGroup,
engine: rds.DatabaseClusterEngine.auroraMysql({ version: rds.AuroraMysqlEngineVersion.VER_2_08_1 }),
credentials: rdsCredentials,
cloudwatchLogsExports:['slowquery','general','error','audit'],
backup: backupProps,
instances:2,
removalPolicy: cdk.RemovalPolicy.DESTROY,
clusterIdentifier: dbInfos['cluster'], //clusterIdentifier,
defaultDatabaseName :dbInfos['database'], //defaultDatabaseName,
instanceProps: {
// optional , defaults to t3.medium
instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE2, ec2.InstanceSize.SMALL),
vpcSubnets: {
subnetType: ec2.SubnetType.PRIVATE_ISOLATED,
},
vpc,
securityGroups:[dbSecurityGroup],
},
});
const proxy = new rds.DatabaseProxy(this, 'Proxy', {
proxyTarget: rds.ProxyTarget.fromCluster(dbCluster),
secrets: [dbCluster.secret!],
vpc,
});
I guess this error is related to secrets: [dbCluster.secret!] maybe.
I googled around and found this error happens when secrets are deleted.
However I want to use credential which is just generated for RDS
Is it impossible?
how can I fix this?
More Test
I tried another way but this comes the error below
/node_modules/aws-cdk-lib/aws-rds/lib/proxy.ts:239
secret.grantRead(role);
my code is here
dbCluster.addProxy('testProxy',{
secrets: [rdsCredentials.secret!],
vpc
});

AWS SDK runinstance and IAM roles

The code below works when I have added the AWS IAM role "AdministratorAccess" - But it is risky and a bit of overkill... But how do I know and find only the necessary role(s)...It is very confusing and hard to know by when I look at all the possible roles in the console?
try {
// Load the AWS SDK for Node.js
var AWS = require('aws-sdk');
// Set the region
AWS.config.update({region: 'us-east-2'});
var instanceParams = {
ImageId: 'ami-xxxxxxxxxxxx',
InstanceType: 't2.micro',
KeyName: 'xxxxxxxxxx',
SecurityGroups: ['xxxxxxxxxxxxxxx'],
MinCount: 1,
MaxCount: 1
};
// Create a promise on an EC2 service object
var instancePromise = new AWS.EC2({apiVersion: '2016-11-15'}).runInstances(instanceParams).promise();
// Handle promise's fulfilled/rejected states
instancePromise.then(
function (data) {
console.log(data);
var instanceId = data.Instances[0].InstanceId;
console.log("Created instance", instanceId);
// Add tags to the instance
var tagParams = {
Resources: [instanceId], Tags: [
{
Key: 'Name',
Value: 'SDK Sample'
}
]
};
// Create a promise on an EC2 service object
var tagPromise = new AWS.EC2({apiVersion: '2016-11-15'}).createTags(tagParams).promise();
// Handle promise's fulfilled/rejected states
tagPromise.then(
function (data) {
console.log("Instance tagged");
}).catch(
function (err) {
console.error(err, err.stack);
});
}).catch(
function (err) {
console.error(err, err.stack);
});
}
catch(e){
wl.info('Error: ' + e);
}
Firstly you can see the api's you are calling via the sdk as a hint to what permissions you need i.e ec2:RunInstance and ec2:CreateTags.
You first create a policy then select the service then attach permissions (RunInstances and CreateTags)
You then create a Role with that policy attached.
Then you can attach the role to your Lambda

access all ec2 cross region via lambda

I have lambda function for auto Ami backup is possible to execute lambda across the region for take automatic backup of all my EC2 working on account.
One lambda function execution for all ec2 across region
var aws = require('aws-sdk');
aws.config.region = 'us-east-1','ap-south-1','eu-central-1';
var ec2 = new aws.EC2();
var now = new Date();
date = now.toISOString().substring(0, 10)
hours = now.getHours()
minutes = now.getMinutes()
exports.handler = function(event, context) {
var instanceparams = {
Filters: [{
Name: 'tag:Backup',
Values: [
'yes'
]
}]
}
ec2.describeInstances(instanceparams, function(err, data) {
if (err) console.log(err, err.stack);
else {
for (var i in data.Reservations) {
for (var j in data.Reservations[i].Instances) {
instanceid = data.Reservations[i].Instances[j].InstanceId;
nametag = data.Reservations[i].Instances[j].Tags
for (var k in data.Reservations[i].Instances[j].Tags) {
if (data.Reservations[i].Instances[j].Tags[k].Key == 'Name') {
name = data.Reservations[i].Instances[j].Tags[k].Value;
}
}
console.log("Creating AMIs of the Instance: ", name);
var imageparams = {
InstanceId: instanceid,
Name: name + "_" + date + "_" + hours + "-" + minutes,
NoReboot: true
}
ec2.createImage(imageparams, function(err, data) {
if (err) console.log(err, err.stack);
else {
image = data.ImageId;
console.log(image);
var tagparams = {
Resources: [image],
Tags: [{
Key: 'DeleteOn',
Value: 'yes'
}]
};
ec2.createTags(tagparams, function(err, data) {
if (err) console.log(err, err.stack);
else console.log("Tags added to the created AMIs");
});
}
});
}
}
}
});
}
where aws.config.region is for region config..it's working for current(in which lambda deploy) region
This line:
var ec2 = new aws.EC2();
connects to the Amazon EC2 service in the region where the Lambda function is running.
You can modify it to connect to another region:
var ec2 = new AWS.EC2({apiVersion: '2006-03-01', region: 'us-west-2'});
Thus, your program could loop through a list of regions (from ec2.describeRegions), creating a new EC2 client for the given region, then running the code you already have.
See: Setting the AWS Region - AWS SDK for JavaScript
In your Lambda Role, you need to add a policy which gives the Lambda function necessary permissions to access the EC2 on different accounts, typically you can add ARN's of EC2 instances you wan't access to or you can specify "*" which gives permissions to all instances.
Also on other accounts where EC2 instances are running you need to add IAM policy which gives access to your Lambda Role, note that you need to provide Lambda role ARN,
In this way your Lambda role will have policy to access EC2 and cross account EC2 will have policy which grant's access to Lambda role.
Without this in place you might need to do heavy lifting of configuring IP's of each EC2 in each account.
Yes and you also need to point EC2 object to a region where the instance is running,
Any code (including a Lambda function) can create a client that connects to a different region.

AWS DynamoDB: "Error: Missing region in config" - even with 'config.region' returning 'eu-west-1'

While following the AWS docs for setting up DynamoDB in my front end project, with settings taken from the docs the API throws:
Error: Missing region in config
at constructor.<anonymous> (aws-sdk-2.129.0.min.js:42)
at constructor.callListeners (aws-sdk-2.129.0.min.js:44)
at i (aws-sdk-2.129.0.min.js:44)
at aws-sdk-2.129.0.min.js:42
at t (aws-sdk-2.129.0.min.js:41)
at constructor.getCredentials (aws-sdk-2.129.0.min.js:41)
at constructor.<anonymous> (aws-sdk-2.129.0.min.js:42)
at constructor.callListeners (aws-sdk-2.129.0.min.js:44)
at constructor.emit (aws-sdk-2.129.0.min.js:44)
at constructor.emitEvent (aws-sdk-2.129.0.min.js:43)
My settings:
<script src="https://sdk.amazonaws.com/js/aws-sdk-2.129.0.min.js"></script>
<script>
var myCredentials = new AWS.CognitoIdentityCredentials({IdentityPoolId:'eu-west-1_XXXXXX'});
var myConfig = new AWS.Config({
credentials: myCredentials, region: 'eu-west-1',
});
console.log(myConfig.region); //logs 'eu-west-1'
var dynamodb = new AWS.DynamoDB({apiVersion: '2012-08-10'});
dynamodb.listTables({Limit: 10}, function(err, data) {
if (err) {
console.log(err);
} else {
console.log("Table names are ", data.TableNames);
}
});
</script>
What am I missing?
Looks like you’re newing up AWS.config.
Change the line
var myConfig = new AWS.Config({
credentials: myCredentials, region: 'eu-west-1',
});
to
AWS.config.update({
credentials: myCredentials, region: 'eu-west-1',
}});
Reference:
http://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/setting-region.html
Hope it helps.
For others hitting the same issue, where the docs mention:
If you have not yet created one, create an identity pool...
and you got forwarded to the Amazon Cognito service, choose the Manage Federal Identities not the Manage User Pools option.

How to pass script to UserData field in EC2 creation on AWS Lambda?

I'm trying to pass a script in Userdata field of a new EC2 instance created by an AWS Lambda (using AWS SDK for Javascript, Node.js 6.10):
...
var paramsEC2 = {
ImageId: 'ami-28c90151',
InstanceType: 't1.micro',
KeyName: 'myawesomekwy',
MinCount: 1,
MaxCount: 1,
SecurityGroups: [groupname],
UserData:'#!/bin/sh \n echo "Hello Lambda"'
};
// Create the instance
ec2.runInstances(paramsEC2, function(err, data) {
if (err) {
console.log("Could not create instance", err);
return;
}
var instanceId = data.Instances[0].InstanceId;
console.log("Created instance", instanceId);
// Add tags to the instance
params = {Resources: [instanceId], Tags: [
{
Key: 'Name',
Value: 'taggggg'
}
]};
ec2.createTags(params, function(err) {
console.log("Tagging instance", err ? "failure" : "success");
});
});
...
I tried several things like:
- create a string and pass the string to the UserData - not working
- create a string and encode it to base64 and pass the string to the UserData - not working
- paste base64 encoded string - not working
Could you help me understanding how to pass a script in the UserData? The AWS SDK documentation is a bit lacking.
Is it also possible to pass a script put in an S3 bucket to the UserData?
Firstly, base64 encoding is required in your example. Although the docs state that this is done for you automatically, I always need it in my lambda functions creating ec2 instances with user data. Secondly, as of ES6, multi-line strings can make your life easier as long as you add scripts within your lambda function.
So try the following:
var userData= `#!/bin/bash
echo "Hello World"
touch /tmp/hello.txt
`
var userDataEncoded = new Buffer(userData).toString('base64');
var paramsEC2 = {
ImageId: 'ami-28c90151',
InstanceType: 't1.micro',
KeyName: 'AWSKey3',
MinCount: 1,
MaxCount: 1,
SecurityGroups: [groupname],
UserData: userDataEncoded
};
// Create the instance
// ...