Aws-cli: Fix ec2 import-key-pair

Created on 30 Jan 2013  Â·  17Comments  Â·  Source: aws/aws-cli

On Ubuntu 12.04 I ran ssh-keygen and wrote the output to particular (non-default) file.

When I try to use the 'aws ec2 import-key-pair' command it fails, complaining the .pub file isn't in OpenSSH format. However the same key works fine with the java CLI tools.

bug

Most helpful comment

this is still not documented on the ec2 key pair user guide nor in the ec2 import-key-pair guidelines...

if the documentation is in a repo somewhere for me to do a pull request, I'd gladly do so.. just point me in the right direction

All 17 comments

Ah, I see the problem. The key pair body must be encoded in base64 prior to uploading to EC2. Thanks for the report. This will be fixed soon.

Fix was actually in the botocore layer and has been fixed. You will need to update your botocore to get the fix.

I think I'm seeing this happen again. I've installed aws cli from pip and I have botocore 0.7 from pip. I get the following when trying to upload the public key file produced by using ssh-keygen:

{
"Response": {
"Errors": {
"Error": {
"Message": "Key is not in valid OpenSSH public key format",
"Code": "InvalidKeyPair.Format"
}
},
"RequestID": "49bdfd48-5252-4562-b6cd-fee30e55d946"
}
}
A client error (InvalidKeyPair.Format) occurred: Key is not in valid OpenSSH public key format

I ended up getting it to work by running the following command for aws cli:

aws ec2 import-key-pair --public-key-material $(base64 fry.pub | tr -d 'n') --key-name fry

My OS is Arch Linux 64-bit with Python 2.7 running the commands.

Fixed again in 5d5079f758cfd86356572896820855c7b128a162

With botocore 0.13.1 (and awscli 0.13.2), I had to do

aws ec2 import-key-pair --public-key-material "$(cat ~/.ssh/id_rsa.pub | tr -d '\n')"  --key-name my-key

boto/botocore:5d5079f changed the form from string to blob, so botocore does the base64 encoding. However, the trailing newline from regular cat screws up the program as well. Supplying the file path directly does not help.

I should add, it'd be great to re-open this issue. This method is a non-intuitive hack that took an hour or so to figure out. A user should be able to just supply a file path and have the program do the rest.

How about this variation:

aws ec2 import-key-pair --public-key-material file://~/.ssh/id_rsa.pub  --key-name my-key

Does that work for you?

yes it does, thank you. is that documented anywhere? it makes some amount
of sense in retrospect, but found no indication that such file URLs were
possible.

On Fri, Aug 2, 2013 at 4:32 PM, Mitch Garnaat [email protected]:

How about this variation:

aws ec2 import-key-pair --public-key-material file://~/.ssh/id_rsa.pub --key-name my-key

Does that work for you?

—
Reply to this email directly or view it on GitHubhttps://github.com/aws/aws-cli/issues/41#issuecomment-22034081
.

It is documented here but it's probably easy to miss. I think we might add something to the help text for complex parameters mentioning the file:// trick. You can also use any other URI, e.g. http://blah.blah.com/foobar.json, and it will retrieve the data and use the contents as the value of the parameter.

more extended help from the command line would definitely be appreciated.

On Sat, Aug 3, 2013 at 9:19 AM, Mitch Garnaat [email protected]:

It is documented herehttps://github.com/aws/aws-cli#file-based-parameter-inputbut it's probably easy to miss. I think we might add something to the help
text for complex parameters mentioning the file:// trick. You can also
use any other URI, e.g. http://blah.blah.com/foobar.json, and it will
retrieve the data and use the contents as the value of the parameter.

—
Reply to this email directly or view it on GitHubhttps://github.com/aws/aws-cli/issues/41#issuecomment-22054785
.

The fact that we are required to write --public-key-material file://~/.ssh/id_rsa.pub instead of just specifying the filepath is really a bad UX.

+1
I also think that the file:// is really not intuitive, in fact I don't know any other cli using it. And at least the shell I use (fish) can't do auto-completion for filenames.

I would agree that file:// (or sometimes even more-unintuitive fileb://) is not obvious. Yet the reason of introducing such syntax in the first place is that, many AWS parameters can accept input either as a literal string in command line, or read it from a file (or from a URL). So we need a special syntax to differentiate the two scenarios. Is there any other syntax which is more intuitive? Possibly. Any new suggestion is welcome.

Why not just check if the parameter meets the format for a ssh private key and if not, open it as a file? AWS is already pretty restrictive on what it will take as a public key. (No DSA, no non-standard lengths, etc.) So there are a limited number of formats to check for.

Also, it doesn't help that the --help option in command line tools says:

"--public-key-material" (blob)

The public key. You must base64 encode the public key material
before sending it to AWS.

This is additionally confused by the example which shows the data being sent without being base64 encoded.

This indicates that the user has to base64 encode the public key, when in fact it's being done by the client and the user should NOT base64 encode it, as shown in the example.

Or if you want less ambiguity and corner case coding, consider adding a --public-key-file to specify a filename. Then leave the current syntax as is but depreciated for backward compatibility.

To minimize my headaches, I have adopted using OpenSSH pubkey format, since it resides on a single line, without line breaks, and I can easily include it on the command line without needing to create/reference a .pub file.

this is still not documented on the ec2 key pair user guide nor in the ec2 import-key-pair guidelines...

if the documentation is in a repo somewhere for me to do a pull request, I'd gladly do so.. just point me in the right direction

+1

Good lord! The pain!

Had the same issue with the Import-EC2KeyPair command in PowerShell. Here's how I fixed it:

# Get file contents as a single string
$RawKey = Get-Content -Raw -Path /path/to/key

# Cast string to char array
# Cast char array to byte array
# Call ToBase64String() method on result
$KeyMaterial = [System.Convert]::ToBase64String([byte[]][char[]]$RawKey)

# Import the Base64-encoded key material
Import-EC2KeyPair -PublicKeyMaterial $KeyMaterial -KeyName trevor
Was this page helpful?
0 / 5 - 0 ratings

Related issues

braddr picture braddr  Â·  3Comments

maanbsat picture maanbsat  Â·  3Comments

KimberleySDU picture KimberleySDU  Â·  3Comments

vadimkim picture vadimkim  Â·  3Comments

ronaldpetty picture ronaldpetty  Â·  3Comments