Commit 9d0de6e9 authored by Jérome Perrin's avatar Jérome Perrin

Updates on Selenium Server

Hopefully fix the random failure with:

```
test_connect (test.TestSSHServer) ... /srv/slapgrid/slappart3/srv/testnode/byx/soft/a452c8ac557f7eaea3c20f6cc373c390/eggs/paramiko-2.4.2-py2.7.egg/paramiko/client.py:822: UserWarning: Unknown ecdsa-sha2-nistp521 host key for [2001:67c:1254:e:4a::7bd5]:22222: 22c41f5090433152d1e5395a85d6cb4f
  key.get_name(), hostname, hexlify(key.get_fingerprint())
FAIL

======================================================================
FAIL: test_connect (test.TestSSHServer)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/srv/slapgrid/slappart3/srv/testnode/byx/soft/a452c8ac557f7eaea3c20f6cc373c390/parts/slapos-repository/software/seleniumserver/test/test.py", line 357, in test_connect
    self.assertIn("Welcome to SlapOS Selenium Server.", channel.recv(100))
AssertionError: 'Welcome to SlapOS Selenium Server.' not found in 'Attempt to write login records by non-root user (aborting)\r\r\n'

----------------------------------------------------------------------
```

Also publish the fingerprint of the server ssh key, which addresses this warning in the correct way (I feel) and since we can publish the fingerprint, why not.

/reviewed-on nexedi/slapos!492
parents 297a0dd9 fe55b022
...@@ -19,4 +19,4 @@ md5sum = c4ac5de141ae6a64848309af03e51d88 ...@@ -19,4 +19,4 @@ md5sum = c4ac5de141ae6a64848309af03e51d88
[template-selenium] [template-selenium]
filename = instance-selenium.cfg.in filename = instance-selenium.cfg.in
md5sum = 4167621b473f81892d38389ac427c6ba md5sum = 8e6b9629c1489559ec88a67d7b1bdf41
...@@ -176,6 +176,19 @@ extra-args=-t dsa ...@@ -176,6 +176,19 @@ extra-args=-t dsa
<=ssh-keygen-base <=ssh-keygen-base
extra-args=-t ecdsa -b 521 extra-args=-t ecdsa -b 521
[ssh-key-fingerprint-command]
recipe = plone.recipe.command
# recent openssh client display ECDSA key's fingerprint as SHA256
command = ${openssh-output:keygen} -lf $${ssh-host-ecdsa-key:output}
[ssh-key-fingerprint]
recipe = collective.recipe.shelloutput
# XXX because collective.recipe.shelloutput ignore errors, we run the same
# command in a plone.recipe.command so that if fails if something goes wrong.
commands =
fingerprint = $${ssh-key-fingerprint-command:command}
[sshd-config] [sshd-config]
recipe = slapos.recipe.template:jinja2 recipe = slapos.recipe.template:jinja2
rendered = $${directory:etc}/sshd.conf rendered = $${directory:etc}/sshd.conf
...@@ -268,6 +281,7 @@ url = $${selenium-server-frontend-instance:url} ...@@ -268,6 +281,7 @@ url = $${selenium-server-frontend-instance:url}
admin-url = $${selenium-server-frontend-instance:admin-url} admin-url = $${selenium-server-frontend-instance:admin-url}
ssh-url = $${sshd-service:url} ssh-url = $${sshd-service:url}
ssh-fingerprint = $${ssh-key-fingerprint:fingerprint}
# to run a local node - useful to see what tests are doing or # to run a local node - useful to see what tests are doing or
# using to use unsupported browsers like safari or edge or to test # using to use unsupported browsers like safari or edge or to test
# on mobile using appium. # on mobile using appium.
......
...@@ -17,8 +17,12 @@ extends = ...@@ -17,8 +17,12 @@ extends =
parts = parts =
slapos-cookbook slapos-cookbook
collective.recipe.shelloutput
template template
[collective.recipe.shelloutput]
recipe = zc.recipe.egg
[selenium-server] [selenium-server]
recipe = slapos.recipe.build:download recipe = slapos.recipe.build:download
version = 3.14.0 version = 3.14.0
...@@ -41,4 +45,5 @@ output = ${buildout:directory}/template-selenium.cfg ...@@ -41,4 +45,5 @@ output = ${buildout:directory}/template-selenium.cfg
[versions] [versions]
plone.recipe.command = 1.1 plone.recipe.command = 1.1
collective.recipe.shelloutput = 0.1
slapos.recipe.template = 4.3 slapos.recipe.template = 4.3
...@@ -32,6 +32,9 @@ import os ...@@ -32,6 +32,9 @@ import os
import tempfile import tempfile
import unittest import unittest
import urlparse import urlparse
import base64
import hashlib
import contextlib
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
from io import BytesIO from io import BytesIO
...@@ -343,15 +346,43 @@ class TestSSHServer(SeleniumServerTestCase): ...@@ -343,15 +346,43 @@ class TestSSHServer(SeleniumServerTestCase):
self.assertEqual('ssh', parsed.scheme) self.assertEqual('ssh', parsed.scheme)
client = paramiko.SSHClient() client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.client.WarningPolicy) class TestKeyPolicy(object):
"""Accept server key and keep it in self.key for inspection
"""
def missing_host_key(self, client, hostname, key):
self.key = key
key_policy = TestKeyPolicy()
client.set_missing_host_key_policy(key_policy)
with contextlib.closing(client):
client.connect( client.connect(
username=urlparse.urlparse(ssh_url).username, username=urlparse.urlparse(ssh_url).username,
hostname=urlparse.urlparse(ssh_url).hostname, hostname=urlparse.urlparse(ssh_url).hostname,
port=urlparse.urlparse(ssh_url).port, port=urlparse.urlparse(ssh_url).port,
pkey=self.ssh_key, pkey=self.ssh_key,
) )
# Check fingerprint from server matches the published one.
# The publish format is the raw output of ssh-keygen and is something like this:
# 521 SHA256:9aZruv3LmFizzueIFdkd78eGtzghDoPSCBXFkkrHqXE user@hostname (ECDSA)
# we only want to parse SHA256:9aZruv3LmFizzueIFdkd78eGtzghDoPSCBXFkkrHqXE
_, fingerprint_string, _, key_type = parameter_dict['ssh-fingerprint'].split()
self.assertEqual(key_type, '(ECDSA)')
fingerprint_algorithm, fingerprint = fingerprint_string.split(':', 1)
self.assertEqual(fingerprint_algorithm, 'SHA256')
# Paramiko does not allow to get the fingerprint as SHA256 easily yet
# https://github.com/paramiko/paramiko/pull/1103
self.assertEqual(
fingerprint,
# XXX with sha256, we need to remove that trailing =
base64.b64encode(hashlib.new(fingerprint_algorithm, key_policy.key.asbytes()).digest())[:-1]
)
channel = client.invoke_shell() channel = client.invoke_shell()
channel.settimeout(30) channel.settimeout(30)
# apparently we sometimes need to send something on the first ssh connection
channel.send('\n')
# openssh prints a warning 'Attempt to write login records by non-root user (aborting)' # openssh prints a warning 'Attempt to write login records by non-root user (aborting)'
# so we received more than the lenght of the asserted message. # so we received more than the lenght of the asserted message.
self.assertIn("Welcome to SlapOS Selenium Server.", channel.recv(100)) self.assertIn("Welcome to SlapOS Selenium Server.", channel.recv(100))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment