def test_select_auth_no_match(auth_config, tmpdir): no_match = "No matching credential found" # no credentials at all with pytest.raises(RuntimeError) as err: selected = auth.select_matching_auth([], "example.com", "nosuchuser") assert "No matching credential found for hostname 'example.com'" in err.value.args[ 0] # no match for requested hostname with_host = """auth = [{ username = "******", password = "******", hostname = "example.com" }]""" with temp_config(tmpdir, with_host) as config_dir, \ temp_environ(XDG_CONFIG_HOME=config_dir), pytest.raises(RuntimeError) as err: creds = auth.load_auth() selected = auth.select_matching_auth(creds, "example.net") assert f"{no_match} for hostname 'example.net'" in err.value.args[0] # no match for requested username with temp_config(tmpdir, auth_config) as config_dir, \ temp_environ(XDG_CONFIG_HOME=config_dir), pytest.raises(RuntimeError) as err: creds = auth.load_auth() selected = auth.select_matching_auth(creds, "example.com", "nosuchuser") assert f"{no_match} for hostname 'example.com' with username 'nosuchuser'" in err.value.args[ 0]
def test_load_auth_bad_perms(auth_config, tmpdir): for bad_perm in [ stat.S_IRGRP, stat.S_IWGRP, stat.S_IXGRP, stat.S_IROTH, stat.S_IWOTH, stat.S_IXOTH ]: with temp_config(tmpdir, auth_config, bad_perm) as config_dir, \ temp_environ(XDG_CONFIG_HOME=config_dir), pytest.raises(RuntimeError): auth.load_auth()
def test_load_auth_options(auth_config, tmpdir): # SSL should be used by default # The default mechanism should be SCRAM_SHA_512 with temp_config(tmpdir, auth_config) as config_dir, \ temp_environ(XDG_CONFIG_HOME=config_dir), patch("hop.auth.Auth") as auth_mock: auth.load_auth() assert auth_mock.called_with(ssl=True) from adc.auth import SASLMethod assert auth_mock.called_with(mechanism=SASLMethod.SCRAM_SHA_512) # But it should be possible to disable SSL use_plaintext = """auth = [{ username = "******", password = "******", protocol = "SASL_PLAINTEXT" }]""" with temp_config(tmpdir, use_plaintext) as config_dir, \ temp_environ(XDG_CONFIG_HOME=config_dir), patch("hop.auth.Auth") as auth_mock: auth.load_auth() assert auth_mock.called_with(ssl=False) # An SSL CA data path should be honored with_ca_data = """auth = [{ username = "******", password = "******", ssl_ca_location = "/foo/bar/baz" }]""" with temp_config(tmpdir, with_ca_data) as config_dir, \ temp_environ(XDG_CONFIG_HOME=config_dir), patch("hop.auth.Auth") as auth_mock: auth.load_auth() assert auth_mock.called_with(ssl_ca_location="/foo/bar/baz") # Alternate mechanisms should be honored plain_mechanism = """auth = [{ username = "******", password = "******", mechanism = "PLAIN" }]""" with temp_config(tmpdir, plain_mechanism) as config_dir, \ temp_environ(XDG_CONFIG_HOME=config_dir), patch("hop.auth.Auth") as auth_mock: auth.load_auth() assert auth_mock.called_with(mechanism=SASLMethod.PLAIN) # Associated hostnames should be included with_host = """auth = [{ username = "******", password = "******", hostname = "example.com" }]""" with temp_config(tmpdir, with_host) as config_dir, \ temp_environ(XDG_CONFIG_HOME=config_dir): creds = auth.load_auth() assert len(creds) == 1 assert creds[0].hostname == "example.com"
def test_load_auth_malformed(tmpdir): missing_username = """ auth = [{extra="stuff", password="******"}] """ with temp_config(tmpdir, missing_username) as config_dir, \ temp_environ(XDG_CONFIG_HOME=config_dir), pytest.raises(RuntimeError): auth.load_auth() missing_password = """ auth = [{username="******", extra="stuff"}] """ with temp_config(tmpdir, missing_password) as config_dir, \ temp_environ(XDG_CONFIG_HOME=config_dir), pytest.raises(RuntimeError): auth.load_auth()
def _main(args): """Stream TNS objects to Hopskotch. """ # set up logging logging.basicConfig( level=utils.get_log_level(args.verbose), format="%(asctime)s | tns2hop : %(levelname)s : %(message)s", ) # lower verbosity of schedule logger logging.getLogger('schedule').setLevel(logging.WARNING) # load parameters file with open(args.params_file, "r") as f: parameters_list = json.load(f)["data"] # open stream to hop stream = io.Stream(auth=auth.load_auth(args.config)) sink = stream.open(args.hop_url + "tns", "w") # schedule everyday exact_time = "23:00" schedule.every().day.at(exact_time).do(job, sink, args.api_key, parameters_list) try: while True: schedule.run_pending() time.sleep(1) except KeyboardInterrupt: pass except Exception: raise finally: sink.close()
def _main(args): """Stream GCN alerts to Hopskotch. """ # set up logging logging.basicConfig( level=utils.get_log_level(args.verbose), format="%(asctime)s | gcn2hop : %(levelname)s : %(message)s", ) # Line buffer stdout and stderr sys.stdout = os.fdopen(sys.stdout.fileno(), "w", buffering=1) sys.stderr = os.fdopen(sys.stderr.fileno(), "w", buffering=1) hop_url = args.hop_url + "gcn" hop_conf_file = os.path.expanduser(args.config) host = tuple(args.hosts.split(",")) port = args.port logger.info("starting up") logger.info(f"GCN host list: {repr(host)}") logger.info(f"GCN port: {port}") logger.info(f"Hop server URL: {hop_url}") logger.info(f"Hop config file: {hop_conf_file}") # open stream to hop stream = io.Stream(auth=auth.load_auth(hop_conf_file)) sink = stream.open(hop_url, "w") try: gcn.voeventclient.listen(host=host, port=port, handler=write_to_hop(sink)) except KeyboardInterrupt: pass except Exception: raise finally: sink.close()
def test_load_auth_malformed(tmpdir): missing_username = """ [auth] password = "******" extra = "stuff" """ with temp_config(tmpdir, missing_username) as config_dir, \ temp_environ(XDG_CONFIG_HOME=config_dir), pytest.raises(KeyError): auth.load_auth() missing_password = """ [auth] username = "******" extra = "stuff" """ with temp_config(tmpdir, missing_password) as config_dir, \ temp_environ(XDG_CONFIG_HOME=config_dir), pytest.raises(KeyError): auth.load_auth()
def test_auth_location_fallback(tmpdir): valid_auth = "auth = [{username=\"user\",password=\"pass\"}]" other_auth = "auth = [{username=\"other-user\",password=\"other-pass\"}]" config_dir = f"{tmpdir}/hop" os.makedirs(config_dir, exist_ok=True) def write_file(name: str, data: str): file_path = f"{config_dir}/{name}" with open(file_path, 'w') as file: os.chmod(file_path, stat.S_IRUSR | stat.S_IWUSR) file.write(data) with temp_environ(XDG_CONFIG_HOME=str(tmpdir)): # If both auth.toml and config.toml contain auth data, only auth.toml should be read write_file("auth.toml", valid_auth) write_file("config.toml", other_auth) creds = auth.load_auth() assert len(creds) == 1 assert creds[0].username == "user" # If auth.toml does not exist and config.toml contains valid auth data, it should be read os.remove(f"{config_dir}/auth.toml") creds = auth.load_auth() assert len(creds) == 1 assert creds[0].username == "other-user" # If auth.toml does not exist and config.toml exists but contains no valid auth data, the # resulting error should be about auth.toml write_file("config.toml", "") with pytest.raises(FileNotFoundError) as err: creds = auth.load_auth() assert "auth.toml" in err.value.filename # If neither auth.toml nor config.toml exixts, the error should be about auth.toml os.remove(f"{config_dir}/config.toml") with pytest.raises(FileNotFoundError) as err: creds = auth.load_auth() assert "auth.toml" in err.value.filename
def check_credential_deletion(config_file, removed_index): """Check that a particular credential is not in a config file after removal, and that all other are still present. Args: config_file: Path to the file to check. removed_index: Index of the credential in delete_input_creds which should not be present. """ observed = auth.load_auth(config_file) for idx, cred in enumerate(delete_input_creds): if idx == removed_index: assert cred not in observed else: assert cred in observed
def test_load_auth_options(auth_config, tmpdir): # SSL should be used by default # The default mechanism should be SCRAM_SHA_512 with temp_config(tmpdir, auth_config) as config_dir, \ temp_environ(XDG_CONFIG_HOME=config_dir), patch("hop.auth.Auth") as auth_mock: auth.load_auth() assert auth_mock.called_with(ssl=True) from adc.auth import SASLMethod assert auth_mock.called_with(mechanism=SASLMethod.SCRAM_SHA_512) # But it should be possible to disable SSL use_plaintext = """ [auth] username = "******" password = "******" protocol = "SASL_PLAINTEXT" """ with temp_config(tmpdir, use_plaintext) as config_dir, \ temp_environ(XDG_CONFIG_HOME=config_dir), patch("hop.auth.Auth") as auth_mock: auth.load_auth() assert auth_mock.called_with(ssl=False) # An SSL CA data path should be honored with_ca_data = """ [auth] username = "******" password = "******" ssl_ca_location = "/foo/bar/baz" """ with temp_config(tmpdir, with_ca_data) as config_dir, \ temp_environ(XDG_CONFIG_HOME=config_dir), patch("hop.auth.Auth") as auth_mock: auth.load_auth() assert auth_mock.called_with(ssl_ca_location="/foo/bar/baz") # Alternate mechanisms should be honored plain_mechanism = """ [auth] username = "******" password = "******" mechanism = "PLAIN" """ with temp_config(tmpdir, plain_mechanism) as config_dir, \ temp_environ(XDG_CONFIG_HOME=config_dir), patch("hop.auth.Auth") as auth_mock: auth.load_auth() assert auth_mock.called_with(mechanism=SASLMethod.PLAIN)
def test_add_credential_conflict_with_host(tmpdir, caplog): old_cred = auth.Auth("username", "password", "example.com") new_cred = auth.Auth("username", "other_pass", "example.com") unrelated_cred = auth.Auth("username", "unrelated_pass", "example.org") with temp_environ(HOME=str(tmpdir)), \ patch("hop.auth.read_new_credential", MagicMock(return_value=new_cred)): auth.write_auth_data(configure.get_config_path("auth"), [old_cred, unrelated_cred]) args = MagicMock() args.cred_file = None args.force = False auth.add_credential(args) # without the force option, the old credential should not be overwritten check_credential_file(configure.get_config_path("auth"), old_cred) assert "Credential already exists; overwrite with --force" in caplog.text args.force = True auth.add_credential(args) # with the force option, the old credential should be overwritten check_credential_file(configure.get_config_path("auth"), new_cred) # also check that unrelated credentials haven't been removed creds = auth.load_auth(configure.get_config_path("auth")) assert unrelated_cred in creds
def test_load_auth_muliple_creds(tmpdir): two_creds = """auth = [ { username = "******", password = "******", hostname = "host1" }, { username = "******", password = "******", hostname = "host2" }, ]""" with temp_config( tmpdir, two_creds) as config_dir, temp_environ(XDG_CONFIG_HOME=config_dir): creds = auth.load_auth() assert len(creds) == 2 assert creds[0].username == "user1" assert creds[0].password == "pass1" assert creds[0].hostname == "host1" assert creds[1].username == "user2" assert creds[1].password == "pass2" assert creds[1].hostname == "host2"
def test_load_auth_invalid_toml(tmpdir): garbage = "KHFBGKJSBVJKbdfb ,s ,msb vks bs" with temp_config(tmpdir, garbage) as config_dir, \ temp_environ(XDG_CONFIG_HOME=config_dir), pytest.raises(RuntimeError): auth.load_auth()
def test_load_auth_non_existent(auth_config, tmpdir): with temp_environ(XDG_CONFIG_HOME=str(tmpdir)), \ pytest.raises(FileNotFoundError): auth.load_auth()
def test_load_auth(auth_config, tmpdir): with temp_config(tmpdir, auth_config) as config_dir, temp_environ( XDG_CONFIG_HOME=config_dir): auth_data = auth.load_auth() assert len(auth_data) == 1 assert auth_data[0].username == "username"
def credential_write_read_round_trip(orig_cred, file_path): auth.write_auth_data(file_path, [orig_cred]) read_creds = auth.load_auth(file_path) assert len(read_creds) == 1 assert read_creds[0] == orig_cred