From 07c0e60e6bdc5b8bfe1f42f76dae9f0a79e7abb0 Mon Sep 17 00:00:00 2001 From: elijah Date: Mon, 29 Aug 2016 16:35:14 -0700 Subject: moved infrastructure tests run by `leap run` to tests/server-tests --- tests/helpers/bonafide_helper.rb | 235 --------------------------------------- tests/helpers/client_side_db.py | 167 ---------------------------- tests/helpers/couchdb_helper.rb | 143 ------------------------ tests/helpers/files_helper.rb | 54 --------- tests/helpers/http_helper.rb | 157 -------------------------- tests/helpers/network_helper.rb | 79 ------------- tests/helpers/os_helper.rb | 41 ------- tests/helpers/smtp_helper.rb | 45 -------- tests/helpers/soledad_sync.py | 89 --------------- tests/helpers/srp_helper.rb | 171 ---------------------------- 10 files changed, 1181 deletions(-) delete mode 100644 tests/helpers/bonafide_helper.rb delete mode 100644 tests/helpers/client_side_db.py delete mode 100644 tests/helpers/couchdb_helper.rb delete mode 100644 tests/helpers/files_helper.rb delete mode 100644 tests/helpers/http_helper.rb delete mode 100644 tests/helpers/network_helper.rb delete mode 100644 tests/helpers/os_helper.rb delete mode 100644 tests/helpers/smtp_helper.rb delete mode 100755 tests/helpers/soledad_sync.py delete mode 100644 tests/helpers/srp_helper.rb (limited to 'tests/helpers') diff --git a/tests/helpers/bonafide_helper.rb b/tests/helpers/bonafide_helper.rb deleted file mode 100644 index 5b886228..00000000 --- a/tests/helpers/bonafide_helper.rb +++ /dev/null @@ -1,235 +0,0 @@ -# -# helper for the communication with the provider API for creating, authenticating, and deleting accounts. -# - -class LeapTest - - def assert_tmp_user - user = assert_create_user - assert_authenticate_user(user) - yield user if block_given? - assert_delete_user(user) - rescue StandardError, MiniTest::Assertion => exc - begin - assert_delete_user(user) - rescue - end - raise exc - end - - # - # attempts to create a user account via the API, - # returning the user object if successful. - # - def assert_create_user(username=nil, auth=nil) - user = SRP::User.new(username) - url = api_url("/users.json") - params = user.to_params - 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, 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 - 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("/sessions.json") - session = SRP::Session.new(user) - params = {'login' => user.username, 'A' => session.aa} - 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("/sessions/login.json") - params = {'client_auth' => session.m, 'A' => session.aa} - 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'] - user.id = response['id'] - assert(user.session_token, 'response should include token') - assert(user.id, 'response should include user id') - end - end - end - - # - # attempts to destroy a user account via the API. - # - def assert_delete_user(user) - 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") - options = {:ok_codes => [200, 404]}.merge( - api_options(:auth => :monitor) - ) - assert_get(url, nil, options) 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, 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') - assert(response["success"], 'Deleting user should be a success') - end - end - end - - -end diff --git a/tests/helpers/client_side_db.py b/tests/helpers/client_side_db.py deleted file mode 100644 index 2f8c220f..00000000 --- a/tests/helpers/client_side_db.py +++ /dev/null @@ -1,167 +0,0 @@ -import logging -import os -import tempfile -import getpass -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 - - -""" -Helper functions to give access to client-side Soledad database. -Copied over from soledad/scripts folder. -""" - -# 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_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() - 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_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) diff --git a/tests/helpers/couchdb_helper.rb b/tests/helpers/couchdb_helper.rb deleted file mode 100644 index efb2c2bf..00000000 --- a/tests/helpers/couchdb_helper.rb +++ /dev/null @@ -1,143 +0,0 @@ -class LeapTest - - # - # generates a couchdb url for when couchdb is running - # remotely and is available via stunnel. - # - # example properties: - # - # stunnel: - # clients: - # couch_client: - # couch1_5984: - # accept_port: 4000 - # connect: couch1.bitmask.i - # 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 - userpart = "" - end - assert_property('stunnel.clients.couch_client').values.collect do |stunnel_conf| - assert port = stunnel_conf['accept_port'], 'Field `accept_port` must be present in `stunnel` property.' - URLString.new("http://#{userpart}localhost:#{port}#{path}").tap {|url| - remote_ip_address = TCPSocket.gethostbyname(stunnel_conf['connect']).last - url.memo = "(via stunnel to %s:%s, aka %s)" % [stunnel_conf['connect'], stunnel_conf['connect_port'], remote_ip_address] - } - end - end - - # - # generates a couchdb url for accessing couchdb via haproxy - # - # example properties: - # - # haproxy: - # couch: - # listen_port: 4096 - # servers: - # panda: - # backup: false - # host: localhost - # port: 4000 - # weight: 100 - # 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 - userpart = "" - end - port = assert_property('haproxy.couch.listen_port') - return URLString.new("http://#{userpart}localhost:#{port}#{path}").tap { |url| - url.memo = '(via haproxy)' - } - end - - # - # generates a couchdb url for when couchdb is running locally. - # - # example properties: - # - # couch: - # 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) - userpart = "%s:%s@" % [options[:username], password] - else - userpart = "" - end - return URLString.new("http://#{userpart}localhost:#{port}#{path}").tap { |url| - url.memo = '(via direct localhost connection)' - } - end - - # - # returns a single url for accessing couchdb - # - def couchdb_url(path="", options=nil) - if property('couch.port') - couchdb_url_via_localhost(path, options) - elsif property('stunnel.clients.couch_client') - couchdb_urls_via_stunnel(path, options).first - end - end - - # - # returns an array of urls for accessing couchdb - # - def couchdb_urls(path="", options=nil) - if property('couch.port') - [couchdb_url_via_localhost(path, options)] - elsif property('stunnel.clients.couch_client') - couchdb_urls_via_stunnel(path, options) - 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) - options = {:username => 'admin'}.merge(options || {}) - 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/files_helper.rb b/tests/helpers/files_helper.rb deleted file mode 100644 index d6795889..00000000 --- a/tests/helpers/files_helper.rb +++ /dev/null @@ -1,54 +0,0 @@ -class LeapTest - - # - # Matches the regexp in the file, and returns the first matched string (or fails if no match). - # - def file_match(filename, regexp) - if match = File.read(filename).match(regexp) - match.captures.first - else - fail "Regexp #{regexp.inspect} not found in file #{filename.inspect}." - end - end - - # - # Matches the regexp in the file, and returns array of matched strings (or fails if no match). - # - def file_matches(filename, regexp) - if match = File.read(filename).match(regexp) - match.captures - else - fail "Regexp #{regexp.inspect} not found in file #{filename.inspect}." - end - end - - # - # checks to make sure the given property path exists in $node (e.g. hiera.yaml) - # and returns the value - # - def assert_property(property) - latest = $node - property.split('.').each do |segment| - latest = latest[segment] - fail "Required node property `#{property}` is missing." if latest.nil? - end - return latest - end - - # - # a handy function to get the value of a long property path - # without needing to test the existance individually of each part - # in the tree. - # - # e.g. property("stunnel.clients.couch_client") - # - def property(property) - latest = $node - property.split('.').each do |segment| - latest = latest[segment] - return nil if latest.nil? - end - return latest - end - -end \ No newline at end of file diff --git a/tests/helpers/http_helper.rb b/tests/helpers/http_helper.rb deleted file mode 100644 index 0d0bb7d5..00000000 --- a/tests/helpers/http_helper.rb +++ /dev/null @@ -1,157 +0,0 @@ -require 'net/http' - -class LeapTest - - # - # In order to easily provide detailed error messages, it is useful - # to append a memo to a url string that details what this url is for - # (e.g. stunnel, haproxy, etc). - # - # So, the url happens to be a UrlString, the memo field is used - # if there is an error in assert_get. - # - class URLString < String - attr_accessor :memo - end - - # - # aliases for http_send() - # - def get(url, params=nil, options=nil, &block) - http_send("GET", url, params, options, &block) - end - def delete(url, params=nil, options=nil, &block) - http_send("DELETE", url, params, options, &block) - end - def post(url, params=nil, options=nil, &block) - http_send("POST", url, params, options, &block) - end - def put(url, params=nil, options=nil, &block) - http_send("PUT", url, params, options, &block) - end - - # - # send a GET, DELETE, POST, or PUT - # yields |body, response, error| - # - def http_send(method, url, params=nil, options=nil) - options ||= {} - response = nil - - # build uri - uri = URI(url) - if params && (method == 'GET' || method == 'DELETE') - uri.query = URI.encode_www_form(params) - end - - # build http - http = Net::HTTP.new uri.host, uri.port - if uri.scheme == 'https' - http.verify_mode = OpenSSL::SSL::VERIFY_NONE - http.use_ssl = true - end - - # build request - request = build_request(method, uri, params, options) - - # make http request - http.start do |agent| - response = agent.request(request) - yield response.body, response, nil - end - rescue => exc - yield nil, response, exc - end - - # - # Aliases for assert_http_send() - # - def assert_get(url, params=nil, options=nil, &block) - assert_http_send("GET", url, params, options, &block) - end - def assert_delete(url, params=nil, options=nil, &block) - assert_http_send("DELETE", url, params, options, &block) - end - def assert_post(url, params=nil, options=nil, &block) - assert_http_send("POST", url, params, options, &block) - end - def assert_put(url, params=nil, options=nil, &block) - assert_http_send("PUT", url, params, options, &block) - end - - # - # calls http_send, yielding results if successful or failing with - # 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| - 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 - else - fail ["Expected a response from #{method} #{url}, but got \"#{error}\" instead.", error_msg, body].compact.join("\n"), error - end - end - end - - # - # only a warning for now, should be a failure in the future - # - def assert_auth_fail(url, params) - uri = URI(url) - get(url, params) do |body, response, error| - unless response.code.to_s == "401" - warn "Expected a '401 Unauthorized' response, but got #{response.code} instead (GET #{uri.request_uri} with username '#{uri.user}')." - return false - end - end - true - end - - private - - def build_request(method, uri, params, options) - request = case method - when "GET" then Net::HTTP::Get.new(uri.request_uri) - when "DELETE" then Net::HTTP::Delete.new(uri.request_uri) - when "POST" then Net::HTTP::Post.new(uri.request_uri) - when "PUT" then Net::HTTP::Put.new(uri.request_uri) - end - if uri.user - request.basic_auth uri.user, uri.password - end - if params && (method == 'POST' || method == 'PUT') - if options[:format] == :json || options[:format] == 'json' - request["Content-Type"] = "application/json" - request.body = params.to_json - else - request.set_form_data(params) if params - end - end - if options[:headers] - options[:headers].each do |key, value| - request[key] = value - end - end - request - end - -end \ No newline at end of file diff --git a/tests/helpers/network_helper.rb b/tests/helpers/network_helper.rb deleted file mode 100644 index 713d57aa..00000000 --- a/tests/helpers/network_helper.rb +++ /dev/null @@ -1,79 +0,0 @@ -class LeapTest - - # - # tcp connection helper with timeout - # - def try_tcp_connect(host, port, timeout = 5) - addr = Socket.getaddrinfo(host, nil) - sockaddr = Socket.pack_sockaddr_in(port, addr[0][3]) - - Socket.new(Socket.const_get(addr[0][0]), Socket::SOCK_STREAM, 0).tap do |socket| - socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1) - begin - socket.connect_nonblock(sockaddr) - rescue IO::WaitReadable - if IO.select([socket], nil, nil, timeout) == nil - raise "Connection timeout" - else - socket.connect_nonblock(sockaddr) - end - rescue IO::WaitWritable - if IO.select(nil, [socket], nil, timeout) == nil - raise "Connection timeout" - else - socket.connect_nonblock(sockaddr) - end - end - return socket - end - end - - def try_tcp_write(socket, timeout = 5) - begin - socket.write_nonblock("\0") - rescue IO::WaitReadable - if IO.select([socket], nil, nil, timeout) == nil - raise "Write timeout" - else - retry - end - rescue IO::WaitWritable - if IO.select(nil, [socket], nil, timeout) == nil - raise "Write timeout" - else - retry - end - end - end - - def try_tcp_read(socket, timeout = 5) - begin - socket.read_nonblock(1) - rescue IO::WaitReadable - if IO.select([socket], nil, nil, timeout) == nil - raise "Read timeout" - else - retry - end - rescue IO::WaitWritable - if IO.select(nil, [socket], nil, timeout) == nil - raise "Read timeout" - else - retry - end - end - end - - def assert_tcp_socket(host, port, msg=nil) - begin - socket = try_tcp_connect(host, port, 1) - #try_tcp_write(socket,1) - #try_tcp_read(socket,1) - rescue StandardError => exc - fail ["Failed to open socket #{host}:#{port}", exc, msg].compact.join("\n") - ensure - socket.close if socket - end - end - -end \ No newline at end of file diff --git a/tests/helpers/os_helper.rb b/tests/helpers/os_helper.rb deleted file mode 100644 index 9923d5b1..00000000 --- a/tests/helpers/os_helper.rb +++ /dev/null @@ -1,41 +0,0 @@ -class LeapTest - - # - # works like pgrep command line - # return an array of hashes like so [{:pid => "1234", :process => "ls"}] - # - def pgrep(match) - output = `pgrep --full --list-name '#{match}'` - output.each_line.map{|line| - pid = line.split(' ')[0] - process = line.gsub(/(#{pid} |\n)/, '') - # 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} - end - }.compact - end - - def assert_running(process, options={}) - processes = pgrep(process) - assert processes.any?, "No running process for #{process}" - if options[:single] - assert processes.length == 1, "More than one process for #{process}" - end - end - - # - # runs the specified command, failing on a non-zero exit status. - # - def assert_run(command) - output = `#{command} 2>&1` - if $?.exitstatus != 0 - fail "Error running `#{command}`:\n#{output}" - end - end - -end \ No newline at end of file diff --git a/tests/helpers/smtp_helper.rb b/tests/helpers/smtp_helper.rb deleted file mode 100644 index ea7fb9fa..00000000 --- a/tests/helpers/smtp_helper.rb +++ /dev/null @@ -1,45 +0,0 @@ -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/soledad_sync.py b/tests/helpers/soledad_sync.py deleted file mode 100755 index f4fc81ae..00000000 --- a/tests/helpers/soledad_sync.py +++ /dev/null @@ -1,89 +0,0 @@ -#!/usr/bin/env python -""" -soledad_sync.py - -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 shutil -import sys -import tempfile - -# This is needed because the twisted shipped with wheezy is too old -# to do proper ssl verification. -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 - -flags.set_events_enabled(False) - -NUMDOCS = 1 -USAGE = "Usage: %s uuid token server cert_file password" % sys.argv[0] - - -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__': - - 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) - - 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(): - d = create_docs(s) - d.addCallback(lambda _: s.sync()) - d.addCallback(onSyncDone) - d.addErrback(log_and_exit) - - reactor.callWhenRunning(start_sync) - reactor.run() diff --git a/tests/helpers/srp_helper.rb b/tests/helpers/srp_helper.rb deleted file mode 100644 index b30fa768..00000000 --- a/tests/helpers/srp_helper.rb +++ /dev/null @@ -1,171 +0,0 @@ -# -# Here are some very stripped down helper methods for SRP, useful only for -# testing the client side. -# - -require 'digest' -require 'openssl' -require 'securerandom' -require 'base64' - -module SRP - - ## - ## UTIL - ## - - module Util - PRIME_N = <<-EOS.split.join.hex -115b8b692e0e045692cf280b436735c77a5a9e8a9e7ed56c965f87db5b2a2ece3 - EOS - BIG_PRIME_N = <<-EOS.split.join.hex # 1024 bits modulus (N) -eeaf0ab9adb38dd69c33f80afa8fc5e86072618775ff3c0b9ea2314c9c25657 -6d674df7496ea81d3383b4813d692c6e0e0d5d8e250b98be48e495c1d6089da -d15dc7d7b46154d6b6ce8ef4ad69b15d4982559b297bcf1885c529f566660e5 -7ec68edbc3c05726cc02fd4cbf4976eaa9afd5138fe8376435b9fc61d2fc0eb -06e3 - EOS - GENERATOR = 2 # g - - def hn_xor_hg - byte_xor_hex(sha256_int(BIG_PRIME_N), sha256_int(GENERATOR)) - end - - # a^n (mod m) - def modpow(a, n, m = BIG_PRIME_N) - r = 1 - while true - r = r * a % m if n[0] == 1 - n >>= 1 - return r if n == 0 - a = a * a % m - end - end - - # Hashes the (long) int args - def sha256_int(*args) - sha256_hex(*args.map{|a| "%02x" % a}) - end - - # Hashes the hex args - def sha256_hex(*args) - h = args.map{|a| a.length.odd? ? "0#{a}" : a }.join('') - sha256_str([h].pack('H*')) - end - - def sha256_str(s) - Digest::SHA2.hexdigest(s) - end - - def bigrand(bytes) - OpenSSL::Random.random_bytes(bytes).unpack("H*")[0] - end - - def multiplier - @muliplier ||= calculate_multiplier - end - - protected - - def calculate_multiplier - sha256_int(BIG_PRIME_N, GENERATOR).hex - end - - def byte_xor_hex(a, b) - a = [a].pack('H*') - b = [b].pack('H*') - a.bytes.each_with_index.map do |a_byte, i| - (a_byte ^ (b[i].ord || 0)).chr - end.join - end - end - - ## - ## SESSION - ## - - class Session - include SRP::Util - attr_accessor :user - attr_accessor :bb - - def initialize(user, aa=nil) - @user = user - @a = bigrand(32).hex - end - - def m - @m ||= sha256_hex(n_xor_g_long, login_hash, @user.salt.to_s(16), aa, bb, k) - end - - def aa - @aa ||= modpow(GENERATOR, @a).to_s(16) # A = g^a (mod N) - end - - protected - - # client: K = H( (B - kg^x) ^ (a + ux) ) - def client_secret - base = bb.hex - base -= modpow(GENERATOR, @user.private_key) * multiplier - base = base % BIG_PRIME_N - modpow(base, @user.private_key * u.hex + @a) - end - - def k - @k ||= sha256_int(client_secret) - end - - def n_xor_g_long - @n_xor_g_long ||= hn_xor_hg.bytes.map{|b| "%02x" % b.ord}.join - end - - def login_hash - @login_hash ||= sha256_str(@user.username) - end - - def u - @u ||= sha256_hex(aa, bb) - end - end - - ## - ## Dummy USER - ## - - class User - include SRP::Util - - attr_accessor :username, :password, :salt, :verifier, :id, :session_token, :ok, :deleted - - 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) - @ok = false - @deleted = false - end - - def private_key - @private_key ||= calculate_private_key - end - - def to_params - { - 'user[login]' => @username, - 'user[password_verifier]' => @verifier.to_s(16), - 'user[password_salt]' => @salt.to_s(16) - } - end - - private - - def calculate_private_key - shex = '%x' % [@salt] - inner = sha256_str([@username, @password].join(':')) - sha256_hex(shex, inner).hex - end - end - -end -- cgit v1.2.3