I've started an EC2 instance and installed the ec2-api-tools. Environment variables (JAVA_HOME, EC2_PRIVATE_KEY, EC2_CERT) are set up.
Running ec2-describe-instances doesn't return anything. According to the EC2 command line reference information on all currently running (and terminated) instances should be returned. What's going wrong?
In general ec2-describe-images -o self -o amazon works, so the EC2 tools are working. Adding explicitly -K and -C parameters to ec2-describe-instances doesn't change the situation.
A little more detail:
You don't need to set the EC2_URL directly. You can use the more friendly command-line option:
--region eu-west-1
(substituting the name of the region you want to address).
This way you don't need to look up the region's URL endpoint.
Here are the EC2 Command Line API Tools general options where this is explained.
if all your instances are in eu-west-1, configure your aws cli to use this region by default.
just type : aws configure
and you ll be prompted to enter your credential, then you can rewrite the region
Related
I have a string parameter for AWS SSM CLI command that looks like a path to a file due to starting with a /. /path/to/my/param.
When I run the command on git bash it tries to find the file instead, no matter how I try to escape it:
aws ssm get-parameter --name "/path/to/my/param"
aws ssm get-parameter --name '/path/to/my/param'
aws ssm get-parameter --name '\/path\/to\/my\/param'
An error occurred (ValidationException) when calling the GetParameter operation: Invalid label format /Program Files/Git/path/to/my/param. A label name can't be prefixed with numbers, "ssm", or "aws" (case-insensitive). You can specify letters, numbers, and the following symbols: period (.), dash (-), or underscore (_).
Even tried back-ticks, then I get a bash error
aws ssm get-parameter --name `/path/to/my/param`
Error: bash: /path/to/my/param: No such file or directory
If I do echo /asd/asd it actually outputs /asd/asd, so it also might be how the aws cli is treating the input.
Any ideas how to escape it?
It is possible to turn off a path conversion in MSYS2 for selected paths (see Msys2 Porting, Filesystem namespaces section).
You can also disable it temporarily in the following way:
MSYS2_ARG_CONV_EXCL="/aws" aws ssm get-parameter --name '/aws/path/to/my/param'
Edit:
After stumbling upon this issue once more, but this time for: aws logs describe-log-groups --log-group-name-prefix ..., I decided to try 'n' find a more sustainable solution.
I found an SO post that provided an explanation for the underlying problem as well as what I believe to be a better fix, i.e.:
MSYS_NO_PATHCONV=1 aws ...
This goes for any aws cli command suffering from this forward slash problem when being called from Git Bash on Windows.
Kudos of course go to: https://stackoverflow.com/a/56034540
Seems like my first answer happens to work for aws ssm get-parameter because that part of the cli is a bit more forgiving in the sense that it returns the desired value, even when providing the leading space. However, upon further scrutiny of the returned value I noticed in retrospect that the name of the returned parameter also contains the leading space, making the solution of disabling path conversion - by far - the better option.
Original answer:
In case anyone bumps into this issue in the future:
I randomly managed to solve it while grasping at straws.
The trick for me was to put a space before the first forward slash after surrounding the parameter name with double quotes, i.e.:
aws ssm get-parameter --name " /path/to/my/param"
(The GitHub issue that led me to try it out: https://github.com/bmatzelle/gow/issues/196)
I have an EC2 ASG on AWS and I'm interested in storing the shell script that's used to instantiate any given instance in an S3 bucket and have it downloaded and run upon instantiation, but it all feels a little rickety even though I'm using an IAM Instance Role, transferring via HTTPS, and encrypting the script itself while at rest in the S3 bucket using KMS using S3 Server Side Encryption (because the KMS method was throwing an 'Unknown' error).
The Setup
Created an IAM Instance Role that gets assigned to any instance in my ASG upon instantiation, resulting in my AWS creds being baked into the instance as ENV vars
Uploaded and encrypted my Instance-Init.sh script to S3 resulting in a private endpoint like so : https://s3.amazonaws.com/super-secret-bucket/Instance-Init.sh
In The User-Data Field
I input the following into the User Data field when creating the Launch Configuration I want my ASG to use:
#!/bin/bash
apt-get update
apt-get -y install python-pip
apt-get -y install awscli
cd /home/ubuntu
aws s3 cp s3://super-secret-bucket/Instance-Init.sh . --region us-east-1
chmod +x Instance-Init.sh
. Instance-Init.sh
shred -u -z -n 27 Instance-Init.sh
The above does the following:
Updates package lists
Installs Python (required to run aws-cli)
Installs aws-cli
Changes to the /home/ubuntu user directory
Uses the aws-cli to download the Instance-Init.sh file from S3. Due to the IAM Role assigned to my instance, my AWS creds are automagically discovered by aws-cli. The IAM Role also grants my instance the permissions necessary to decrypt the file.
Makes it executable
Runs the script
Deletes the script after it's completed.
The Instance-Init.sh Script
The script itself will do stuff like setting env vars and docker run the containers that I need deployed on my instance. Kinda like so:
#!/bin/bash
export MONGO_USER='MyMongoUserName'
export MONGO_PASS='Top-Secret-Dont-Tell-Anyone'
docker login -u <username> -p <password> -e <email>
docker run - e MONGO_USER=${MONGO_USER} -e MONGO_PASS=${MONGO_PASS} --name MyContainerName quay.io/myQuayNameSpace/MyAppName:latest
Very Handy
This creates a very handy way to update User-Data scripts without the need to create a new Launch Config every time you need to make a minor change. And it does a great job of getting env vars out of your codebase and into a narrow, controllable space (the Instance-Init.sh script itself).
But it all feels a little insecure. The idea of putting my master DB creds into a file on S3 is unsettling to say the least.
The Questions
Is this a common practice or am I dreaming up a bad idea here?
Does the fact that the file is downloaded and stored (albeit briefly) on the fresh instance constitute a vulnerability at all?
Is there a better method for deleting the file in a more secure way?
Does it even matter whether the file is deleted after it's run? Considering the secrets are being transferred to env vars it almost seems redundant to delete the Instance-Init.sh file.
Is there something that I'm missing in my nascent days of ops?
Thanks for any help in advance.
What you are describing is almost exactly what we are using to instantiate Docker containers from our registry (we now use v2 self-hosted/private, s3-backed docker-registry instead of Quay) into production. FWIW, I had the same "this feels rickety" feeling that you describe when first treading this path, but after almost a year now of doing it -- and compared to the alternative of storing this sensitive configuration data in a repo or baked into the image -- I'm confident it's one of the better ways of handling this data. Now, that being said, we are currently looking at using Hashicorp's new Vault software for deploying configuration secrets to replace this "shared" encrypted secret shell script container (say that five times fast). We are thinking that Vault will be the equivalent of outsourcing crypto to the open source community (where it belongs), but for configuration storage.
In fewer words, we haven't run across many problems with a very similar situation we've been using for about a year, but we are now looking at using an external open source project (Hashicorp's Vault) to replace our homegrown method. Good luck!
An alternative to Vault is to use credstash, which leverages AWS KMS and DynamoDB to achieve a similar goal.
I actually use credstash to dynamically import sensitive configuration data at container startup via a simple entrypoint script - this way the sensitive data is not exposed via docker inspect or in docker logs etc.
Here's a sample entrypoint script (for a Python application) - the beauty here is you can still pass in credentials via environment variables for non-AWS/dev environments.
#!/bin/bash
set -e
# Activate virtual environment
. /app/venv/bin/activate
# Pull sensitive credentials from AWS credstash if CREDENTIAL_STORE is set with a little help from jq
# AWS_DEFAULT_REGION must also be set
# Note values are Base64 encoded in this example
if [[ -n $CREDENTIAL_STORE ]]; then
items=$(credstash -t $CREDENTIAL_STORE getall -f json | jq 'to_entries | .[]' -r)
keys=$(echo $items | jq .key -r)
for key in $keys
do
export $key=$(echo $items | jq 'select(.key=="'$key'") | .value' -r | base64 --decode)
done
fi
exec $#
I'm trying to set up a means to register an instance in route53 automatically when the instance is created, using salt and this article.
The article uses ec2-metadata to get the instance-id and and the hostname. I'm wondering if there is a way, using bash within the instance, to get the instance Name instead. ec2-metadata only seems to show the instance-id. Thanks in advance.
First, you need to get the instance-id.
AWS_INSTANCE_ID=`curl -s http://169.254.169.254/latest/meta-data/instance-id`
Than you can get the ec2 instance name using below command.
EC2_NAME=$(aws ec2 describe-tags --region $REGION --filters "Name=resource-id,Values=$AWS_INSTANCE_ID" "Name=key,Values=Name" --output text | cut -f5)
Please ensure that you have AWS Cli Installed.
I hope this helps.
Thanks!
First and foremost, the Amazon EC2 Instance Metadata Service also provides quite some other Names besides the instance-id, if these might be what you are looking for - see Instance Metadata Categories:
hostname - The private hostname of the instance. In cases where multiple network interfaces are present, this refers to the eth0 device (the device for which the device number is 0).
local-hostname - The private DNS hostname of the instance. In cases where multiple network interfaces are present, this refers to the eth0 device (the device for which the device number is 0).
public-hostname - The instance's public DNS. If the instance is in a VPC, this category is only returned if the enableDnsHostnames attribute is set to true.
If you are looking for the Name as exposed in the AWS Management Console though, you would indeed need to resort to using one of the Tools for Amazon Web Services to retrieve it - that Name is in fact just a regular tag with the key Name (see Tagging Your Amazon EC2 Resources), which happens to be used across most AWS services for the obvious purpose.
Here's how to get it with the AWS Command Line Interface for example (skipping region and credentials):
aws ec2 describe-tags \
--filters Name=resource-id,Values=i-abcd1234 Name=key,Values=Name \
--query Tags[].Value --output text
For more advanced CLI JSON output processing than what's possible with the built in --query option, you could resort to jq (a lightweight and flexible command-line JSON processor).
Overthink's answer provides an example based on the now legacy Amazon EC2 API Tools (please note the comments, which correctly point out that you'd nowadays deal with credentials differently, see Tell the CLI Tools Who You Are and IAM Roles for EC2 instances for details).
Not sure what it would look like with bash, but you could use an SDK from the instance itself if you can get the instance id. You would query the ec2 recourse and pass in the ec2 instance id. Using the ruby sdk it would look like:
i = ec2.instances["i-12345678"]
puts i.dns_name
Found that describe-tags not working in my config, failed with 'UnauthorizedOperation' error. Got this working with describe-instances:
aws ec2 describe-instances --filters Name=instance-id,Values=$(wget -qO- http://instance-data/latest/meta-data/instance-id) --query Reservations[].Instances[].Tags[].Value --output text
Command using region and access keys from current user's aws config file's [default] section: ~/.aws/config . If need to use another user's region/keys (can be found at AWS console's IAM dashboard), you can add them to another section in that file, for example [user2] and use in command like this:
aws --profile user2 ec2 describe-instances --filters Name=instance-id,Values=$(wget -qO- http://instance-data/latest/meta-data/instance-id) --query Reservations[].Instances[].Tags[].Value --output text
Use this command to show which metadata is available
TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"` \
&& curl -H "X-aws-ec2-metadata-token: $TOKEN" -v http://169.254.169.254/latest/meta-data/
You can chain any one of the below file/folders to display the required info
ami-id
ami-launch-index
ami-manifest-path
block-device-mapping/
events/
hostname
iam/
identity-credentials/
instance-action
instance-id
instance-life-cycle
instance-type
local-hostname
local-ipv4
mac
metrics/
network/
placement/
profile
public-keys/
reservation-id
For eg. instance-type can be chained this to the above command as follows:
TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"` \
&& curl -H "X-aws-ec2-metadata-token: $TOKEN" -v http://169.254.169.254/latest/meta-data/instance-type
Reference from AWS
ec2metadata tool is useful to get information about the EC2 server.
You can use the following;
ec2metadata --instance-id
in bash;
INSTANCE_ID=$(ec2metadata --instance-id)
You can also access other useful information like the following;
--ami-id
--ami-launch-index
--ami-manifest-path
--ancestor-ami-ids
--availability-zone
--block-device-mapping
--instance-action
--instance-id
--instance-type
--local-hostname
--local-ipv4
--kernel-id
--mac
--profile
--product-codes
--public-hostname
--public-ipv4
--public-keys
--ramdisk-id
--reserveration-id
--security-groups
I am trying to launch an instance on Amazon EC2. I have researched this problem extensively, but I have not found any helpful information.
When I run the command hadoop-ec2 launch-cluster mycluster 2, I receive the following error message:
Starting master with AMI.
Required parameter 'AMI' missing (-h for usage)
I have entered my AWS key, AWS secret key, AWS key pairs, etc. I am using hadoop-1.0.4. I am using the default S3 bucket (hadoop-images), but I have tried many other AMIs and I always get the same error message.
Has anybody experience this problem before?
The basic issue is that the search for images the launch-hadoop-master script performs is not returning any results. The most likely cause of this due to the different AMIs that are available in different regions (but it could be due to any changes you've made to S3_BUCKET and HADOOP_VERSION in hadoop-ec2-env.sh).
From the launch-hadoop-master script:
# Finding Hadoop image
AMI_IMAGE=`ec2-describe-images -a | grep $S3_BUCKET
| grep $HADOOP_VERSION
| grep $ARCH
| grep available
| awk '{print $2}'`
# Start a master
echo "Starting master with AMI $AMI_IMAGE"
So, it appears that AMI_IMAGE is not being set to a valid image and thus the search for AMIs that match the various grep filters is failing (the defaults for the Hadoop 1.0.4 distribution are S3_BUCKET is hadoop-images, HADOOP_VERSION is 0.19.0 and ARCH is x86 if you're using m1.small instances). If you search the public AMIs in the US-West-2 region, you'll see that there aren't many Hadoop images, but if you search the public AMIs in the US-East-1 region, you'll see that there are quite a few. Thus, one way around this issue is to work in the US-East-1 region (this is simplest) or, alternatively, set EC2_URL in your login script via export EC2_URL=https://ec2.us-east-1.amazonaws.com but now you need make sure you put your keys in this region from the AWS console.
If you did indeed change HADOOP_VERSION to 1.0.4, I'll note that
ec2-describe-images -a | grep hadoop-images
| grep "1.0.4"'
| grep x86
| grep available
doesn't return any images in the US-East-1 region. Note that the version (HADOOP_VERSION) of the Hadoop distribution that you are running the hadoop-ec2 command from does not need to be the same as the version of Hadoop that the images will be running.
Lastly, as a blunt fix, you could find the AMI that you want to use, and force set AMI_IMAGE to the image name in the launch-hadoop-master and launch-hadoop-cluster scripts.
I just want to install the ec2-api-tools. So I follows the instructions on this links
https://help.ubuntu.com/community/EC2StartersGuide
But when I give ec2-describe-images -o self -o amazon on the command line, it returns nothing.There is no error. It just waits like waiting for an input. What is the wrong I have done?
Thanks for helps.
I hope you have set environment variable correctly (and set appropriate privilege, I remember it's chmod 400). E.g.
$ export EC2_PRIVATE_KEY=/PATH/TO/PK/pk-XXXXXXXXXXXXXXXXXXXX.pem
$ export EC2_CERT=/PATH/TO/CERT/cert-XXXXXXXXXXXXXXXXXXXX.pem
Also, Apart from this your command looks good. Also, keep in mind that owner amazon has lots of AMIs listed.. so it may not be super quick to see the result.. you might need to wait a couple to 10s of seconds.
Please read these:
Installing Amazon EC2 Command Line Tools
Latest CLI reference to Amazon API Command Line
It's not recognizing your credentials. Double check those settings.