dowsoninc
By:
dowsoninc

Connecting to droplet pragmatically via ssh2_auth_pubkey_file

April 18, 2017 163 views
PHP WordPress Ubuntu Ubuntu 16.04

I am using the DigitalOcean API to create Droplets with the Wordpress Ubuntu Image preinstalled - when I create the Droplet I need to activate the Wordpress install by logging in via SSH.

I want a fully automated process where I can create a full install without any manual work. The DO API stuff is straightforward and working but I am having an issue connecting to my droplet via ssh2authpubkey_file.

The steps I have taken:

Generated a key via PuTTY Key Generator
Added the public key to my DO account under 'Settings'
Exported a OpenSSH Key via PuTTY Key Generator

I have a test setup using XAMPP on Windows - current code is:

<?php
$host = "xxx.xx.xxxx";
$port = 22;
$conn = ssh2connect($host, $port);
$username = "root";
$pub
key = "/etc/ssh/sshhostrsakey.pub";
$pri
key = "idrsa";
if(ssh2
authpubkeyfile(
$conn,
$username,
$pubkey,
$pri
key))
{
echo "Authentication succeeded";
}
else
{
echo "Authentication failed";
}
?>

In the same folder I have the private key I generated from PuTTY Key Generator in a file called id_rsa.

I get the following error when trying to connect:
Warning: ssh2authpubkey_file(): Authentication failed for root using public key: Username/PublicKey combination invalid in /var/www/html/test/test.php on line 8
Authentication failed

In the id_rsa file I have:

-----BEGIN RSA PRIVATE KEY-----
KEY HERE
-----END RSA PRIVATE KEY-----

Can anyone see a reason why this isn't working? It should in theory be pretty straight forward.

P.S. I have also tried saving the public key locally into a file called idrsa.pub and using that in the $pubkey variable.

2 Answers

@dowsoninc
But have you connected the key with a droplet, when you create the droplet?
Try to login with PuTTY and the key, does that work?

@dowsoninc

The function name is actually ssh2_connect. In your code, you're using ssh2connect -- also ssh2_auth_pubkey_file instead of ssh2authpubkeyfile. It may be a formatting issue with your post, but just for clarity :-).

As for the connection, I'm using a slightly modified version of what you have right now and it works.

<?php
$host   = 'ip_or_hostname';
$port   = 22;
$user   = 'username';
$pass   = 'passphrase';
$pubkey = '/path/to/key.pub';
$prikey = '/path/to/privkey';

$conn   = ssh2_connect( $host, $port );
$auth   = ssh2_auth_pubkey_file( $conn, $user, $pubkey, $prikey, $pass );

if ( $auth )
{
    echo 'Public Key Authentication Successful.' . PHP_EOL;
}
else
{
    echo 'Public Key Authentication Failed.' . PHP_EOL;
}

In the code above:

$host should be the IP of the Droplet, or Hostname;

$port should be the port you connect to SSH on;

$user should be the username of the user you're connecting as (i.e. root, for example);

$pubkey should be the path to the public key file;

$prikey should be the path to the private key file;

We initialize the connection by assigning the function call to $conn, then assign the authentication function call to $auth. This keeps the function calls out of the if/else statement and keeps things clean.

If $auth returns true (which it should only ever return true or false), we echo out that the connection was a success. If it returns false, we echo out that the connection was a failure.

If you're not using a passphrase on your SSH Key Pair, you can remove $pass from line 5 and also from , $pass from line 10.

I would recommend using a passphrase for security, though removing those two instances would be how to handle authentication without a passphrase.

...

If that doesn't work, then you need to check your keys. PuTTy uses and entirely different format for keys that isn't compatible with standard SSH (OpenSSH), so trying to use keys that PuTTy creates won't work unless you export them as OpenSSH keys specifically.

  • @dowsoninc

    As a general note, when it comes to connections and running commands, if you expect output from the commands that you execute, make sure you block the stream.

    i.e.

    $cmd = ssh2_exec( $conn, 'php -v' );
    
    stream_set_blocking( $cmd, true );
    
    $out = ssh2_fetch_stream( $cmd, SSH2_STREAM_STDIO );
    
    echo stream_get_contents( $out );
    

    Using the above, when connecting to one of my test Droplets with PHP 7.0 installed, I receive an expected response of:

    PHP 7.0.15-0ubuntu0.16.04.4 (cli) ( NTS )
    Copyright (c) 1997-2017 The PHP Group
    Zend Engine v3.0.0, Copyright (c) 1998-2017 Zend Technologies
        with Zend OPcache v7.0.15-0ubuntu0.16.04.4, Copyright (c) 1999-2017, by Zend Technologies
    

    Without stream_set_blocking( $cmd, true );, all that is received is an empty response since the commands execute before PHP is able to capture the result.

Have another answer? Share your knowledge.