Add-AzVMSshPublicKey to vmConfig fails when calling New-AzVM - windows

I'm following the windows quickstart for creating a VM in azure powershell
I'm stuck here:
# Configure the SSH key
$sshPublicKey = cat ~/.ssh/id_rsa.pub
Add-AzVMSshPublicKey `
-VM $vmconfig `
-KeyData $sshPublicKey `
-Path "/home/azureuser/.ssh/authorized_keys"
First of all I think the following code is wrong, as cat returns System.String[] and running this verbatim results in
Add-AzVMSshPublicKey : Cannot convert 'System.Object[]' to the type 'System.String'
So... I instead use Get-Content "./path/to/file" -raw which just returns a string and the command runs without errors
Now when I run
New-AzVM `
-ResourceGroupName $resourceGroupName `
-Location $location -VM $vmConfig
I get the following error, meaning the keyData I set earlier wasn't set correctly.
New-AzVM : The value of parameter linuxConfiguration.ssh.publicKeys.keyData is invalid.
I've found the issue - So Azure key vault gives me a PEM public key in the form
-----BEGIN PUBLIC KEY-----
MIIBojANBgkqhkiG9w0BAQEFAAO...
...
...
...
...0CS94AFAgMBAAE=
-----END PUBLIC KEY-----
Whereas the VM is expecting it in OpenSSH format
ssh-rsa ..........
I've tried to convert it with
ssh-keygen -i -m PKCS8 -f ./key.pem
but nothing gets output
UPDATE
Aaaand it's a powershell issue

First, the tutorial is a guide to create Linux VM via Azure PowerShell, not Windows. Second, the command cat just outputs the content of the file. And command $sshPublicKey = cat ~/.ssh/id_rsa.pub creates a variable in string:
The parameter -KeyData of the command Add-AzVMSshPublicKey also expect a string:
So there is no problem with the PowerShell command and all the commands work fine on my side. And the error shows the value of the key data is invalid, what you need to do is to make sure if the SSH public key is no problem.

To get this key from an Azure Key vault,
Get-AzKeyVaultKey -OutFile *filename* returns a public key in PEM Form
-----BEGIN PUBLIC KEY------
....
-----END PUBLIC KEY-----
The vm requires the key data to be a one-liner in OpenSSH format
ssh-rsa ....... mykeylabel
But Powershell's ssh-keygen, unlike its UNIX counterpart, cannot convert between these formats as it has an open bug

Related

How to read/write SSH Private key (id_rsa)

As part of an automated Cloud Init setup, I am auto generating public/private keys for users, reading them from file and then saving them in bash variables like so
public_key=$(cat /path/to/id_rsa.pub)
private_key=$(cat /path/to/id_rsa)
Then I write them to the target machine through Cloud Init like so
- sudo -H -u aryan bash -c 'echo "$public_key" > ~/.ssh/id_rsa.pub'
- sudo -H -u aryan bash -c 'echo "$private_key" > ~/.ssh/id_rsa'
The public key is written correctly, but the private key is written to a single line and then SSH complains that it is the wrong format. I am expecting this
-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQCpOipW5Xyjc9jLE6AX/0HktpZtyokJap9k5njJl3uw7VpcUITW
3UzHHZor4b4N1x8wp17Y0udPsrcPtfJR+pVSr0s6ZMkjX0B7J5jE64iPlVOkO+ww
b4CMlonViWeTJ/+gSLkfC2EDfSqPTEOWx44Vs7Mt2qi5Rvq/Po81NDrK2QIDAQAB
AoGAcklZ9r2dYzYFn4BtikdVVQUKqrMxwS5E33vW7y5i1qY1dErcq89g3shbKm+W
TvqNkeo23+/vT5++idmzATJeTQ+uhRidPrU6XTWd4I8LvHB6dYIGKpGuciv4NWG0
3CLDt5IRLpAJ8qAl3tmitWadZw7lJtGAWg+7zdbIoP07XhECQQD32vBAwePlB/ZY
CsRNeIDUWtAGaxqBvssmbh4wfCYZDH+3BJbyMG0AWycE0YLZLlACKzTUu5PC8CKu
zQBKb02LAkEArsnGdJ7ipDTZZWl1Q42M494SfQUA9+he12WU6O2o2BJqr8cVRG2V
BJHHXvdHB+xWRMpo0vxTiGdDIDqPwfPdqwJBAMBpkgvjuYSqur48lYpC21h/q3Dg
IrLIqDMMV5lyN61Ie7lb8cbQez5EhTUDZN4vSuN0IU5o1FwIShSDhw9B+uMCQFwN
UiJLJ0uZtcCOCL76BnBfnVcQUpE9ZO2FxyXhPGIHWP6YF6BBIhEVAW4HRvZqRojW
HNy5HPkigRyxGtLnrx8CQFWZtrGiBIrYRsrf9fwXv4DTB5z7sQLEf8x2dwvif34O
+bYMoDJPewr3ti88KJP4rubmIS9PTCAJxEfMBPkZHvE=
-----END RSA PRIVATE KEY-----
But instead I have this (truncated)
-----BEGIN RSA PRIVATE KEY-----MIICXAIBAAKBgQCpOipW5Xyjc9jLE6AX/0HktpZtyokJ...
Question: How do I correctly read a private key into a variable and then write it to a text file
Note: The easiest way would be to simply copy the file but I don't think Cloudinit supports cp/scp. If it does, please do let me know how
You need to quote your command substitution to preserve newlines:
private_key="$(cat /path/to/id_rsa)"
What you can do for cloud-init ssh setup, is to generate the private and public key before the deployment and then use cloud-init to deploy the servers with those ssh keys.
This way, you will always have the same private key on your computer and be able to ssh into the new servers.
Also it might be a security issue if the wrong people have access to the cloud-config file
Sample code:
ssh_authorized_keys:
- ssh-rsa AAA... user#server
ssh_keys:
rsa_private: |
-----BEGIN RSA PRIVATE KEY-----
MIIEpwIBAAKCAQIA3FurAzWIiBuNd1ew2sM3s/eOg+Sf9nSQPcEzNyNTkhxSwkxf
3fgNlSpoBc1s7XD9DefpzGT/lxZzVQcQGJ7NnxddRKOH8Uhhp75L3Q18L4z4bZNM
zX5ngtZopa4SoFWiMCVljXeWy4CpuQdpD8N9Bpb+9IYCVOzitnrD2UM2ubf6imOq
Saeiyi3/SdftcUO3uhjemLkg9d2nwvfbJUqSFR4NGR5nsOxxMC4tnxylDRN88qE3
fSrSQHY+qTu+3mKQ6J7VKUM7e0jRD/vQK64V0f6AqKLxta7XFeA8sIa0qbGNQHBk
Zg+OOFYUz4x0qbwmwuQR9RS6HnBLXvdcZb36nXkCAwEAAQKCAQEfx+jGMbZbSv4A
NFmBc55ZCl83joWzmeQjw/WLAkFPVV5qP3GkJd5voQoXrCUFqcIVe1kw7XAfblF7
9eTQaDbntwrwl1VH61SKSNvQKd27Tf2WgCQXjx+Gsz2sh4qQLUmTABHBcXoCJ7BS
y0rPxzYE+UoUIi+7595ayyHr99Gwv1/N78xw7PS+oyxmn4rsbFYfWbkKWKgbizAm
oxM5EE1g1Mn9m0ocruYzTiPIHLGMsfeqMDzHG7lK0rTL0nqFP/QegZkSE0hQ/fJm
gS44NnFQ1HeQB3GCbgJlQFNVNHPueZevEemZ5QEuPIhYmG8+GlGRl9aFto9BGDa7
z0Ct29HeAQKBgQ95Z86CIZIsSWhjt0ZjW0DzFd6JQC+gKxmxcaELZPL+M0jh2zMV
9jCIPERV4RKwzttKm/tGz2Zh+FsToi0Ie1TW4uVArGcFeX+XsTIrcIyIwzoFixR1
k2Rv9ZwJGQgapTokhoVidAMRUIZfN/2HH4y2ZnIdOUDpP8FpknFiTXFoEQKBgQ49
hWHFwKFB6sprKq+dJkFgNEhtdn4q0K5NrBgwHm6h2sO3tyIwVMCmhwHtBnEQOovg
W7dM/GYqpxE76qaJBoHFht0RGPxt1wbQRbjwZ78KdMrLa+RZlFRVdPU5QXEcYu+H
jqIiTf/aDl69cdQ8dkJoGwjjT80R4t2zy+7iKqqG6QKBgQbqYhsniytRgYkWr2zU
sI6pVMe3nSPrt/dmlvq7JeV296Kf1bnSAdGUwSJlIw6AWCInCOjWr4/5Ds5dSuhH
Vx8GXibIrYPpLXB5caaTRVx5Lo66tXpyRWnoo2KVqks15UvD0R7BbkmErnEvEs3K
Wq4/Qi+Toe3Blk2xCdKEdUnOkQKfgQLZXC5LmlapEYieGFQ6ZMT/snYrMGHdvxKg
h6XvOqd3yoUN5J36fXpt1uUTvw4v6QbDRJZP2M+4COTxz+ix0ZN1KZ5hJVabw0Gh
udFeh+M4/FT2jgeJxJt63YOSiP1QaJrzzB20L1bZEbbywCtuTVrL6VzF3dlxkqo4
pryMk2y6wQKBgQ3MpmrMTRS3bA7h6qMvaZep6Pke6gsXSgGpbU9mFB2ja8IKIVLZ
iVLjmcN1ItqKtYbD01WURkcV3ne+E9bbDYrBQmPDfaO+VbUgBVTjmybLpamrci5k
DcDQVCymHy0EwAqGOuWKM8EgbxuTKDGuUX9Q0TI23fwTc9rB6j3FEAnyvQ==
-----END RSA PRIVATE KEY-----

Error loading key "/root/.ssh/id_rsa": invalid format

I am building a CI/CD for my django project using GitLab. As part of my deploy stage, I have
deploy:
stage: deploy
script:
- mkdir -p ~/.ssh
- echo "$PRIVATE_KEY" | tr -d '\r' > ~/.ssh/id_rsa
- cat ~/.ssh/id_rsa
- chmod 700 ~/.ssh/id_rsa
- eval "$(ssh-agent -s)"
- ssh-add ~/.ssh/id_rsa
- ssh-keyscan -H 'gitlab.com' >> ~/.ssh/known_hosts
- chmod +x ./deploy.sh
- scp -o StrictHostKeyChecking=no -r ./.env ./docker-compose.prod.yml ec2-user#$EC2_PUBLIC_IP_ADDRESS:/home/ec2-user/app
- bash ./deploy.sh
only:
- master
The build breaks down at ssh-add ~/.ssh/id_rsa with the error message Error loading key "/root/.ssh/id_rsa": invalid format.
I have checked people with questions with similar error messages and none seem related to what I am doing.
Notes
I am trying to deploy to amazon ec2
I am following this tutorial https://testdriven.io/blog/deploying-django-to-ec2-with-docker-and-gitlab/ and everything seems to work fine up until this last point.
I faced such issue, the error was "Error loading key "/root/.ssh/id_rsa": invalid format" It was due to protected variable, that only applied on protected branch. I mean to say if you use protected variable on unprotected branch it will not recognize the variable thus failed to recognize it.
I managed to fix it with the help of guys from the ##aws irc channel
The Problem
I generated a PKCS#1 key format instead of a PKCS#8 format.
The PKCS#1 is represented as:
-----BEGIN RSA PRIVATE KEY-----
BASE64 ENCODED DATA
-----END RSA PRIVATE KEY-----
The PKCS#8 is represented as:
-----BEGIN PRIVATE KEY-----
BASE64 ENCODED DATA
-----END PRIVATE KEY-----
Solution
I simply copied the PRIVATE KEY and converted it here https://decoder.link/rsa_converter
You can also see a better elucidation here Differences between "BEGIN RSA PRIVATE KEY" and "BEGIN PRIVATE KEY"
Edited
As indicated below, it is not a good idea to use websites to do the conversion. Especially when your private key is likely being
sent to their servers. Instead, do the conversion locally as indicated here
by #csgeek

Setting CF environment variable with multiline value

I want to set a RSA token in environment variable of CF App.
I try to set it with below commands
export var1=`cat key.pem`
cf set-env app KEY "$var1"
If I console the env variable(cf env app), I get the expected output:
.
.
User-Provided:
KEY: -----BEGIN RSA PRIVATE KEY-----
.
. multi-line key contents
.
-----END RSA PRIVATE KEY-----
However, if I run the app, it fails in the authentication.
I also tried applying quotes:
cf set-env app KEY "'$var1'"
It was the token issue.
The first approach mentioned in the question worked.

Invalid public ssh key

Trying to follow the instructions on github for Generating SSH Keys for windows.
I run ssh-keygen -t rsa -C "my#email.com", enter passphrase and it appears the SSH key is generated correctly.
However, when trying to "Add SSH Key" on GitHub it gives me the error
Key is invalid. It must begin with 'ssh-rsa' or 'ssh-dss'. Check that you're copying the public half of the key
The public key generated by Windows looks like this:
---- BEGIN SSH2 PUBLIC KEY ----
Comment: "2048-bit RSA, my#email.com"
*public key*
---- END SSH2 PUBLIC KEY ----
Most notably it does not begin with 'ssh-rsa' or 'ssh-dss'. I tried just copying the *public key* part and prepending 'ssh-rsa' to it but I get the same error on GitHub. Any ideas what I'm doing wrong?
Got it. The public key should look like this:
ssh-rsa *public key* my#email.com
That is:
ssh-rsa<space><public key ending with ==><space><email address>
In Linux,after executing the above command,(xyz.pub) file will be generated in the directory you are working on.
Then if you do a " cat xyz.pub ", you will get your public key which has "ssh-rsa" in the beginning.
Now,you need to copy paste the displayed text in your GitHub Account.
Hope this will probably solve the issue.
And in windows,I think you should edit the file in NotePad++
GitHub generates two files: one with no type, and one .pub. You need the second one with the .pub extension, that file will already have the pattern:
ssh-rsa <key> <email>
If it doesn't have this pattern, you may be looking at the wrong file.
After the Git Bash steps, I went through the steps successfully. A pub file was generated in the Drive:\Users<YOUR DIR>.ssh\
Open the file with notepad, copied and pasted into https://github.com/settings/keys. That's it!

ansible to read openssl public key (.pem) content from user input and create a file on server

I m basically creating a playbook for creating pkcs12 file where in it asks for public key(.pem) and private key. my private key is on server so i can pass location of file. but my public key(.pem) is not residing on server nor i can copy paste from local.
so i want to create an ansible-playbook which can read public key content from user as a variable and create a file on the remote server to use in pkcs12 file creation.
my publickey content is spreaded across multiple lines like below.
-----BEGIN CERTIFICATE-----
(64-character alphanumeric content)
.
.
.
.
-----END CERTIFICATE-----
can you suggest simple way to achieve this.
i am using copy module 'content' option, but unable to achieve this.
tasks:
- name: copy content
copy:
content: "{{ my_pub_key }}"
dest: /tmp/{{file}}.pem
ansible-playbook abc.yaml -e "my_pub_key=
-----BEGIN CERTIFICATE-----
.
.
.
.
-----END CERTIFICATE-----
"~
please suggest if there is any another way to achieve this ?
Not exactly sure, what do you mean by below statement. From the question, guessing nothing was written to the destination file.
...but unable to achieve this...
Your task looks fine. However, to pass multiline string as a parameter, add quote (') to define variable value like this.
$ ansible-playbook abc.yaml -e "my_pub_key='
-----BEGIN CERTIFICATE-----
.
.
.
.
-----END CERTIFICATE-----'"

Resources