Repository: DataDog/dd-agent

Issue:
Support ECDSA for ssh_check
ssh_check.py is not support ECDSA ssh key.
paramiko is support ECDSA ssh key.
http://docs.paramiko.org/en/1.17/api/keys.html#module-paramiko.ecdsakey

I changes ssh_key.py, but It's not working.

```
2016-05-08 17:56:27 JST | ERROR | dd.collector | checks.ssh_check(__init__.py:763) | Check 'ssh_check' instance #0 failed
Traceback (most recent call last):
  File "/opt/datadog-agent/agent/checks/__init__.py", line 746, in run
    self.check(copy.deepcopy(instance))
  File "/opt/datadog-agent/agent/checks.d/ssh_check.py", line 70, in check
    password=conf.password, pkey=private_key)
  File "/opt/datadog-agent/embedded/lib/python2.7/site-packages/paramiko/client.py", line 307, in connect
    look_for_keys, gss_auth, gss_kex, gss_deleg_creds, gss_host)
  File "/opt/datadog-agent/embedded/lib/python2.7/site-packages/paramiko/client.py", line 519, in _auth
    raise saved_exception
AuthenticationException: Authentication failed.
```



Discussion:
Thanks a lot for the feedback @n0ts 
You are right, it looks like we are forcing the use of an RSA key https://github.com/DataDog/dd-agent/blob/5.7.x/checks.d/ssh_check.py#L57, while we should just use the generic `paramiko.pkey.PKey class` to handle this situation.

Would you like to open a pull request to fix this ? 

Thanks again.

Hi @n0ts, Thanks for raising this issue. Would you be open to submitting a PR to add ECDSA support as you suggested?

@remh @irabinovitch Thanks, I'll try it. How to run test only `test_ssh_check.py` in local?
rake ci:run[ssh_check] is not working...

@n0ts the correct command is `rake ci:run[ssh]` for this check, let us know if it works for you.


Resolving patch:
diff --git a/checks.d/ssh_check.py b/checks.d/ssh_check.py
--- a/checks.d/ssh_check.py
+++ b/checks.d/ssh_check.py
@@ -21,6 +21,7 @@ class CheckSSH(AgentCheck):
         ('username', True, None, str),
         ('password', False, None, str),
         ('private_key_file', False, None, str),
+        ('private_key_type', False, 'rsa', str),
         ('sftp_check', False, True, bool),
         ('add_missing_keys', False, False, bool),
     ]
@@ -31,6 +32,7 @@ class CheckSSH(AgentCheck):
         'username',
         'password',
         'private_key_file',
+        'private_key_type',
         'sftp_check',
         'add_missing_keys',
     ])
@@ -55,7 +57,10 @@ def check(self, instance):
 
         private_key = None
         try:
-            private_key = paramiko.RSAKey.from_private_key_file(conf.private_key_file)
+            if conf.private_key_type == 'ecdsa':
+                private_key = paramiko.ECDSAKey.from_private_key_file(conf.private_key_file)
+            else:
+                private_key = paramiko.RSAKey.from_private_key_file(conf.private_key_file)
         except IOError:
             self.warning("Unable to find private key file: {}".format(conf.private_key_file))
         except paramiko.ssh_exception.PasswordRequiredException:
@@ -69,11 +74,11 @@ def check(self, instance):
         client.load_system_host_keys()
 
         exception_message = None
-        #Service Availability to check status of SSH
+        # Service Availability to check status of SSH
         try:
             client.connect(conf.host, port=conf.port, username=conf.username,
                 password=conf.password, pkey=private_key)
-            self.service_check('ssh.can_connect', AgentCheck.OK,  tags=tags,
+            self.service_check('ssh.can_connect', AgentCheck.OK, tags=tags,
                 message=exception_message)
 
         except Exception as e:
@@ -86,7 +91,7 @@ def check(self, instance):
                     message=exception_message)
             raise
 
-        #Service Availability to check status of SFTP
+        # Service Availability to check status of SFTP
         if conf.sftp_check:
             try:
                 sftp = client.open_sftp()


Test patch: