From b1e50fc76ddece9944ae253da9bacd485ffea84b Mon Sep 17 00:00:00 2001 From: varac Date: Tue, 6 Oct 2015 13:23:56 +0200 Subject: [feat] Remove tapicero from more places Remove from: - platform white-box tests (couchdb user ACLs, tapicero daemon test) - provider_base/ dir that handles the compilation of the hiera config file - Resolves: #7501 --- tests/white-box/couchdb.rb | 3 +-- tests/white-box/webapp.rb | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'tests') diff --git a/tests/white-box/couchdb.rb b/tests/white-box/couchdb.rb index 5ee12ff3..edb28eac 100644 --- a/tests/white-box/couchdb.rb +++ b/tests/white-box/couchdb.rb @@ -9,7 +9,6 @@ class CouchDB < LeapTest end def test_00_Are_daemons_running? - assert_running '^tapicero', :single => true if multimaster? assert_running 'bin/beam' assert_running 'bin/epmd' @@ -70,7 +69,7 @@ class CouchDB < LeapTest end def test_04_Do_ACL_users_exist? - acl_users = ['_design/_auth', 'leap_mx', 'nickserver', 'soledad', 'tapicero', 'webapp', 'replication'] + acl_users = ['_design/_auth', 'leap_mx', 'nickserver', 'soledad', 'webapp', 'replication'] url = couchdb_backend_url("/_users/_all_docs", :username => 'admin') assert_get(url) do |body| response = JSON.parse(body) diff --git a/tests/white-box/webapp.rb b/tests/white-box/webapp.rb index 9956eb35..8be6bde2 100644 --- a/tests/white-box/webapp.rb +++ b/tests/white-box/webapp.rb @@ -95,7 +95,7 @@ class Webapp < LeapTest end # - # returns true if the per-user db created by tapicero exists. + # returns true if the per-user db created by soledad-server exists. # we try three times, and give up after that. # def assert_user_db_exists(user) -- cgit v1.2.3 From b53bd889d5407fb357329b414bcae929176c0690 Mon Sep 17 00:00:00 2001 From: ankonym Date: Wed, 7 Oct 2015 11:19:26 +0200 Subject: Change webapp tests to work with enabled invite codes This will generate an invite code so test_05_Can_create_and_authenticate_and_delete_user_via_API? will work correctly (when invite codes are required for signups). --- tests/helpers/bonafide_helper.rb | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'tests') diff --git a/tests/helpers/bonafide_helper.rb b/tests/helpers/bonafide_helper.rb index 9b26eaaf..39f761fe 100644 --- a/tests/helpers/bonafide_helper.rb +++ b/tests/helpers/bonafide_helper.rb @@ -32,7 +32,11 @@ class LeapTest def assert_create_user user = SRP::User.new url = api_url("/1/users.json") - assert_post(url, user.to_params) do |body| + + params = user.to_params + params['user[invite_code]'] = generate_invite_code + + assert_post(url, params) do |body| assert response = JSON.parse(body), 'response should be JSON' assert response['ok'], "Creating a user should be successful, got #{response.inspect} instead." end @@ -40,6 +44,13 @@ class LeapTest return user end + def generate_invite_code + if property('webapp.invite_required') + `cd /srv/leap/webapp/ && sudo RAILS_ENV=production bundle exec rake generate_invites[1]`.gsub(/\n/, "") + end + end + + # # attempts to authenticate user. if successful, # user object is updated with id and session token. -- cgit v1.2.3 From dc426cc777aec921772c1d8c2fa014d61aa90d33 Mon Sep 17 00:00:00 2001 From: ankonym Date: Wed, 7 Oct 2015 12:11:21 +0200 Subject: Modify bonafide_helper to improve user creation test with invites Will now use the correct user to generate invite codes and only add invite code parameter when invite codes are enabled --- tests/helpers/bonafide_helper.rb | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'tests') diff --git a/tests/helpers/bonafide_helper.rb b/tests/helpers/bonafide_helper.rb index 39f761fe..1a6dc6fe 100644 --- a/tests/helpers/bonafide_helper.rb +++ b/tests/helpers/bonafide_helper.rb @@ -34,7 +34,10 @@ class LeapTest url = api_url("/1/users.json") params = user.to_params - params['user[invite_code]'] = generate_invite_code + + if property('webapp.invite_required') + params['user[invite_code]'] = generate_invite_code + end assert_post(url, params) do |body| assert response = JSON.parse(body), 'response should be JSON' @@ -45,9 +48,7 @@ class LeapTest end def generate_invite_code - if property('webapp.invite_required') - `cd /srv/leap/webapp/ && sudo RAILS_ENV=production bundle exec rake generate_invites[1]`.gsub(/\n/, "") - end + `cd /srv/leap/webapp/ && sudo -u leap-webapp RAILS_ENV=production bundle exec rake generate_invites[1]`.gsub(/\n/, "") end -- cgit v1.2.3 From 2053883c81d261b5a9af5011bd6f0e8bc709f8d1 Mon Sep 17 00:00:00 2001 From: ankonym Date: Mon, 12 Oct 2015 11:19:21 +0200 Subject: Fix soledad test when invite codes are enabled This provides an invite code when invite codes are enabled while the test runs (but it does not get deleted yet afterwards) --- tests/helpers/bonafide_helper.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'tests') diff --git a/tests/helpers/bonafide_helper.rb b/tests/helpers/bonafide_helper.rb index 1a6dc6fe..82db3973 100644 --- a/tests/helpers/bonafide_helper.rb +++ b/tests/helpers/bonafide_helper.rb @@ -36,7 +36,8 @@ class LeapTest params = user.to_params if property('webapp.invite_required') - params['user[invite_code]'] = generate_invite_code + @invite_code = generate_invite_code + params['user[invite_code]'] = @invite_code end assert_post(url, params) do |body| -- cgit v1.2.3 From d7f8fde6d48568c912733aca6fa3030ccdfcada7 Mon Sep 17 00:00:00 2001 From: varac Date: Mon, 26 Oct 2015 10:56:31 +0100 Subject: [bug] Disable user-creation and soledad test Until we have a proper fix for #7523, we disable this test. - Tested: [unstable.bitmask.net] - Related: #7523 --- tests/white-box/webapp.rb | 28 ---------------------------- 1 file changed, 28 deletions(-) (limited to 'tests') diff --git a/tests/white-box/webapp.rb b/tests/white-box/webapp.rb index 8be6bde2..48507521 100644 --- a/tests/white-box/webapp.rb +++ b/tests/white-box/webapp.rb @@ -41,34 +41,6 @@ class Webapp < LeapTest pass end - def test_05_Can_create_and_authenticate_and_delete_user_via_API? - if property('webapp.allow_registration') - assert_tmp_user - pass - else - skip "New user registrations are disabled." - end - end - - def test_06_Can_sync_Soledad? - return unless property('webapp.allow_registration') - soledad_config = property('definition_files.soledad_service') - if soledad_config && !soledad_config.empty? - soledad_server = pick_soledad_server(soledad_config) - if soledad_server - assert_tmp_user do |user| - assert_user_db_exists(user) - command = File.expand_path "../../helpers/soledad_sync.py", __FILE__ - soledad_url = "https://#{soledad_server}/user-#{user.id}" - assert_run "#{command} #{user.id} #{user.session_token} #{soledad_url}" - pass - end - end - else - skip 'No soledad service configuration' - end - end - private def url_options -- cgit v1.2.3 From 9ca3e3ede5beb8763233063315cdb3d6bc15bc98 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Fri, 13 Nov 2015 12:10:32 -0400 Subject: re-enable user creation and soledad-sync test --- tests/white-box/webapp.rb | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'tests') diff --git a/tests/white-box/webapp.rb b/tests/white-box/webapp.rb index 48507521..8be6bde2 100644 --- a/tests/white-box/webapp.rb +++ b/tests/white-box/webapp.rb @@ -41,6 +41,34 @@ class Webapp < LeapTest pass end + def test_05_Can_create_and_authenticate_and_delete_user_via_API? + if property('webapp.allow_registration') + assert_tmp_user + pass + else + skip "New user registrations are disabled." + end + end + + def test_06_Can_sync_Soledad? + return unless property('webapp.allow_registration') + soledad_config = property('definition_files.soledad_service') + if soledad_config && !soledad_config.empty? + soledad_server = pick_soledad_server(soledad_config) + if soledad_server + assert_tmp_user do |user| + assert_user_db_exists(user) + command = File.expand_path "../../helpers/soledad_sync.py", __FILE__ + soledad_url = "https://#{soledad_server}/user-#{user.id}" + assert_run "#{command} #{user.id} #{user.session_token} #{soledad_url}" + pass + end + end + else + skip 'No soledad service configuration' + end + end + private def url_options -- cgit v1.2.3 From 1b1b9fa708ea93635f341c086e264b01e3717a67 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Fri, 30 Oct 2015 17:28:55 -0400 Subject: new soledad-sync test this new test uses leap.soledad.client to perform an actual sync against the soledad server. closes: #7523 --- tests/helpers/client_side_db.py | 268 ++++++++++++++++++++++++++++++++++++++++ tests/helpers/soledad_sync.py | 123 +++++++++--------- tests/white-box/webapp.rb | 5 +- 3 files changed, 331 insertions(+), 65 deletions(-) create mode 100644 tests/helpers/client_side_db.py (limited to 'tests') diff --git a/tests/helpers/client_side_db.py b/tests/helpers/client_side_db.py new file mode 100644 index 00000000..f52354cc --- /dev/null +++ b/tests/helpers/client_side_db.py @@ -0,0 +1,268 @@ +import logging +import os +import argparse +import tempfile +import getpass +import requests +import srp._pysrp as srp +import binascii +import logging +import json +import time + +from twisted.internet import reactor +from twisted.internet.defer import inlineCallbacks + +from leap.soledad.client import Soledad +from leap.keymanager import KeyManager +from leap.keymanager.openpgp import OpenPGPKey + + +""" +Helper functions to give access to client-side Soledad database. +""" + + +# create a logger +logger = logging.getLogger(__name__) + +# DEBUG: enable debug logs +# LOG_FORMAT = '%(asctime)s %(message)s' +# logging.basicConfig(format=LOG_FORMAT, level=logging.DEBUG) + + +safe_unhexlify = lambda x: binascii.unhexlify(x) if ( + len(x) % 2 == 0) else binascii.unhexlify('0' + x) + + +def _fail(reason): + logger.error('Fail: ' + reason) + exit(2) + + +def _get_api_info(provider): + info = requests.get( + 'https://'+provider+'/provider.json', verify=False).json() + return info['api_uri'], info['api_version'] + + +def _login(username, passphrase, provider, api_uri, api_version): + usr = srp.User(username, passphrase, srp.SHA256, srp.NG_1024) + auth = None + try: + auth = _authenticate(api_uri, api_version, usr).json() + except requests.exceptions.ConnectionError: + _fail('Could not connect to server.') + if 'errors' in auth: + _fail(str(auth['errors'])) + return api_uri, api_version, auth + + +def _authenticate(api_uri, api_version, usr): + api_url = "%s/%s" % (api_uri, api_version) + session = requests.session() + uname, A = usr.start_authentication() + params = {'login': uname, 'A': binascii.hexlify(A)} + init = session.post( + api_url + '/sessions', data=params, verify=False).json() + if 'errors' in init: + _fail('test user not found') + M = usr.process_challenge( + safe_unhexlify(init['salt']), safe_unhexlify(init['B'])) + return session.put(api_url + '/sessions/' + uname, verify=False, + data={'client_auth': binascii.hexlify(M)}) + + +def _get_soledad_info(username, provider, passphrase, basedir): + api_uri, api_version = _get_api_info(provider) + auth = _login(username, passphrase, provider, api_uri, api_version) + # get soledad server url + service_url = '%s/%s/config/soledad-service.json' % \ + (api_uri, api_version) + soledad_hosts = requests.get(service_url, verify=False).json()['hosts'] + hostnames = soledad_hosts.keys() + # allow for choosing the host + host = hostnames[0] + if len(hostnames) > 1: + i = 1 + print "There are many available hosts:" + for h in hostnames: + print " (%d) %s.%s" % (i, h, provider) + i += 1 + choice = raw_input("Choose a host to use (default: 1): ") + if choice != '': + host = hostnames[int(choice) - 1] + server_url = 'https://%s:%d/user-%s' % \ + (soledad_hosts[host]['hostname'], soledad_hosts[host]['port'], + auth[2]['id']) + # get provider ca certificate + ca_cert = requests.get('https://%s/ca.crt' % provider, verify=False).text + cert_file = os.path.join(basedir, 'ca.crt') + with open(cert_file, 'w') as f: + f.write(ca_cert) + return auth[2]['id'], server_url, cert_file, auth[2]['token'] + + +def get_soledad_instance(uuid, passphrase, basedir, server_url, cert_file, + token): + # setup soledad info + logger.info('UUID is %s' % uuid) + logger.info('Server URL is %s' % server_url) + secrets_path = os.path.join( + basedir, '%s.secret' % uuid) + local_db_path = os.path.join( + basedir, '%s.db' % uuid) + # instantiate soledad + return Soledad( + uuid, + unicode(passphrase), + secrets_path=secrets_path, + local_db_path=local_db_path, + server_url=server_url, + cert_file=cert_file, + auth_token=token, + defer_encryption=True) + + +def _get_keymanager_instance(username, provider, soledad, token, + ca_cert_path=None, api_uri=None, api_version=None, + uid=None, gpgbinary=None): + return KeyManager( + "{username}@{provider}".format(username=username, provider=provider), + "http://uri", + soledad, + token=token, + ca_cert_path=ca_cert_path, + api_uri=api_uri, + api_version=api_version, + uid=uid, + gpgbinary=gpgbinary) + + + +def _get_passphrase(args): + passphrase = args.passphrase + if passphrase is None: + passphrase = getpass.getpass( + 'Password for %s@%s: ' % (args.username, args.provider)) + return passphrase + + +def _get_basedir(args): + basedir = args.basedir + if basedir is None: + basedir = tempfile.mkdtemp() + elif not os.path.isdir(basedir): + os.mkdir(basedir) + logger.info('Using %s as base directory.' % basedir) + return basedir + + +@inlineCallbacks +def _export_key(args, km, fname, private=False): + address = args.username + "@" + args.provider + pkey = yield km.get_key( + address, OpenPGPKey, private=private, fetch_remote=False) + with open(args.export_private_key, "w") as f: + f.write(pkey.key_data) + + +@inlineCallbacks +def _export_incoming_messages(soledad, directory): + yield soledad.create_index("by-incoming", "bool(incoming)") + docs = yield soledad.get_from_index("by-incoming", '1') + i = 1 + for doc in docs: + with open(os.path.join(directory, "message_%d.gpg" % i), "w") as f: + f.write(doc.content["_enc_json"]) + i += 1 + + +@inlineCallbacks +def _get_all_docs(soledad): + _, docs = yield soledad.get_all_docs() + for doc in docs: + print json.dumps(doc.content, indent=4) + + +# main program + +@inlineCallbacks +def _main(soledad, km, args): + try: + if args.create_docs: + for i in xrange(args.create_docs): + t = time.time() + logger.debug( + "Creating doc %d/%d..." % (i + 1, args.create_docs)) + content = { + 'datetime': time.strftime( + "%Y-%m-%d %H:%M:%S", time.gmtime(t)), + 'timestamp': t, + 'index': i, + 'total': args.create_docs, + } + yield soledad.create_doc(content) + if args.sync: + yield soledad.sync() + if args.repeat_sync: + old_gen = 0 + new_gen = yield soledad.sync() + while old_gen != new_gen: + old_gen = new_gen + new_gen = yield soledad.sync() + if args.get_all_docs: + yield _get_all_docs(soledad) + if args.export_private_key: + yield _export_key(args, km, args.export_private_key, private=True) + if args.export_public_key: + yield _export_key(args, km, args.expoert_public_key, private=False) + if args.export_incoming_messages: + yield _export_incoming_messages( + soledad, args.export_incoming_messages) + except Exception as e: + logger.error(e) + finally: + soledad.close() + reactor.callWhenRunning(reactor.stop) + + +if __name__ == '__main__': + args = _parse_args() + passphrase = _get_passphrase(args) + basedir = _get_basedir(args) + + if not args.use_auth_data: + # get auth data from server + uuid, server_url, cert_file, token = \ + _get_soledad_info( + args.username, args.provider, passphrase, basedir) + else: + # load auth data from file + with open(args.use_auth_data) as f: + auth_data = json.loads(f.read()) + uuid = auth_data['uuid'] + server_url = auth_data['server_url'] + cert_file = auth_data['cert_file'] + token = auth_data['token'] + + # export auth data to a file + if args.export_auth_data: + with open(args.export_auth_data, "w") as f: + f.write(json.dumps({ + 'uuid': uuid, + 'server_url': server_url, + 'cert_file': cert_file, + 'token': token, + })) + + soledad = _get_soledad_instance( + uuid, passphrase, basedir, server_url, cert_file, token) + km = _get_keymanager_instance( + args.username, + args.provider, + soledad, + token, + uid=uuid) + _main(soledad, km, args) + reactor.run() diff --git a/tests/helpers/soledad_sync.py b/tests/helpers/soledad_sync.py index 2fb865fc..a1cea069 100755 --- a/tests/helpers/soledad_sync.py +++ b/tests/helpers/soledad_sync.py @@ -1,78 +1,75 @@ #!/usr/bin/env python +""" +soledad_sync.py -# -# Test Soledad sync -# -# This script performs a slightly modified U1DB sync to the Soledad server and -# returns whether that sync was successful or not. -# -# It takes three arguments: -# -# uuid -- uuid of the user to sync -# token -- a valid session token -# server -- the url of the soledad server we should connect to -# -# For example: -# -# soledad_sync.py f6bef0586fcfdb8705e26a58f2d9e580 uYO-4ucEJFksJ6afjmcYwIyap2vW7bv6uLxk0w_RfCc https://199.119.112.9:2323/user-f6bef0586fcfdb8705e26a58f2d9e580 -# +This script exercises soledad synchronization. +Its exit code is 0 if the sync took place correctly, 1 otherwise. +It takes 5 arguments: + + uuid: uuid of the user to sync + token: a valid session token + server: the url of the soledad server we should connect to + cert_file: the file containing the certificate for the CA that signed the + cert for the soledad server. + password: the password for the user to sync + +__author__: kali@leap.se +""" import os import sys -import traceback import tempfile -import shutil -import u1db -from u1db.remote.http_target import HTTPSyncTarget +# This is needed because the twisted shipped with wheezy is too old +# to do proper ssl verification. +os.environ['SKIP_TWISTED_SSL_CHECK'] = '1' -# -# monkey patch U1DB's HTTPSyncTarget to perform token based auth -# +from twisted.internet import defer, reactor -def set_token_credentials(self, uuid, token): - self._creds = {'token': (uuid, token)} +from client_side_db import get_soledad_instance +from leap.common.events import flags -def _sign_request(self, method, url_query, params): - uuid, token = self._creds['token'] - auth = '%s:%s' % (uuid, token) - return [('Authorization', 'Token %s' % auth.encode('base64')[:-1])] +flags.set_events_enabled(False) -HTTPSyncTarget.set_token_credentials = set_token_credentials -HTTPSyncTarget._sign_request = _sign_request +NUMDOCS = 1 +USAGE = "Usage: %s uuid token server cert_file password" % sys.argv[0] -# -# Create a temporary local u1db replica and attempt to sync to it. -# Returns a failure message if something went wrong. -# -def soledad_sync(uuid, token, server): - tempdir = tempfile.mkdtemp() - try: - db = u1db.open(os.path.join(tempdir, '%s.db' % uuid), True) - creds = {'token': {'uuid': uuid, 'token': token}} - db.sync(server, creds=creds, autocreate=False) - finally: - shutil.rmtree(tempdir) - -# -# exit codes: -# -# 0 - OK -# 1 - WARNING -# 2 - ERROR -# +def bail(msg, exitcode): + print "[!] %s" % msg + sys.exit(exitcode) + + +def create_docs(soledad): + """ + Populates the soledad database with dummy messages, so we can exercise + sending payloads during the sync. + """ + deferreds = [] + for index in xrange(NUMDOCS): + deferreds.append(soledad.create_doc({'payload': 'dummy'})) + return defer.gatherResults(deferreds) + +# main program if __name__ == '__main__': - try: - uuid, token, server = sys.argv[1:] - result = soledad_sync(uuid, token, server) - if result is None: - exit(0) - else: - print(result) - exit(1) - except Exception as exc: - print(exc.message or str(exc)) - traceback.print_exc(file=sys.stdout) - exit(2) + + tempdir = tempfile.mkdtemp() + if len(sys.argv) < 6: + bail(USAGE, 2) + uuid, token, server, cert_file, passphrase = sys.argv[1:] + s = get_soledad_instance( + uuid, passphrase, tempdir, server, cert_file, token) + + def onSyncDone(sync_result): + print "SYNC_RESULT:", sync_result + s.close() + reactor.stop() + + def start_sync(): + d = create_docs(s) + d.addCallback(lambda _: s.sync()) + d.addCallback(onSyncDone) + + reactor.callWhenRunning(start_sync) + reactor.run() diff --git a/tests/white-box/webapp.rb b/tests/white-box/webapp.rb index 8be6bde2..e689c143 100644 --- a/tests/white-box/webapp.rb +++ b/tests/white-box/webapp.rb @@ -57,10 +57,11 @@ class Webapp < LeapTest soledad_server = pick_soledad_server(soledad_config) if soledad_server assert_tmp_user do |user| - assert_user_db_exists(user) command = File.expand_path "../../helpers/soledad_sync.py", __FILE__ soledad_url = "https://#{soledad_server}/user-#{user.id}" - assert_run "#{command} #{user.id} #{user.session_token} #{soledad_url}" + soledad_cert = "/usr/local/share/ca-certificates/leap_ca.crt" + assert_run "#{command} #{user.id} #{user.session_token} #{soledad_url} #{soledad_cert} #{user.password}" + assert_user_db_exists(user) pass end end -- cgit v1.2.3 From 6d9dc1a9bed8da7827e6f7cf80fe2ecff49ca308 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Fri, 13 Nov 2015 12:06:18 -0400 Subject: remove keymanager --- tests/helpers/client_side_db.py | 107 ---------------------------------------- 1 file changed, 107 deletions(-) (limited to 'tests') diff --git a/tests/helpers/client_side_db.py b/tests/helpers/client_side_db.py index f52354cc..d2a4bbcb 100644 --- a/tests/helpers/client_side_db.py +++ b/tests/helpers/client_side_db.py @@ -1,28 +1,21 @@ import logging import os -import argparse import tempfile import getpass import requests import srp._pysrp as srp import binascii -import logging import json -import time -from twisted.internet import reactor from twisted.internet.defer import inlineCallbacks from leap.soledad.client import Soledad -from leap.keymanager import KeyManager -from leap.keymanager.openpgp import OpenPGPKey """ Helper functions to give access to client-side Soledad database. """ - # create a logger logger = logging.getLogger(__name__) @@ -123,23 +116,6 @@ def get_soledad_instance(uuid, passphrase, basedir, server_url, cert_file, auth_token=token, defer_encryption=True) - -def _get_keymanager_instance(username, provider, soledad, token, - ca_cert_path=None, api_uri=None, api_version=None, - uid=None, gpgbinary=None): - return KeyManager( - "{username}@{provider}".format(username=username, provider=provider), - "http://uri", - soledad, - token=token, - ca_cert_path=ca_cert_path, - api_uri=api_uri, - api_version=api_version, - uid=uid, - gpgbinary=gpgbinary) - - - def _get_passphrase(args): passphrase = args.passphrase if passphrase is None: @@ -183,86 +159,3 @@ def _get_all_docs(soledad): _, docs = yield soledad.get_all_docs() for doc in docs: print json.dumps(doc.content, indent=4) - - -# main program - -@inlineCallbacks -def _main(soledad, km, args): - try: - if args.create_docs: - for i in xrange(args.create_docs): - t = time.time() - logger.debug( - "Creating doc %d/%d..." % (i + 1, args.create_docs)) - content = { - 'datetime': time.strftime( - "%Y-%m-%d %H:%M:%S", time.gmtime(t)), - 'timestamp': t, - 'index': i, - 'total': args.create_docs, - } - yield soledad.create_doc(content) - if args.sync: - yield soledad.sync() - if args.repeat_sync: - old_gen = 0 - new_gen = yield soledad.sync() - while old_gen != new_gen: - old_gen = new_gen - new_gen = yield soledad.sync() - if args.get_all_docs: - yield _get_all_docs(soledad) - if args.export_private_key: - yield _export_key(args, km, args.export_private_key, private=True) - if args.export_public_key: - yield _export_key(args, km, args.expoert_public_key, private=False) - if args.export_incoming_messages: - yield _export_incoming_messages( - soledad, args.export_incoming_messages) - except Exception as e: - logger.error(e) - finally: - soledad.close() - reactor.callWhenRunning(reactor.stop) - - -if __name__ == '__main__': - args = _parse_args() - passphrase = _get_passphrase(args) - basedir = _get_basedir(args) - - if not args.use_auth_data: - # get auth data from server - uuid, server_url, cert_file, token = \ - _get_soledad_info( - args.username, args.provider, passphrase, basedir) - else: - # load auth data from file - with open(args.use_auth_data) as f: - auth_data = json.loads(f.read()) - uuid = auth_data['uuid'] - server_url = auth_data['server_url'] - cert_file = auth_data['cert_file'] - token = auth_data['token'] - - # export auth data to a file - if args.export_auth_data: - with open(args.export_auth_data, "w") as f: - f.write(json.dumps({ - 'uuid': uuid, - 'server_url': server_url, - 'cert_file': cert_file, - 'token': token, - })) - - soledad = _get_soledad_instance( - uuid, passphrase, basedir, server_url, cert_file, token) - km = _get_keymanager_instance( - args.username, - args.provider, - soledad, - token, - uid=uuid) - _main(soledad, km, args) - reactor.run() -- cgit v1.2.3 From 675f826d4a85c1cd26e30d0f8ef52d5b592c0d1c Mon Sep 17 00:00:00 2001 From: varac Date: Fri, 6 Nov 2015 00:16:24 +0100 Subject: [bug] [jessie] check for 1 stunnel instance only - Resolves: #7574 --- tests/helpers/os_helper.rb | 7 +++++-- tests/white-box/network.rb | 11 +++++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) (limited to 'tests') diff --git a/tests/helpers/os_helper.rb b/tests/helpers/os_helper.rb index aad67dda..c57300e2 100644 --- a/tests/helpers/os_helper.rb +++ b/tests/helpers/os_helper.rb @@ -9,7 +9,10 @@ class LeapTest output.each_line.map{|line| pid = line.split(' ')[0] process = line.gsub(/(#{pid} |\n)/, '') - if process =~ /pgrep --full --list-name/ + # filter out pgrep cmd itself + # on wheezy hosts, the "process" var contains the whole cmd including all parameters + # on jessie hosts, it only contains the first cmd (which is the default sheel invoked by 'sh') + if process =~ /^sh/ nil else {:pid => pid, :process => process} @@ -35,4 +38,4 @@ class LeapTest end end -end \ No newline at end of file +end diff --git a/tests/white-box/network.rb b/tests/white-box/network.rb index acb5c5e6..382f857b 100644 --- a/tests/white-box/network.rb +++ b/tests/white-box/network.rb @@ -28,11 +28,18 @@ class Network < LeapTest def test_02_Is_stunnel_running? ignore unless $node['stunnel'] good_stunnel_pids = [] + release = `facter lsbmajdistrelease` + if release.to_i > 7 + # on jessie, there is only one stunnel proc running instead of 6 + expected = 1 + else + expected = 6 + end $node['stunnel']['clients'].each do |stunnel_type, stunnel_configs| stunnel_configs.each do |stunnel_name, stunnel_conf| config_file_name = "/etc/stunnel/#{stunnel_name}.conf" processes = pgrep(config_file_name) - assert_equal 6, processes.length, "There should be six stunnel processes running for `#{config_file_name}`" + assert_equal expected, processes.length, "There should be #{expected} stunnel processes running for `#{config_file_name}`" good_stunnel_pids += processes.map{|ps| ps[:pid]} assert port = stunnel_conf['accept_port'], 'Field `accept_port` must be present in `stunnel` property.' assert_tcp_socket('localhost', port) @@ -41,7 +48,7 @@ class Network < LeapTest $node['stunnel']['servers'].each do |stunnel_name, stunnel_conf| config_file_name = "/etc/stunnel/#{stunnel_name}.conf" processes = pgrep(config_file_name) - assert_equal 6, processes.length, "There should be six stunnel processes running for `#{config_file_name}`" + assert_equal expected, processes.length, "There should be #{expected} stunnel processes running for `#{config_file_name}`" good_stunnel_pids += processes.map{|ps| ps[:pid]} assert accept_port = stunnel_conf['accept_port'], "Field `accept` must be present in property `stunnel.servers.#{stunnel_name}`" assert_tcp_socket('localhost', accept_port) -- cgit v1.2.3 From 75341eeb905e9c7312232d8c9c4077a358b8cb20 Mon Sep 17 00:00:00 2001 From: varac Date: Fri, 6 Nov 2015 00:16:24 +0100 Subject: [bug] [jessie] check for 1 stunnel instance only - Resolves: #7574 --- tests/helpers/os_helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests') diff --git a/tests/helpers/os_helper.rb b/tests/helpers/os_helper.rb index c57300e2..da9ac843 100644 --- a/tests/helpers/os_helper.rb +++ b/tests/helpers/os_helper.rb @@ -38,4 +38,4 @@ class LeapTest end end -end +end \ No newline at end of file -- cgit v1.2.3 From 9f12fd1b52ad79873a699b9d3faa29ff3e3c2677 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Thu, 19 Nov 2015 08:44:56 -0400 Subject: [bug] do not fail if no requests/srp dependencies present client_side_db helper has some extra functions that can be useful in the future for further tests, but right now it shouldn't depend on requests, since it already get all the relevant soledad info passed as arguments. for the same reason, it doesn't need to depend on srp, since we pass the token. --- tests/helpers/client_side_db.py | 50 +++++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 22 deletions(-) (limited to 'tests') diff --git a/tests/helpers/client_side_db.py b/tests/helpers/client_side_db.py index d2a4bbcb..2f8c220f 100644 --- a/tests/helpers/client_side_db.py +++ b/tests/helpers/client_side_db.py @@ -2,11 +2,15 @@ import logging import os import tempfile import getpass -import requests -import srp._pysrp as srp import binascii import json +try: + import requests + import srp._pysrp as srp +except ImportError: + pass + from twisted.internet.defer import inlineCallbacks from leap.soledad.client import Soledad @@ -14,6 +18,7 @@ from leap.soledad.client import Soledad """ Helper functions to give access to client-side Soledad database. +Copied over from soledad/scripts folder. """ # create a logger @@ -33,6 +38,27 @@ def _fail(reason): exit(2) +def get_soledad_instance(uuid, passphrase, basedir, server_url, cert_file, + token): + # setup soledad info + logger.info('UUID is %s' % uuid) + logger.info('Server URL is %s' % server_url) + secrets_path = os.path.join( + basedir, '%s.secret' % uuid) + local_db_path = os.path.join( + basedir, '%s.db' % uuid) + # instantiate soledad + return Soledad( + uuid, + unicode(passphrase), + secrets_path=secrets_path, + local_db_path=local_db_path, + server_url=server_url, + cert_file=cert_file, + auth_token=token, + defer_encryption=True) + + def _get_api_info(provider): info = requests.get( 'https://'+provider+'/provider.json', verify=False).json() @@ -96,26 +122,6 @@ def _get_soledad_info(username, provider, passphrase, basedir): return auth[2]['id'], server_url, cert_file, auth[2]['token'] -def get_soledad_instance(uuid, passphrase, basedir, server_url, cert_file, - token): - # setup soledad info - logger.info('UUID is %s' % uuid) - logger.info('Server URL is %s' % server_url) - secrets_path = os.path.join( - basedir, '%s.secret' % uuid) - local_db_path = os.path.join( - basedir, '%s.db' % uuid) - # instantiate soledad - return Soledad( - uuid, - unicode(passphrase), - secrets_path=secrets_path, - local_db_path=local_db_path, - server_url=server_url, - cert_file=cert_file, - auth_token=token, - defer_encryption=True) - def _get_passphrase(args): passphrase = args.passphrase if passphrase is None: -- cgit v1.2.3 From f59d938c5744dcb2bc44412d684c10acf4a35936 Mon Sep 17 00:00:00 2001 From: varac Date: Thu, 19 Nov 2015 15:20:28 +0100 Subject: [feat] Check for postfwd procs on mx nodes --- tests/white-box/mx.rb | 3 +++ 1 file changed, 3 insertions(+) (limited to 'tests') diff --git a/tests/white-box/mx.rb b/tests/white-box/mx.rb index 794a9a41..f49d2ab4 100644 --- a/tests/white-box/mx.rb +++ b/tests/white-box/mx.rb @@ -34,6 +34,9 @@ class Mx < LeapTest def test_03_Are_MX_daemons_running? assert_running 'leap_mx' assert_running '/usr/lib/postfix/master' + assert_running '/usr/sbin/postfwd' + assert_running 'postfwd2::cache' + assert_running 'postfwd2::policy' assert_running '/usr/sbin/unbound' pass end -- cgit v1.2.3 From 58c4e6878561dc9772070e3ca9b666b9e1abdc7a Mon Sep 17 00:00:00 2001 From: varac Date: Mon, 30 Nov 2015 14:50:13 +0100 Subject: Disable webapp usercreation and soledad sync test --- tests/white-box/webapp.rb | 29 ----------------------------- 1 file changed, 29 deletions(-) (limited to 'tests') diff --git a/tests/white-box/webapp.rb b/tests/white-box/webapp.rb index e689c143..48507521 100644 --- a/tests/white-box/webapp.rb +++ b/tests/white-box/webapp.rb @@ -41,35 +41,6 @@ class Webapp < LeapTest pass end - def test_05_Can_create_and_authenticate_and_delete_user_via_API? - if property('webapp.allow_registration') - assert_tmp_user - pass - else - skip "New user registrations are disabled." - end - end - - def test_06_Can_sync_Soledad? - return unless property('webapp.allow_registration') - soledad_config = property('definition_files.soledad_service') - if soledad_config && !soledad_config.empty? - soledad_server = pick_soledad_server(soledad_config) - if soledad_server - assert_tmp_user do |user| - command = File.expand_path "../../helpers/soledad_sync.py", __FILE__ - soledad_url = "https://#{soledad_server}/user-#{user.id}" - soledad_cert = "/usr/local/share/ca-certificates/leap_ca.crt" - assert_run "#{command} #{user.id} #{user.session_token} #{soledad_url} #{soledad_cert} #{user.password}" - assert_user_db_exists(user) - pass - end - end - else - skip 'No soledad service configuration' - end - end - private def url_options -- cgit v1.2.3 From 4fdcb4f126b36170c290f4059a8b019b8de5c9eb Mon Sep 17 00:00:00 2001 From: Christoph Kluenter Date: Tue, 1 Dec 2015 14:56:24 +0100 Subject: Revert "Disable webapp usercreation and soledad sync test" This reverts commit 58c4e6878561dc9772070e3ca9b666b9e1abdc7a. The test was fine. The assert_tmp_user was testing the database without using credentials. will be fixed in next commit --- tests/white-box/webapp.rb | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'tests') diff --git a/tests/white-box/webapp.rb b/tests/white-box/webapp.rb index 48507521..e689c143 100644 --- a/tests/white-box/webapp.rb +++ b/tests/white-box/webapp.rb @@ -41,6 +41,35 @@ class Webapp < LeapTest pass end + def test_05_Can_create_and_authenticate_and_delete_user_via_API? + if property('webapp.allow_registration') + assert_tmp_user + pass + else + skip "New user registrations are disabled." + end + end + + def test_06_Can_sync_Soledad? + return unless property('webapp.allow_registration') + soledad_config = property('definition_files.soledad_service') + if soledad_config && !soledad_config.empty? + soledad_server = pick_soledad_server(soledad_config) + if soledad_server + assert_tmp_user do |user| + command = File.expand_path "../../helpers/soledad_sync.py", __FILE__ + soledad_url = "https://#{soledad_server}/user-#{user.id}" + soledad_cert = "/usr/local/share/ca-certificates/leap_ca.crt" + assert_run "#{command} #{user.id} #{user.session_token} #{soledad_url} #{soledad_cert} #{user.password}" + assert_user_db_exists(user) + pass + end + end + else + skip 'No soledad service configuration' + end + end + private def url_options -- cgit v1.2.3 From b610c85e9872b5f9347a52af1fe6acb9a2662530 Mon Sep 17 00:00:00 2001 From: Micah Date: Thu, 26 Nov 2015 15:50:17 -0500 Subject: Check for clamav processes on mx nodes (#7648) Change-Id: I751985c0537d430b568a670a2f70d1906b0f0f35 --- tests/white-box/mx.rb | 3 +++ 1 file changed, 3 insertions(+) (limited to 'tests') diff --git a/tests/white-box/mx.rb b/tests/white-box/mx.rb index f49d2ab4..8b5cc485 100644 --- a/tests/white-box/mx.rb +++ b/tests/white-box/mx.rb @@ -38,6 +38,9 @@ class Mx < LeapTest assert_running 'postfwd2::cache' assert_running 'postfwd2::policy' assert_running '/usr/sbin/unbound' + assert_running '^/usr/sbin/clamd -c /etc/clamav/clamd.conf$' + assert_running '^/usr/sbin/clamav-milter --config-file=/etc/clamav/clamav-milter.conf$' + assert_running '^/usr/bin/freshclam -d --quiet --config-file=/etc/clamav/freshclam.conf$' pass end -- cgit v1.2.3 From d610405e585966406fd9813423e300a39ef300b5 Mon Sep 17 00:00:00 2001 From: Christoph Kluenter Date: Tue, 1 Dec 2015 15:02:02 +0100 Subject: don't check in database if user was deleted. we already check if the webapp returned success when it deleted the user. If the webapp had failed it would not have returned success. leap_web has tests that prove this. This fixes https://leap.se/code/issues/7625 --- tests/helpers/bonafide_helper.rb | 8 -------- 1 file changed, 8 deletions(-) (limited to 'tests') diff --git a/tests/helpers/bonafide_helper.rb b/tests/helpers/bonafide_helper.rb index 82db3973..20c3ca8d 100644 --- a/tests/helpers/bonafide_helper.rb +++ b/tests/helpers/bonafide_helper.rb @@ -98,14 +98,6 @@ class LeapTest assert(response = JSON.parse(body), 'Delete response should be JSON') assert(response["success"], 'Deleting user should be a success') end - domain = property('domain.full_suffix') - identities_url = couchdb_url("/identities/_design/Identity/_view/by_address?key=%22#{user.username}@#{domain}%22") - get(identities_url) do |body, response, error| - assert error.nil?, "Error checking identities db: #{error}" - assert response.code.to_i == 200, "Unable to check that user identity was deleted: HTTP response from API should have code 200, was #{response.code} #{error} #{body}" - assert(response = JSON.parse(body), 'Couch response should be JSON') - assert response['rows'].empty?, "Identity should have been deleted for test user #{user.username} (id #{user.id}), but was not! Response was: #{body}." - end end end -- cgit v1.2.3 From f85e0ad1be2675b1429a554d83dabaa3aec0d85e Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Wed, 2 Dec 2015 16:53:20 -0400 Subject: [bug] catch 401 return code instead of 200 for user-db-created check --- tests/white-box/webapp.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'tests') diff --git a/tests/white-box/webapp.rb b/tests/white-box/webapp.rb index e689c143..4a669db3 100644 --- a/tests/white-box/webapp.rb +++ b/tests/white-box/webapp.rb @@ -119,7 +119,9 @@ class Webapp < LeapTest sleep 0.2 get(couchdb_url(url)) do |body, response, error| last_body, last_response, last_error = body, response, error - if response.code.to_i == 200 + # After moving to couchdb, webapp user is not allowed to Read user dbs, + # but the return code for non-existent databases is 404. See #7674 + if response.code.to_i == 401 return end end -- cgit v1.2.3 From fa90ab06aa09224d5a1fbac69c9bc0f067099206 Mon Sep 17 00:00:00 2001 From: Micah Date: Mon, 30 Nov 2015 12:48:10 -0500 Subject: improve whitebox tests to match on more specific processes (#7655, #7676) Change-Id: I9f267ba38130ceb308d284c926b14d2cee9f87be --- tests/white-box/mx.rb | 18 +++++++++--------- tests/white-box/openvpn.rb | 6 +++--- tests/white-box/soledad.rb | 2 +- tests/white-box/webapp.rb | 4 ++-- 4 files changed, 15 insertions(+), 15 deletions(-) (limited to 'tests') diff --git a/tests/white-box/mx.rb b/tests/white-box/mx.rb index 8b5cc485..ba523fe0 100644 --- a/tests/white-box/mx.rb +++ b/tests/white-box/mx.rb @@ -32,15 +32,15 @@ class Mx < LeapTest end def test_03_Are_MX_daemons_running? - assert_running 'leap_mx' - assert_running '/usr/lib/postfix/master' - assert_running '/usr/sbin/postfwd' - assert_running 'postfwd2::cache' - assert_running 'postfwd2::policy' - assert_running '/usr/sbin/unbound' - assert_running '^/usr/sbin/clamd -c /etc/clamav/clamd.conf$' - assert_running '^/usr/sbin/clamav-milter --config-file=/etc/clamav/clamav-milter.conf$' - assert_running '^/usr/bin/freshclam -d --quiet --config-file=/etc/clamav/freshclam.conf$' + assert_running '.*/usr/bin/twistd.*leap_mx.tac' + assert_running '^/usr/lib/postfix/master$' + assert_running '^/usr/sbin/postfwd' + assert_running 'postfwd2::cache$' + assert_running 'postfwd2::policy$' + assert_running '^/usr/sbin/unbound$' + assert_running '^/usr/sbin/clamd' + assert_running '^/usr/sbin/clamav-milter' + assert_running '^/usr/bin/freshclam' pass end diff --git a/tests/white-box/openvpn.rb b/tests/white-box/openvpn.rb index 23a40426..170d4503 100644 --- a/tests/white-box/openvpn.rb +++ b/tests/white-box/openvpn.rb @@ -7,9 +7,9 @@ class OpenVPN < LeapTest end def test_01_Are_daemons_running? - assert_running '/usr/sbin/openvpn .* /etc/openvpn/tcp_config.conf' - assert_running '/usr/sbin/openvpn .* /etc/openvpn/udp_config.conf' - assert_running '/usr/sbin/unbound' + assert_running '^/usr/sbin/openvpn .* /etc/openvpn/tcp_config.conf$' + assert_running '^/usr/sbin/openvpn .* /etc/openvpn/udp_config.conf$' + assert_running '^/usr/sbin/unbound$' pass end diff --git a/tests/white-box/soledad.rb b/tests/white-box/soledad.rb index 5a13e4a6..d41bee58 100644 --- a/tests/white-box/soledad.rb +++ b/tests/white-box/soledad.rb @@ -10,7 +10,7 @@ class Soledad < LeapTest end def test_00_Is_Soledad_running? - assert_running 'soledad' + assert_running '.*/usr/bin/twistd.*--wsgi=leap.soledad.server.application' pass end diff --git a/tests/white-box/webapp.rb b/tests/white-box/webapp.rb index 4a669db3..54c00b89 100644 --- a/tests/white-box/webapp.rb +++ b/tests/white-box/webapp.rb @@ -27,8 +27,8 @@ class Webapp < LeapTest end def test_03_Are_daemons_running? - assert_running '/usr/sbin/apache2' - assert_running '/usr/bin/nickserver' + assert_running '^/usr/sbin/apache2' + assert_running '^/usr/bin/ruby /usr/bin/nickserver' pass end -- cgit v1.2.3 From dc853191a92cb22641f65b1099d69630ca1e79f4 Mon Sep 17 00:00:00 2001 From: Christoph Kluenter Date: Mon, 7 Dec 2015 15:23:54 +0100 Subject: tac file was renamed --- tests/white-box/mx.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests') diff --git a/tests/white-box/mx.rb b/tests/white-box/mx.rb index ba523fe0..336f78a4 100644 --- a/tests/white-box/mx.rb +++ b/tests/white-box/mx.rb @@ -32,7 +32,7 @@ class Mx < LeapTest end def test_03_Are_MX_daemons_running? - assert_running '.*/usr/bin/twistd.*leap_mx.tac' + assert_running '.*/usr/bin/twistd.*mx.tac' assert_running '^/usr/lib/postfix/master$' assert_running '^/usr/sbin/postfwd' assert_running 'postfwd2::cache$' -- cgit v1.2.3 From c010d7dd1307e5cdb344b25fea078af8108df20a Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Mon, 25 Jan 2016 12:01:39 -0400 Subject: [bug] add errback to log failure --- tests/helpers/soledad_sync.py | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'tests') diff --git a/tests/helpers/soledad_sync.py b/tests/helpers/soledad_sync.py index a1cea069..b8e8fbc9 100755 --- a/tests/helpers/soledad_sync.py +++ b/tests/helpers/soledad_sync.py @@ -25,6 +25,7 @@ import tempfile os.environ['SKIP_TWISTED_SSL_CHECK'] = '1' from twisted.internet import defer, reactor +from twisted.python import log from client_side_db import get_soledad_instance from leap.common.events import flags @@ -66,10 +67,15 @@ if __name__ == '__main__': s.close() reactor.stop() + def log_and_exit(f): + log.err(f) + reactor.stop() + def start_sync(): d = create_docs(s) d.addCallback(lambda _: s.sync()) d.addCallback(onSyncDone) + d.addErrback(log_and_exit) reactor.callWhenRunning(start_sync) reactor.run() -- cgit v1.2.3 From 393d46feb9890a87c5764f40b61c51d03fe0a4fe Mon Sep 17 00:00:00 2001 From: elijah Date: Wed, 24 Feb 2016 11:10:25 -0800 Subject: check server cert expiry in tests, closes #7910 --- tests/white-box/network.rb | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'tests') diff --git a/tests/white-box/network.rb b/tests/white-box/network.rb index 382f857b..2436230b 100644 --- a/tests/white-box/network.rb +++ b/tests/white-box/network.rb @@ -1,4 +1,5 @@ require 'socket' +require 'openssl' raise SkipTest if $node["dummy"] @@ -69,4 +70,21 @@ class Network < LeapTest pass end + THIRTY_DAYS = 60*60*24*30 + + def test_04_Are_server_certificates_valid? + cert_paths = ["/etc/x509/certs/leap_commercial.crt", "/etc/x509/certs/leap.crt"] + cert_paths.each do |cert_path| + if File.exists?(cert_path) + cert = OpenSSL::X509::Certificate.new(File.read(cert_path)) + if cert.not_after > Time.now + fail "The certificate #{cert_path} expired on #{cert.not_after}" + elsif cert.not_after > Time.now + THIRTY_DAYS + fail "The certificate #{cert_path} will expire soon, on #{cert.not_after}" + end + end + end + pass + end + end -- cgit v1.2.3 From 25204787dfa9fd3486a9244de56d92fe3d5bfb99 Mon Sep 17 00:00:00 2001 From: elijah Date: Wed, 24 Feb 2016 13:08:19 -0800 Subject: fix time comparison bug in network test --- tests/white-box/network.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'tests') diff --git a/tests/white-box/network.rb b/tests/white-box/network.rb index 2436230b..436fc8a8 100644 --- a/tests/white-box/network.rb +++ b/tests/white-box/network.rb @@ -77,9 +77,9 @@ class Network < LeapTest cert_paths.each do |cert_path| if File.exists?(cert_path) cert = OpenSSL::X509::Certificate.new(File.read(cert_path)) - if cert.not_after > Time.now + if Time.now > cert.not_after fail "The certificate #{cert_path} expired on #{cert.not_after}" - elsif cert.not_after > Time.now + THIRTY_DAYS + elsif Time.now + THIRTY_DAYS > cert.not_after fail "The certificate #{cert_path} will expire soon, on #{cert.not_after}" end end -- cgit v1.2.3 From 2599431bb42380f5d8d45769c9a56175f8137267 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Thu, 25 Feb 2016 11:59:39 -0400 Subject: [bug] remove tempdir after soledad sync test Closes: #7921 --- tests/helpers/soledad_sync.py | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'tests') diff --git a/tests/helpers/soledad_sync.py b/tests/helpers/soledad_sync.py index b8e8fbc9..f4fc81ae 100755 --- a/tests/helpers/soledad_sync.py +++ b/tests/helpers/soledad_sync.py @@ -17,6 +17,7 @@ It takes 5 arguments: __author__: kali@leap.se """ import os +import shutil import sys import tempfile @@ -56,8 +57,13 @@ def create_docs(soledad): if __name__ == '__main__': tempdir = tempfile.mkdtemp() + + def rm_tempdir(): + shutil.rmtree(tempdir) + if len(sys.argv) < 6: bail(USAGE, 2) + uuid, token, server, cert_file, passphrase = sys.argv[1:] s = get_soledad_instance( uuid, passphrase, tempdir, server, cert_file, token) @@ -65,10 +71,12 @@ if __name__ == '__main__': def onSyncDone(sync_result): print "SYNC_RESULT:", sync_result s.close() + rm_tempdir() reactor.stop() def log_and_exit(f): log.err(f) + rm_tempdir() reactor.stop() def start_sync(): -- cgit v1.2.3 From bfca1b32e33ccd0f5130bae546148529a3642cc3 Mon Sep 17 00:00:00 2001 From: elijah Date: Fri, 26 Feb 2016 09:48:09 -0800 Subject: skip clamd process test if clamav sig file has not yet been downloaded, closes #7683 --- tests/white-box/mx.rb | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'tests') diff --git a/tests/white-box/mx.rb b/tests/white-box/mx.rb index 336f78a4..9f577516 100644 --- a/tests/white-box/mx.rb +++ b/tests/white-box/mx.rb @@ -38,9 +38,13 @@ class Mx < LeapTest assert_running 'postfwd2::cache$' assert_running 'postfwd2::policy$' assert_running '^/usr/sbin/unbound$' - assert_running '^/usr/sbin/clamd' - assert_running '^/usr/sbin/clamav-milter' - assert_running '^/usr/bin/freshclam' + if File.exists?('/var/lib/clamav/daily.cld') + assert_running '^/usr/sbin/clamd' + assert_running '^/usr/sbin/clamav-milter' + assert_running '^/usr/bin/freshclam' + else + skip "The clamav signature file (/var/lib/clamav/daily.cld) has yet to be downloaded, so clamd is not running." + end pass end -- cgit v1.2.3 From 61c2d2c6a584eba1cd757fb7540fc78a8d191e11 Mon Sep 17 00:00:00 2001 From: elijah Date: Tue, 15 Mar 2016 11:34:05 -0700 Subject: tabs are evil. please don't use them. --- tests/white-box/webapp.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'tests') diff --git a/tests/white-box/webapp.rb b/tests/white-box/webapp.rb index 54c00b89..2d4a51f6 100644 --- a/tests/white-box/webapp.rb +++ b/tests/white-box/webapp.rb @@ -59,7 +59,7 @@ class Webapp < LeapTest assert_tmp_user do |user| command = File.expand_path "../../helpers/soledad_sync.py", __FILE__ soledad_url = "https://#{soledad_server}/user-#{user.id}" - soledad_cert = "/usr/local/share/ca-certificates/leap_ca.crt" + soledad_cert = "/usr/local/share/ca-certificates/leap_ca.crt" assert_run "#{command} #{user.id} #{user.session_token} #{soledad_url} #{soledad_cert} #{user.password}" assert_user_db_exists(user) pass @@ -119,8 +119,8 @@ class Webapp < LeapTest sleep 0.2 get(couchdb_url(url)) do |body, response, error| last_body, last_response, last_error = body, response, error - # After moving to couchdb, webapp user is not allowed to Read user dbs, - # but the return code for non-existent databases is 404. See #7674 + # After moving to couchdb, webapp user is not allowed to Read user dbs, + # but the return code for non-existent databases is 404. See #7674 if response.code.to_i == 401 return end -- cgit v1.2.3 From dab3b9227dc2f7977c5f34396f132984fa0485bf Mon Sep 17 00:00:00 2001 From: varac Date: Tue, 15 Mar 2016 15:41:39 +0100 Subject: [bug] Clamav test depends on multiple files The systemd clamav service depends on these files, see the `/lib/systemd/system/clamav-daemon.service` unit file: ConditionPathExistsGlob=/var/lib/clamav/main.{c[vl]d,inc} ConditionPathExistsGlob=/var/lib/clamav/daily.{c[vl]d,inc} Also, leap test should always check for the freshclam daemon. - Resolves: #7683 --- tests/white-box/mx.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'tests') diff --git a/tests/white-box/mx.rb b/tests/white-box/mx.rb index 9f577516..9335649a 100644 --- a/tests/white-box/mx.rb +++ b/tests/white-box/mx.rb @@ -38,12 +38,12 @@ class Mx < LeapTest assert_running 'postfwd2::cache$' assert_running 'postfwd2::policy$' assert_running '^/usr/sbin/unbound$' - if File.exists?('/var/lib/clamav/daily.cld') + assert_running '^/usr/bin/freshclam' + if Dir.glob("/var/lib/clamav/main.{c[vl]d,inc}").size > 0 and Dir.glob("/var/lib/clamav/daily.{c[vl]d,inc}").size > 1 assert_running '^/usr/sbin/clamd' assert_running '^/usr/sbin/clamav-milter' - assert_running '^/usr/bin/freshclam' else - skip "The clamav signature file (/var/lib/clamav/daily.cld) has yet to be downloaded, so clamd is not running." + skip "Downloading the clamav signature files (/var/lib/clamav/{daily,main}.{c[vl]d,inc}) is still in progress, so clamd is not running.\nDon't worry, mail delivery will work without clamav. The download should finish soon." end pass end -- cgit v1.2.3 From dbdd754747c754f7a678659bc52e2c60ee5b751c Mon Sep 17 00:00:00 2001 From: varac Date: Thu, 17 Mar 2016 20:15:13 +0100 Subject: [bug] Fix query for clamav signature files --- tests/white-box/mx.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests') diff --git a/tests/white-box/mx.rb b/tests/white-box/mx.rb index 9335649a..ff8cb744 100644 --- a/tests/white-box/mx.rb +++ b/tests/white-box/mx.rb @@ -39,7 +39,7 @@ class Mx < LeapTest assert_running 'postfwd2::policy$' assert_running '^/usr/sbin/unbound$' assert_running '^/usr/bin/freshclam' - if Dir.glob("/var/lib/clamav/main.{c[vl]d,inc}").size > 0 and Dir.glob("/var/lib/clamav/daily.{c[vl]d,inc}").size > 1 + if Dir.glob("/var/lib/clamav/main.{c[vl]d,inc}").size > 0 and Dir.glob("/var/lib/clamav/daily.{c[vl]d,inc}").size > 0 assert_running '^/usr/sbin/clamd' assert_running '^/usr/sbin/clamav-milter' else -- cgit v1.2.3 From df8b42ffd48a324d63a229a55c11c61076166657 Mon Sep 17 00:00:00 2001 From: Micah Date: Thu, 17 Mar 2016 15:16:48 -0400 Subject: add whitebox test for opendkim (#7649) Change-Id: I8c8ec225d703e3caf6c77fc72305da847cea9560 --- tests/white-box/mx.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'tests') diff --git a/tests/white-box/mx.rb b/tests/white-box/mx.rb index ff8cb744..ed990a2e 100644 --- a/tests/white-box/mx.rb +++ b/tests/white-box/mx.rb @@ -39,6 +39,7 @@ class Mx < LeapTest assert_running 'postfwd2::policy$' assert_running '^/usr/sbin/unbound$' assert_running '^/usr/bin/freshclam' + assert_running '^/usr/sbin/opendkim' if Dir.glob("/var/lib/clamav/main.{c[vl]d,inc}").size > 0 and Dir.glob("/var/lib/clamav/daily.{c[vl]d,inc}").size > 0 assert_running '^/usr/sbin/clamd' assert_running '^/usr/sbin/clamav-milter' -- cgit v1.2.3 From 61441a85b2a96cedd33c7bdc5940f0b8858de7be Mon Sep 17 00:00:00 2001 From: elijah Date: Thu, 17 Mar 2016 16:53:33 -0700 Subject: mx test: query identities table for a random record. closes #6406 --- tests/helpers/couchdb_helper.rb | 1 + tests/helpers/http_helper.rb | 5 +++-- tests/white-box/couchdb.rb | 2 +- tests/white-box/mx.rb | 31 +++++++++++++++++++++++++++++++ 4 files changed, 36 insertions(+), 3 deletions(-) (limited to 'tests') diff --git a/tests/helpers/couchdb_helper.rb b/tests/helpers/couchdb_helper.rb index d4d3c0e0..312e38ac 100644 --- a/tests/helpers/couchdb_helper.rb +++ b/tests/helpers/couchdb_helper.rb @@ -66,6 +66,7 @@ class LeapTest # port: 5984 # def couchdb_url_via_localhost(path="", options=nil) + path = path.gsub('"', '%22') port = (options && options[:port]) || assert_property('couch.port') if options && options[:username] password = property("couch.users.%{username}.password" % options) diff --git a/tests/helpers/http_helper.rb b/tests/helpers/http_helper.rb index 0b13b754..2fcdc910 100644 --- a/tests/helpers/http_helper.rb +++ b/tests/helpers/http_helper.rb @@ -87,12 +87,13 @@ class LeapTest options ||= {} error_msg = options[:error_msg] || (url.respond_to?(:memo) ? url.memo : nil) http_send(method, url, params, options) do |body, response, error| - if body && response && response.code.to_i >= 200 && response.code.to_i < 300 + ok = response && response.code.to_i >= 200 && response.code.to_i < 300 + if body && ok if block yield(body) if block.arity == 1 yield(response, body) if block.arity == 2 end - elsif response + elsif response && !ok fail ["Expected a 200 status code from #{method} #{url}, but got #{response.code} instead.", error_msg, body].compact.join("\n") else fail ["Expected a response from #{method} #{url}, but got \"#{error}\" instead.", error_msg, body].compact.join("\n"), error diff --git a/tests/white-box/couchdb.rb b/tests/white-box/couchdb.rb index edb28eac..da226cc9 100644 --- a/tests/white-box/couchdb.rb +++ b/tests/white-box/couchdb.rb @@ -9,8 +9,8 @@ class CouchDB < LeapTest end def test_00_Are_daemons_running? + assert_running 'bin/beam' if multimaster? - assert_running 'bin/beam' assert_running 'bin/epmd' end pass diff --git a/tests/white-box/mx.rb b/tests/white-box/mx.rb index ed990a2e..768b561f 100644 --- a/tests/white-box/mx.rb +++ b/tests/white-box/mx.rb @@ -31,6 +31,37 @@ class Mx < LeapTest end end + # + # this test picks a random identity document, then queries + # using the by_address view for that same document again. + # + def test_03_Can_query_identities_db? + assert_get(couchdb_url("/identities", url_options)) do |body| + assert response = JSON.parse(body) + doc_count = response['doc_count'].to_i + if doc_count < 1 + skip "There are no identity records yet." + else + offset = rand(doc_count) # pick a random document + count_url = couchdb_url("/identities/_all_docs?include_docs=true&limit=1&skip=#{offset}", url_options) + assert_get(count_url) do |body| + assert response = JSON.parse(body) + record = response['rows'].first + address = record['doc']['address'] + assert address, "address should not be empty" + url_base = %(/identities/_design/Identity/_view/by_address) + params = %(?include_docs=true&reduce=false&startkey="#{address}"&endkey="#{address}") + assert_get(couchdb_url(url_base+params, url_options)) do |body| + assert response = JSON.parse(body) + assert record = response['rows'].first + assert_equal address, record['doc']['address'] + pass + end + end + end + end + end + def test_03_Are_MX_daemons_running? assert_running '.*/usr/bin/twistd.*mx.tac' assert_running '^/usr/lib/postfix/master$' -- cgit v1.2.3 From 966120293ec289636874edda6089b99dc49cb9ae Mon Sep 17 00:00:00 2001 From: elijah Date: Fri, 18 Mar 2016 09:40:41 -0700 Subject: tests: fix mx test, ensure password is redacted. --- tests/helpers/couchdb_helper.rb | 2 ++ tests/white-box/mx.rb | 39 ++++++++++++++++++++++++--------------- 2 files changed, 26 insertions(+), 15 deletions(-) (limited to 'tests') diff --git a/tests/helpers/couchdb_helper.rb b/tests/helpers/couchdb_helper.rb index 312e38ac..27dabfcb 100644 --- a/tests/helpers/couchdb_helper.rb +++ b/tests/helpers/couchdb_helper.rb @@ -15,6 +15,7 @@ class LeapTest # connect_port: 15984 # def couchdb_urls_via_stunnel(path="", options=nil) + path = path.gsub('"', '%22') if options && options[:username] && options[:password] userpart = "%{username}:%{password}@" % options else @@ -46,6 +47,7 @@ class LeapTest # writable: true # def couchdb_url_via_haproxy(path="", options=nil) + path = path.gsub('"', '%22') if options && options[:username] && options[:password] userpart = "%{username}:%{password}@" % options else diff --git a/tests/white-box/mx.rb b/tests/white-box/mx.rb index 768b561f..57ec9117 100644 --- a/tests/white-box/mx.rb +++ b/tests/white-box/mx.rb @@ -39,23 +39,32 @@ class Mx < LeapTest assert_get(couchdb_url("/identities", url_options)) do |body| assert response = JSON.parse(body) doc_count = response['doc_count'].to_i - if doc_count < 1 - skip "There are no identity records yet." + if doc_count <= 1 + # the design document counts as one document. + skip "There are no identity documents yet." else - offset = rand(doc_count) # pick a random document - count_url = couchdb_url("/identities/_all_docs?include_docs=true&limit=1&skip=#{offset}", url_options) - assert_get(count_url) do |body| - assert response = JSON.parse(body) - record = response['rows'].first - address = record['doc']['address'] - assert address, "address should not be empty" - url_base = %(/identities/_design/Identity/_view/by_address) - params = %(?include_docs=true&reduce=false&startkey="#{address}"&endkey="#{address}") - assert_get(couchdb_url(url_base+params, url_options)) do |body| + # try five times to get a valid doc + for i in 1..5 + offset = rand(doc_count) # pick a random document + count_url = couchdb_url("/identities/_all_docs?include_docs=true&limit=1&skip=#{offset}", url_options) + assert_get(count_url) do |body| assert response = JSON.parse(body) - assert record = response['rows'].first - assert_equal address, record['doc']['address'] - pass + record = response['rows'].first + if record['id'] =~ /_design/ + next + else + address = record['doc']['address'] + assert address, "Identity document #{record['id']} is missing an address field. #{record['doc'].inspect}" + url_base = %(/identities/_design/Identity/_view/by_address) + params = %(?include_docs=true&reduce=false&startkey="#{address}"&endkey="#{address}") + assert_get(couchdb_url(url_base+params, url_options)) do |body| + assert response = JSON.parse(body) + assert record = response['rows'].first + assert_equal address, record['doc']['address'] + pass + end + break + end end end end -- cgit v1.2.3 From eac3056c237d523f4786593922fe8f88eb65dff7 Mon Sep 17 00:00:00 2001 From: elijah Date: Tue, 29 Mar 2016 13:27:01 -0700 Subject: testing: adds mx delivery tests --- tests/helpers/bonafide_helper.rb | 190 ++++++++++++++++++++++++++++++++------- tests/helpers/couchdb_helper.rb | 36 ++++++++ tests/helpers/http_helper.rb | 27 ++++-- tests/helpers/smtp_helper.rb | 45 ++++++++++ tests/helpers/srp_helper.rb | 4 +- tests/order.rb | 7 +- tests/white-box/couchdb.rb | 27 ++++++ tests/white-box/mx.rb | 99 ++++++++++++++++++-- tests/white-box/webapp.rb | 18 +--- 9 files changed, 386 insertions(+), 67 deletions(-) create mode 100644 tests/helpers/smtp_helper.rb (limited to 'tests') diff --git a/tests/helpers/bonafide_helper.rb b/tests/helpers/bonafide_helper.rb index 20c3ca8d..95e3e3b7 100644 --- a/tests/helpers/bonafide_helper.rb +++ b/tests/helpers/bonafide_helper.rb @@ -17,58 +17,53 @@ class LeapTest raise exc end - def api_url(path) - api = property('api') - "https://%{domain}:%{port}#{path}" % { - :domain => api['domain'], - :port => api['port'] - } - end - # # attempts to create a user account via the API, # returning the user object if successful. # - def assert_create_user - user = SRP::User.new - url = api_url("/1/users.json") - + def assert_create_user(username=nil, auth=nil) + user = SRP::User.new(username) + url = api_url("/users.json") params = user.to_params - - if property('webapp.invite_required') - @invite_code = generate_invite_code - params['user[invite_code]'] = @invite_code + if auth + options = api_options(:auth => auth) + else + options = api_options + if property('webapp.invite_required') + @invite_code = generate_invite_code + params['user[invite_code]'] = @invite_code + end end - assert_post(url, params) do |body| + assert_post(url, params, options) do |body| assert response = JSON.parse(body), 'response should be JSON' assert response['ok'], "Creating a user should be successful, got #{response.inspect} instead." + user.ok = true + user.id = response['id'] end - user.ok = true return user end + # TODO: use the api for this instead. def generate_invite_code `cd /srv/leap/webapp/ && sudo -u leap-webapp RAILS_ENV=production bundle exec rake generate_invites[1]`.gsub(/\n/, "") end - # # attempts to authenticate user. if successful, # user object is updated with id and session token. # def assert_authenticate_user(user) - url = api_url("/1/sessions.json") + url = api_url("/sessions.json") session = SRP::Session.new(user) params = {'login' => user.username, 'A' => session.aa} - assert_post(url, params) do |response, body| + assert_post(url, params, api_options) do |body, response| cookie = response['Set-Cookie'].split(';').first assert(response = JSON.parse(body), 'response should be JSON') assert(session.bb = response["B"], 'response should include "B"') - url = api_url("/1/sessions/login.json") + url = api_url("/sessions/login.json") params = {'client_auth' => session.m, 'A' => session.aa} - options = {:headers => {'Cookie' => cookie}} - assert_put(url, params, options) do |body| + assert_put(url, params, api_options('Cookie' => cookie)) do |body| assert(response = JSON.parse(body), 'response should be JSON') assert(response['M2'], 'response should include M2') user.session_token = response['token'] @@ -83,16 +78,146 @@ class LeapTest # attempts to destroy a user account via the API. # def assert_delete_user(user) - if user && user.ok && user.id && user.session_token && !user.deleted - url = api_url("/1/users/#{user.id}.json") - options = {:headers => { - "Authorization" => "Token token=\"#{user.session_token}\"" - }} - params = { - :identities => 'destroy' + if user.is_a? String + assert_delete_user_by_login(user) + elsif user.is_a? SRP::User + assert_delete_srp_user(user) + end + end + + # + # returns true if the identity exists, uses monitor token auth + # + def identity_exists?(address) + url = api_url("/identities/#{URI.encode(address)}.json") + get(url, nil, api_options(:auth => :monitor)) do |body, response| + return response.code == "200" + end + end + + def upload_public_key(user_id, public_key) + url = api_url("/users/#{user_id}.json") + params = {"user[public_key]" => public_key} + assert_put(url, params, api_options(:auth => :monitor)) + end + + # + # return user document as a Hash. uses monitor token auth + # + def find_user_by_id(user_id) + url = api_url("/users/#{user_id}.json") + assert_get(url, nil, api_options(:auth => :monitor)) do |body| + return JSON.parse(body) + end + end + + # + # return user document as a Hash. uses monitor token auth + # NOTE: this relies on deprecated behavior of the API + # and will not work when multi-domain support is added. + # + def find_user_by_login(login) + url = api_url("/users/0.json?login=#{login}") + options = {:ok_codes => [200, 404]}.merge(api_options(:auth => :monitor)) + assert_get(url, nil, options) do |body, response| + if response.code == "200" + return JSON.parse(body) + else + return nil + end + end + end + + private + + def api_url(path) + unless path =~ /^\// + path = '/' + path + end + if property('testing.api_uri') + return property('testing.api_uri') + path + elsif property('api') + api = property('api') + return "https://%{domain}:%{port}/%{version}#{path}" % { + :domain => api['domain'], + :port => api['port'], + :version => api['version'] || 1 } + else + fail 'This node needs to have either testing.api_url or api.{domain,port} configured.' + end + end + + # + # produces an options hash used for api http requests. + # + # argument options hash gets added to "headers" + # of the http request. + # + # special :auth key in argument will expand to + # add api_token_auth header. + # + # if you want to try manually: + # + # export API_URI=`grep api_uri /etc/leap/hiera.yaml | cut -d\" -f2` + # export TOKEN=`grep monitor_auth_token /etc/leap/hiera.yaml | awk '{print $2}'` + # curl -H "Accept: application/json" -H "Token: $TOKEN" $API_URI + # + def api_options(options={}) + # note: must be :headers, not "headers" + hsh = { + :headers => { + "Accept" => "application/json" + } + } + if options[:auth] + hsh[:headers].merge!(api_token_auth(options.delete(:auth))) + end + hsh[:headers].merge!(options) + return hsh + end + + # + # add token authentication to a http request. + # + # returns a hash suitable for adding to the 'headers' option + # of an http function. + # + def api_token_auth(token) + if token.is_a?(Symbol) && property('testing') + if token == :monitor + token_str = property('testing.monitor_auth_token') + else + raise ArgumentError.new 'no such token' + end + else + token_str = token + end + {"Authorization" => "Token token=\"#{token_str}\""} + end + + # + # not actually used in any test, but useful when + # writing new tests. + # + def assert_delete_user_by_login(login_name) + user = find_user_by_login(login_name) + url = api_url("/users/#{user['id']}.json") + params = {:identities => 'destroy'} + delete(url, params, api_options(:auth => :monitor)) do |body, response, error| + assert error.nil?, "Error deleting user: #{error}" + assert response.code.to_i == 200, "Unable to delete user: HTTP response from API should have code 200, was #{response.code} #{error} #{body}" + assert(response = JSON.parse(body), 'Delete response should be JSON') + assert(response["success"], 'Deleting user should be a success') + end + end + + def assert_delete_srp_user(user) + if user && user.ok && user.id && user.session_token && !user.deleted + url = api_url("users/#{user.id}.json") + params = {:identities => 'destroy'} user.deleted = true - delete(url, params, options) do |body, response, error| + delete(url, params, api_options(:auth => user.session_token)) do |body, response, error| assert error.nil?, "Error deleting user: #{error}" assert response.code.to_i == 200, "Unable to delete user: HTTP response from API should have code 200, was #{response.code} #{error} #{body}" assert(response = JSON.parse(body), 'Delete response should be JSON') @@ -101,4 +226,5 @@ class LeapTest end end + end diff --git a/tests/helpers/couchdb_helper.rb b/tests/helpers/couchdb_helper.rb index 27dabfcb..b9085c1e 100644 --- a/tests/helpers/couchdb_helper.rb +++ b/tests/helpers/couchdb_helper.rb @@ -103,4 +103,40 @@ class LeapTest end end + def assert_destroy_user_db(user_id, options=nil) + db_name = "user-#{user_id}" + url = couchdb_url("/#{db_name}", options) + http_options = {:ok_codes => [200, 404]} # ignore missing dbs + assert_delete(url, nil, http_options) + end + + def assert_create_user_db(user_id, options=nil) + db_name = "user-#{user_id}" + url = couchdb_url("/#{db_name}", options) + http_options = {:ok_codes => [200, 404]} # ignore missing dbs + assert_put(url, nil, :format => :json) do |body| + assert response = JSON.parse(body), "PUT response should be JSON" + assert response["ok"], "PUT response should be OK" + end + end + + # + # returns true if the per-user db created by soledad-server exists. + # + def user_db_exists?(user_id, options=nil) + db_name = "user-#{user_id}" + url = couchdb_url("/#{db_name}", options) + get(url) do |body, response, error| + if response.nil? + fail "could not query couchdb #{url}: #{error}\n#{body}" + elsif response.code.to_i == 200 + return true + elsif response.code.to_i == 404 + return false + else + fail ["could not query couchdb #{url}: expected response code 200 or 404, but got #{response.code}.", error, body].compact.join("\n") + end + end + end + end \ No newline at end of file diff --git a/tests/helpers/http_helper.rb b/tests/helpers/http_helper.rb index 2fcdc910..0d0bb7d5 100644 --- a/tests/helpers/http_helper.rb +++ b/tests/helpers/http_helper.rb @@ -81,20 +81,31 @@ class LeapTest # # calls http_send, yielding results if successful or failing with - # descriptive infor otherwise. + # descriptive info otherwise. + # + # options: + # - error_msg: custom error message to display. + # - ok_codes: in addition to 2xx, codes in this array will not produce an error. # def assert_http_send(method, url, params=nil, options=nil, &block) options ||= {} error_msg = options[:error_msg] || (url.respond_to?(:memo) ? url.memo : nil) http_send(method, url, params, options) do |body, response, error| - ok = response && response.code.to_i >= 200 && response.code.to_i < 300 - if body && ok - if block - yield(body) if block.arity == 1 - yield(response, body) if block.arity == 2 + if response + code = response.code.to_i + ok = code >= 200 && code < 300 + if options[:ok_codes] + ok ||= options[:ok_codes].include?(code) + end + if ok + if block + yield(body) if block.arity == 1 + yield(body, response) if block.arity == 2 + yield(body, response, error) if block.arity == 3 + end + else + fail ["Expected success code from #{method} #{url}, but got #{response.code} instead.", error_msg, body].compact.join("\n") end - elsif response && !ok - fail ["Expected a 200 status code from #{method} #{url}, but got #{response.code} instead.", error_msg, body].compact.join("\n") else fail ["Expected a response from #{method} #{url}, but got \"#{error}\" instead.", error_msg, body].compact.join("\n"), error end diff --git a/tests/helpers/smtp_helper.rb b/tests/helpers/smtp_helper.rb new file mode 100644 index 00000000..ea7fb9fa --- /dev/null +++ b/tests/helpers/smtp_helper.rb @@ -0,0 +1,45 @@ +require 'net/smtp' + +class LeapTest + + TEST_EMAIL_USER = "test_user_email" + TEST_BAD_USER = "test_user_bad" + + MSG_BODY = %(Since it seems that any heart which beats for freedom has the right only to a +lump of lead, I too claim my share. If you let me live, I shall never stop +crying for revenge and I shall avenge my brothers. I have finished. If you are +not cowards, kill me! + +--Louise Michel) + + def send_email(recipient, options={}) + sender = options[:sender] || recipient + helo_domain = property('domain.full_suffix') + headers = { + "Date" => Time.now.utc, + "From" => sender, + "To" => recipient, + "Subject" => "Test Message", + "X-LEAP-TEST" => "true" + }.merge(options[:headers]||{}) + message = [] + headers.each do |key, value| + message << "#{key}: #{value}" + end + message << "" + message << MSG_BODY + Net::SMTP.start('localhost', 25, helo_domain) do |smtp| + smtp.send_message message.join("\n"), recipient, sender + end + end + + def assert_send_email(recipient, options={}) + begin + send_email(recipient, options) + rescue IOError, Net::OpenTimeout, + Net::ReadTimeout, Net::SMTPError => e + fail "Could not send mail to #{recipient} (#{e})" + end + end + +end \ No newline at end of file diff --git a/tests/helpers/srp_helper.rb b/tests/helpers/srp_helper.rb index 5d30b459..b30fa768 100644 --- a/tests/helpers/srp_helper.rb +++ b/tests/helpers/srp_helper.rb @@ -138,8 +138,8 @@ d15dc7d7b46154d6b6ce8ef4ad69b15d4982559b297bcf1885c529f566660e5 attr_accessor :username, :password, :salt, :verifier, :id, :session_token, :ok, :deleted - def initialize - @username = "test_user_" + SecureRandom.urlsafe_base64(10).downcase.gsub(/[_-]/, '') + def initialize(username=nil) + @username = username || "tmp_user_" + SecureRandom.urlsafe_base64(10).downcase.gsub(/[_-]/, '') @password = "password_" + SecureRandom.urlsafe_base64(10) @salt = bigrand(4).hex @verifier = modpow(GENERATOR, private_key) diff --git a/tests/order.rb b/tests/order.rb index 4468686f..14aad9be 100644 --- a/tests/order.rb +++ b/tests/order.rb @@ -9,11 +9,14 @@ class LeapCli::Config::Node # def test_dependencies dependents = LeapCli::Config::ObjectList.new - unless services.include?('couchdb') - if services.include?('webapp') || services.include?('mx') || services.include?('soledad') + + # webapp, mx, and soledad depend on couchdb nodes + if services.include?('webapp') || services.include?('mx') || services.include?('soledad') + if !services.include?('couchdb') dependents.merge! nodes_like_me[:services => 'couchdb'] end end + dependents.keys.delete_if {|name| self.name == name} end end \ No newline at end of file diff --git a/tests/white-box/couchdb.rb b/tests/white-box/couchdb.rb index da226cc9..859b4745 100644 --- a/tests/white-box/couchdb.rb +++ b/tests/white-box/couchdb.rb @@ -127,6 +127,33 @@ class CouchDB < LeapTest pass end + # + # This is not really a "test", just an attempt to make sure that + # the mx tests that fire off dummy emails don't fill up the + # storage db. + # + # mx tests can't run this because they don't have access to + # the storage db. + # + # This "test" is responsible for both creating the db if it does not + # exist, and destroying if it does. + # + # Yes, this is super hacky. Properly, we should add something to + # the soledad api to support create/delete of user storage dbs. + # + def test_99_Delete_mail_storage_used_in_mx_tests + user = find_user_by_login(TEST_EMAIL_USER) + if user + if user_db_exists?(user["id"]) + # keep the test email db from filling up: + assert_destroy_user_db(user["id"], :username => 'admin') + end + # either way, make sure we leave a db for the mx tests: + assert_create_user_db(user["id"], :username => 'admin') + end + # no 'pass' at the end, since this is not a real test. + end + private def multimaster? diff --git a/tests/white-box/mx.rb b/tests/white-box/mx.rb index 57ec9117..6c0982ce 100644 --- a/tests/white-box/mx.rb +++ b/tests/white-box/mx.rb @@ -1,9 +1,11 @@ raise SkipTest unless service?(:mx) require 'json' +require 'net/smtp' class Mx < LeapTest depends_on "Network" + depends_on "Webapp" if service?(:webapp) def setup end @@ -11,7 +13,7 @@ class Mx < LeapTest def test_01_Can_contact_couchdb? dbs = ["identities"] dbs.each do |db_name| - couchdb_urls("/"+db_name, url_options).each do |url| + couchdb_urls("/"+db_name, couch_url_options).each do |url| assert_get(url) do |body| assert response = JSON.parse(body) assert_equal db_name, response['db_name'] @@ -23,7 +25,7 @@ class Mx < LeapTest def test_02_Can_contact_couchdb_via_haproxy? if property('haproxy.couch') - url = couchdb_url_via_haproxy("", url_options) + url = couchdb_url_via_haproxy("", couch_url_options) assert_get(url) do |body| assert_match /"couchdb":"Welcome"/, body, "Request to #{url} should return couchdb welcome message." end @@ -36,7 +38,7 @@ class Mx < LeapTest # using the by_address view for that same document again. # def test_03_Can_query_identities_db? - assert_get(couchdb_url("/identities", url_options)) do |body| + assert_get(couchdb_url("/identities", couch_url_options)) do |body| assert response = JSON.parse(body) doc_count = response['doc_count'].to_i if doc_count <= 1 @@ -46,7 +48,7 @@ class Mx < LeapTest # try five times to get a valid doc for i in 1..5 offset = rand(doc_count) # pick a random document - count_url = couchdb_url("/identities/_all_docs?include_docs=true&limit=1&skip=#{offset}", url_options) + count_url = couchdb_url("/identities/_all_docs?include_docs=true&limit=1&skip=#{offset}", couch_url_options) assert_get(count_url) do |body| assert response = JSON.parse(body) record = response['rows'].first @@ -57,7 +59,7 @@ class Mx < LeapTest assert address, "Identity document #{record['id']} is missing an address field. #{record['doc'].inspect}" url_base = %(/identities/_design/Identity/_view/by_address) params = %(?include_docs=true&reduce=false&startkey="#{address}"&endkey="#{address}") - assert_get(couchdb_url(url_base+params, url_options)) do |body| + assert_get(couchdb_url(url_base+params, couch_url_options)) do |body| assert response = JSON.parse(body) assert record = response['rows'].first assert_equal address, record['doc']['address'] @@ -71,7 +73,7 @@ class Mx < LeapTest end end - def test_03_Are_MX_daemons_running? + def test_04_Are_MX_daemons_running? assert_running '.*/usr/bin/twistd.*mx.tac' assert_running '^/usr/lib/postfix/master$' assert_running '^/usr/sbin/postfwd' @@ -89,13 +91,96 @@ class Mx < LeapTest pass end + # + # The email sent by this test might get bounced back. + # In this case, the test will pass, but the bounce message will + # get sent to root, so the sysadmin will still figure out pretty + # quickly that something is wrong. + # + def test_05_Can_deliver_email? + addr = [TEST_EMAIL_USER, property('domain.full_suffix')].join('@') + bad_addr = [TEST_BAD_USER, property('domain.full_suffix')].join('@') + + assert !identity_exists?(bad_addr), "the address #{bad_addr} must not exist." + if !identity_exists?(addr) + user = assert_create_user(TEST_EMAIL_USER, :monitor) + upload_public_key(user.id, TEST_EMAIL_PUBLIC_KEY) + end + assert identity_exists?(addr), "The identity #{addr} should have been created, but it doesn't exist yet." + assert_send_email(addr) + assert_raises(Net::SMTPError) do + send_email(bad_addr) + end + pass + end + private - def url_options + def couch_url_options { :username => property('couchdb_leap_mx_user.username'), :password => property('couchdb_leap_mx_user.password') } end + TEST_EMAIL_PUBLIC_KEY=< property('couchdb_webapp_user.username'), - :password => property('couchdb_webapp_user.password') + :username => property('webapp.couchdb_webapp_user.username'), + :password => property('webapp.couchdb_webapp_user.password') } end @@ -131,18 +131,4 @@ class Webapp < LeapTest return end - # - # I tried, but couldn't get this working: - # # - # # get an CSRF authenticity token - # # - # url = api_url("/") - # csrf_token = nil - # assert_get(url) do |body| - # lines = body.split("\n").grep(/csrf-token/) - # assert lines.any?, 'failed to find csrf-token' - # csrf_token = lines.first.split('"')[1] - # assert csrf_token, 'failed to find csrf-token' - # end - end -- cgit v1.2.3 From 232047fdee815d9cf8c92b6853c5bc8039f2719c Mon Sep 17 00:00:00 2001 From: elijah Date: Wed, 13 Apr 2016 02:36:47 -0700 Subject: test: ensure that checkmk always gets the same list of tests --- tests/white-box/couchdb.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests') diff --git a/tests/white-box/couchdb.rb b/tests/white-box/couchdb.rb index 859b4745..85dc6840 100644 --- a/tests/white-box/couchdb.rb +++ b/tests/white-box/couchdb.rb @@ -151,7 +151,7 @@ class CouchDB < LeapTest # either way, make sure we leave a db for the mx tests: assert_create_user_db(user["id"], :username => 'admin') end - # no 'pass' at the end, since this is not a real test. + silent_pass end private -- cgit v1.2.3 From 91dd5a8b3c6d7bc6b06852c1659564c5559d743d Mon Sep 17 00:00:00 2001 From: elijah Date: Mon, 25 Apr 2016 22:24:05 -0300 Subject: [tests] better error message when identity test cannot contact api. closes #8046 --- tests/helpers/bonafide_helper.rb | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'tests') diff --git a/tests/helpers/bonafide_helper.rb b/tests/helpers/bonafide_helper.rb index 95e3e3b7..5b886228 100644 --- a/tests/helpers/bonafide_helper.rb +++ b/tests/helpers/bonafide_helper.rb @@ -90,7 +90,10 @@ class LeapTest # def identity_exists?(address) url = api_url("/identities/#{URI.encode(address)}.json") - get(url, nil, api_options(:auth => :monitor)) do |body, response| + options = {:ok_codes => [200, 404]}.merge( + api_options(:auth => :monitor) + ) + assert_get(url, nil, options) do |body, response| return response.code == "200" end end @@ -118,7 +121,9 @@ class LeapTest # def find_user_by_login(login) url = api_url("/users/0.json?login=#{login}") - options = {:ok_codes => [200, 404]}.merge(api_options(:auth => :monitor)) + options = {:ok_codes => [200, 404]}.merge( + api_options(:auth => :monitor) + ) assert_get(url, nil, options) do |body, response| if response.code == "200" return JSON.parse(body) -- cgit v1.2.3