def test_load_config_spelunked_keys(self): # Setup tmpfile = tempfile.NamedTemporaryFile(mode="w", prefix="xrdsst-", suffix='.yaml', delete=False) tmpfile.writelines([ 'kogging:\n', ' file: asdqwe\n', 'security_server:\n', ' name: xnnn\n', ' ull: http://somesite.com' ]) tmpfile.close() # Given config_file = tmpfile.name base_controller = BaseController() base_controller.app = Mock() base_controller.app.close = Mock(return_value=None) # When base_controller.load_config(config_file) # Cleanup os.remove(config_file) # Then out, err = self.capsys.readouterr() assert err.count("kogging NOT AMONG") > 0 assert err.count("ull NOT AMONG") > 0 assert out.count("Invalid configuration keys encountered") > 0 with self.capsys.disabled(): sys.stdout.write(out) sys.stderr.write(err) base_controller.app.close.assert_called_once_with(os.EX_CONFIG)
def remote_add_endpoints_access(self, ss_api_config, security_server_conf, client_conf, service_description_conf): try: client_controller = ClientController() clients_api = ClientsApi(ApiClient(ss_api_config)) client = client_controller.find_client(clients_api, security_server_conf, client_conf) if client: service_clients_candidates = client_controller.get_clients_service_client_candidates( clients_api, client.id, []) try: service_controller = ServiceController() clients_api = ClientsApi(ApiClient(ss_api_config)) service_description = service_controller.get_client_service_description( clients_api, client, service_description_conf) if service_description.type != ServiceType().WSDL: self.remote_add_endpoint_access( ss_api_config, service_description, service_description_conf, service_clients_candidates) except ApiException as find_err: BaseController.log_api_error( ClientController. CLIENTS_API_GET_CLIENT_SERVICE_DESCRIPTION, find_err) except ApiException as find_err: BaseController.log_api_error( ClientController.CLIENTS_API_FIND_CLIENTS, find_err)
def test_load_config_malformed_yaml(self): # Setup tmpfile = tempfile.NamedTemporaryFile(mode="wb", prefix="xrdsst-", suffix='.yaml', delete=False) tmpfile.write(bytes("{a", "utf-8")) tmpfile.close() # Given config_file = tmpfile.name base_controller = BaseController() base_controller.app = Mock() base_controller.app.close = Mock(return_value=None) # When base_controller.load_config(config_file) # Cleanup os.remove(config_file) # Then out, err = self.capsys.readouterr() assert out.count("Error parsing config") > 0 assert out.count("line 1") > 0 with self.capsys.disabled(): sys.stdout.write(out) sys.stderr.write(err) base_controller.app.close.assert_called_once_with(os.EX_CONFIG)
def test_no_plain_api_key_logging(self): # Given temp_log_file = tempfile.NamedTemporaryFile(mode="wb", prefix="xrdsst-", suffix='.yaml', delete=False) temp_log_file.close() logfile_name = temp_log_file.name import logging logging.getLogger().handlers.clear() assert not logging.getLogger().handlers self._ss_config["logging"]["file"] = logfile_name base_controller = BaseController() base_controller._init_logging(self.get_ss_config()) the_api_key = '460ad0b9-d023-4087-a291-dc97eddcb7d8' # When BaseController.log_info("printf style with dict: API key '%(api_key)s' for security server %(ssn)s revoked." % {'api_key': the_api_key, 'ssn': 'madeup-ss'}) BaseController.log_info("plain concatenated string style: API key '" + the_api_key + "' for security server " + 'madeup-ss' + " revoked.") BaseController.log_info("percent style string formation: API key '%s' for revoked." % the_api_key) logging.info("direct log of api_key (info) " + the_api_key) logging.warning("direct log of api_key (warning)" + the_api_key) # Then with open(logfile_name, "r") as log_file_r: log_lines = log_file_r.readlines() assert 5 == len(log_lines) assert all(map(lambda s: s.count('********-****-4087-****-************') == 1, log_lines)) assert all(map(lambda s: s.count(the_api_key) == 0, log_lines))
def test_configfile_argument_added(self): base_controller = BaseController() base_controller._parser = Mock() base_parser = base_controller._parser base_parser.add_argument = Mock(return_value=None) base_controller._pre_argument_parsing() base_parser.add_argument.assert_called_once()
def remote_update_service_parameter(ss_api_config, service_description_conf, service): try: services_api = ServicesApi(ApiClient(ss_api_config)) for configurable_service in service_description_conf["services"]: response = None if service.service_code == configurable_service["service_code"]: timeout = int(configurable_service["timeout"]) timeout_all = bool(service_description_conf["timeout_all"]) ssl_auth = bool(configurable_service["ssl_auth"]) ssl_auth_all = bool(service_description_conf["ssl_auth_all"]) url = configurable_service["url"] url_all = bool(service_description_conf["url_all"]) service_update = ServiceUpdate(url=url, timeout=timeout, ssl_auth=ssl_auth, url_all=url_all, timeout_all=timeout_all, ssl_auth_all=ssl_auth_all) response = services_api.update_service(service.id, body=service_update) if response: BaseController.log_info("Updated service parameters for service '" + service.id + "' (got full id " + response.id + ")") except ApiException as err: BaseController.log_api_error('ServicesApi->update_service', err)
def test_unsuccessful_app_exit_with_nonexistant_config_spec(self): base_controller = BaseController() base_controller.app = Mock() base_controller.app.pargs = Mock() base_controller.app.pargs.configfile = 'just/not/there/at/all' base_controller.app.close = Mock(return_value=None) base_controller.load_config(baseconfig=None) base_controller.app.close.assert_called_once_with(os.EX_CONFIG)
def remote_download_csrs(self, ss_api_config, security_server): key_labels = self.get_key_labels(security_server) token = remote_get_token(ss_api_config, security_server) auth_keys = list( filter(lambda key: key.label in key_labels['auth'], token.keys)) sign_keys = list( filter(lambda key: key.label in key_labels['sign'], token.keys)) if not (auth_keys or sign_keys): return [] keys_api = KeysApi(ApiClient(ss_api_config)) downloaded_csrs = [] for keytype in [(sign_keys, 'sign'), (auth_keys, 'auth')]: for key in keytype[0]: for csr in key.certificate_signing_requests: with cement.utils.fs.Tmp(prefix=csr_file_prefix( keytype[1], key, csr), suffix='.der', cleanup=False) as tmp: # Impossible to get valid byte array via generated client API conversion, resort to HTTP response. http_response = keys_api.download_csr( key.id, csr.id, csr_format=CsrFormat.DER, _preload_content=False) if 200 == http_response.status: with open(tmp.file, 'wb') as file: file.write(http_response.data) downloaded_csrs.append( DownloadedCsr(csr.id, key.id, keytype[1].upper(), file.name)) else: BaseController.log_info( "Failed to download key '" + key.id + "' CSR '" + csr.id + "' (HTTP " + http_response.status + ", " + http_response.reason + ")") # Remove empty folder that fs.Tmp creates and that would remain with auto-clean off os.rmdir(tmp.dir) render_data = [] if self.is_output_tabulated(): render_data = [DownloadedCsrListMapper.headers()] render_data.extend( map(DownloadedCsrListMapper.as_list, downloaded_csrs)) else: render_data.extend( map(DownloadedCsrListMapper.as_object, downloaded_csrs)) self.render(render_data) return downloaded_csrs
def test_security_server_address_from_url(): security_server_config = {'url': 'https://somehost:64000/api/v1'} assert 'somehost' == BaseController.security_server_address( security_server_config) security_server_config['url'] = 'http://otherhost/api/v1' assert 'otherhost' == BaseController.security_server_address( security_server_config) security_server_config['url'] = 'http://192.168.1.33:4000/api/v1' assert '192.168.1.33' == BaseController.security_server_address( security_server_config)
def token_list(self, config): ss_api_conf_tuple = list( zip( config["security_server"], map(lambda ss: self.create_api_config(ss, config), config["security_server"]))) for security_server in config["security_server"]: ss_api_config = self.create_api_config(security_server, config) self.remote_token_list(ss_api_config) BaseController.log_keyless_servers(ss_api_conf_tuple)
def test_get_api_key_ssh_key_exception(self): with XRDSSTTest() as app: base_controller = BaseController() base_controller.app = app temp_file_name = os.path.join(ROOT_DIR, "conf.yaml") config = self.create_temp_conf(base_controller, temp_file_name) for security_server in config["security_server"]: security_server["api_key"] = 'TOOLKIT_API_KEY' base_controller.get_api_key(config, security_server) os.remove(temp_file_name) self.assertRaises(Exception)
def update_client(self, config): ss_api_conf_tuple = list(zip(config["security_server"], map(lambda ss: self.create_api_config(ss, config), config["security_server"]))) for security_server in config["security_server"]: ss_api_config = self.create_api_config(security_server, config) BaseController.log_debug('Starting client registrations for security server: ' + security_server['name']) if "clients" in security_server: for client in security_server["clients"]: self.remote_update_client(ss_api_config, security_server, client) BaseController.log_keyless_servers(ss_api_conf_tuple)
def add_client(self, config): ss_api_conf_tuple = list(zip(config["security_server"], map(lambda ss: self.create_api_config(ss, config), config["security_server"]))) for security_server in config["security_server"]: ss_api_config = self.create_api_config(security_server, config) BaseController.log_debug('Starting client add process for security server: ' + security_server['name']) if "clients" in security_server: # Guards both against empty section (->None) & complete lack of section for client in security_server["clients"]: self.remote_add_client(ss_api_config, client) BaseController.log_keyless_servers(ss_api_conf_tuple)
def get_clients_service_client_candidates(clients_api, client_id, candidates_ids): try: candidates = clients_api.find_service_client_candidates(client_id) if candidates_ids is None or len(candidates_ids) == 0: return candidates else: return [x for x in candidates if x.id in candidates_ids] except ApiException as find_err: BaseController.log_api_error('ClientsApi->find_service_client_candidates', find_err)
def test_init_logging_directory(self): temp_file_name = str(Path.home()) import logging logging.getLogger().handlers.clear() assert not logging.getLogger().handlers self._ss_config["logging"]["file"] = temp_file_name base_controller = BaseController() base_controller._init_logging(self.get_ss_config()) assert len(logging.getLogger().handlers) == 1
def test_init_logging_no_write_access(self): temp_file_name = "/root/nocanwrite.log" import logging logging.getLogger().handlers.clear() assert not logging.getLogger().handlers self._ss_config["logging"]["file"] = temp_file_name base_controller = BaseController() base_controller._init_logging(self.get_ss_config()) assert len(logging.getLogger().handlers) == 1
def tearDown(self): with XRDSSTTest() as app: urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) base = BaseController() base.app = app api_key_id = app.Meta.handlers[0].api_key_id del os.environ[self.config["security_server"][0]["api_key"]] if api_key_id: revoke_api_key(app) if self.config_file is not None: if os.path.exists(self.config_file): os.remove(self.config_file)
def step_init(self): base = BaseController() init = InitServerController() configuration = base.create_api_config( self.config["security_server"][0], self.config) status = init.check_init_status(configuration) assert status.is_anchor_imported is False assert status.is_server_code_initialized is False init.initialize_server(self.config) status = init.check_init_status(configuration) assert status.is_anchor_imported is True assert status.is_server_code_initialized is True
def enable_service_description(self, config): ss_api_conf_tuple = list(zip(config["security_server"], map(lambda ss: self.create_api_config(ss, config), config["security_server"]))) for security_server in config["security_server"]: ss_api_config = self.create_api_config(security_server, config) BaseController.log_debug('Starting service description enabling process for security server: ' + security_server['name']) if "clients" in security_server: for client in security_server["clients"]: if client.get("service_descriptions"): for service_description in client["service_descriptions"]: self.remote_enable_service_description(ss_api_config, security_server, client, service_description) BaseController.log_keyless_servers(ss_api_conf_tuple)
def test_load_config_access_exception(self): base_controller = BaseController() base_controller.app = Mock() config_file = "/etc/shadow" base_controller.load_config(config_file) out, err = self.capsys.readouterr() assert out.count("ermission") > 0 assert out.count("ould not read file") > 0 with self.capsys.disabled(): sys.stdout.write(out) sys.stderr.write(err)
def remote_add_service_description(ss_api_config, security_server_conf, client_conf, service_description_conf): code = service_description_conf['rest_service_code'] if service_description_conf['rest_service_code'] else None description_add = ServiceDescriptionAdd(url=service_description_conf['url'], rest_service_code=code, ignore_warnings=True, type=service_description_conf['type']) clients_api = ClientsApi(ApiClient(ss_api_config)) try: client_controller = ClientController() client = client_controller.find_client(clients_api, security_server_conf, client_conf) if client: try: response = clients_api.add_client_service_description(client.id, body=description_add) if response: BaseController.log_info("Added service description with type '" + response.type + "' and url '" + response.url + "' (got full id " + response.id + ")") except ApiException as err: if err.status == 409: BaseController.log_info(ServiceController.SERVICE_DESCRIPTION_FOR + "'" + client_controller.partial_client_id(client_conf) + "' with url '" + description_add.url + "' and type '" + description_add.type + "' already exists.") else: BaseController.log_api_error('ClientsApi->add_client_service_description', err) except ApiException as find_err: BaseController.log_api_error(ClientController.CLIENTS_API_FIND_CLIENTS, find_err)
def remote_token_add_signing_key_new_member(ss_api_config, security_server, client): new_member_class = client[ ConfKeysSecServerClients.CONF_KEY_SS_CLIENT_MEMBER_CLASS] new_member_code = client[ ConfKeysSecServerClients.CONF_KEY_SS_CLIENT_MEMBER_CODE] new_member_name = client[ ConfKeysSecServerClients.CONF_KEY_SS_CLIENT_MEMBER_NAME] token_id = security_server[ ConfKeysSecurityServer.CONF_KEY_SOFT_TOKEN_ID] ss_code = security_server[ConfKeysSecurityServer.CONF_KEY_SERVER_CODE] dn_country = security_server[ConfKeysSecurityServer.CONF_KEY_DN_C] sign_key_label = default_member_sign_key_label(security_server, client) ssi = remote_get_security_server_instance(ss_api_config) token = remote_get_token(ss_api_config, security_server) sign_ca = remote_get_sign_certificate_authority(ss_api_config) token_key_labels = list(map(lambda key: key.label, token.keys)) has_sign_key = sign_key_label in token_key_labels sign_cert_subject = { 'C': dn_country, 'O': new_member_name, 'CN': new_member_code, 'serialNumber': '/'.join([ssi.instance_id, ss_code, new_member_class]) } sign_key_req_param = KeyLabelWithCsrGenerate( key_label=sign_key_label, csr_generate_request=CsrGenerate( key_usage_type=KeyUsageType.SIGNING, ca_name=sign_ca.name, csr_format=CsrFormat. DER, # Test CA setup at least only works with DER member_id=':'.join( [ssi.instance_id, new_member_class, str(new_member_code)]), subject_field_values=sign_cert_subject)) token_api = TokensApi(ApiClient(ss_api_config)) if not has_sign_key: try: BaseController.log_info( TokenLabels.generate_key(token_id, sign_key_label, 'SIGN')) response = token_api.add_key_and_csr(token_id, body=sign_key_req_param) BaseController.log_info("Created " + str(response.key.usage) + " CSR '" + response.csr_id + "' for key '" + response.key.id + "' as '" + response.key.label + "'") except ApiException as err: BaseController.log_api_error(TokenLabels.error(), err) else: BaseController.log_info( "Skipping KEY and CSR creation, key for member " + '/'.join([ ssi.instance_id, ss_code, new_member_class, str(new_member_code) ]) + "already exists")
def add_endpoint_access(self, config): ss_api_conf_tuple = list( zip( config["security_server"], map(lambda ss: self.create_api_config(ss, config), config["security_server"]))) for service_description_dic in self.get_services_description(config): self.remote_add_endpoints_access( service_description_dic["ss_api_config"], service_description_dic["security_server"], service_description_dic["client"], service_description_dic["service_description"]) BaseController.log_keyless_servers(ss_api_conf_tuple)
def remote_import_certificates(ss_api_config, security_server): token_cert_api = TokenCertificatesApi(ApiClient(ss_api_config)) for cert in security_server["certificates"]: location = cement.utils.fs.join_exists(cert) if not location[1]: BaseController.log_info("Certificate '" + location[0] + "' does not exist") else: cert_file_loc = location[0] try: cert_file = open(cert_file_loc, "rb") cert_data = cert_file.read() cert_file.close() token_cert_api.import_certificate(body=cert_data) BaseController.log_info("Imported certificate '" + cert_file_loc + "'") except ApiException as err: if err.status == 409 and err.body.count( "certificate_already_exists"): BaseController.log_info("Certificate '" + cert_file_loc + "' already imported.") else: BaseController.log_api_error( 'TokenCertificatesApi->import_certificate', err)
def activate_certificate(self, config): ss_api_conf_tuple = list( zip( config["security_server"], map(lambda ss: self.create_api_config(ss, config), config["security_server"]))) for security_server in config["security_server"]: ss_api_config = self.create_api_config(security_server, config) BaseController.log_debug( 'Starting certificate activation for security server: ' + security_server['name']) self.remote_activate_certificate(ss_api_config, security_server) BaseController.log_keyless_servers(ss_api_conf_tuple)
def token_login(self, config): ss_api_conf_tuple = list( zip( config["security_server"], map(lambda ss: self.create_api_config(ss, config), config["security_server"]))) for security_server in config["security_server"]: ss_api_config = self.create_api_config(security_server, config) BaseController.log_debug( 'Starting token login process for security server: ' + security_server['name']) self.remote_token_login(ss_api_config, security_server) BaseController.log_keyless_servers(ss_api_conf_tuple)
def remote_update_service_parameters(self, ss_api_config, security_server_conf, client_conf, service_description_conf): clients_api = ClientsApi(ApiClient(ss_api_config)) try: client_controller = ClientController() client = client_controller.find_client(clients_api, security_server_conf, client_conf) if client: try: service_description = self.get_client_service_description(clients_api, client, service_description_conf) if service_description: for service in service_description.services: self.remote_update_service_parameter(ss_api_config, service_description_conf, service) except ApiException as find_err: BaseController.log_api_error(ClientController.CLIENTS_API_GET_CLIENT_SERVICE_DESCRIPTION, find_err) except ApiException as find_err: BaseController.log_api_error(ClientController.CLIENTS_API_FIND_CLIENTS, find_err)
def setUp(self): with XRDSSTTest() as app: urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) idx = 0 for arg in sys.argv: idx += 1 if arg == "-c": self.config_file = sys.argv[idx] base = BaseController() base.app = app self.config = base.load_config(baseconfig=self.config_file) for security_server in self.config["security_server"]: api_key = base.get_api_key(self.config, security_server) self.create_api_key(api_key)
def test_get_api_key_json_exception(self): with XRDSSTTest() as app: base_controller = BaseController() base_controller.app = app temp_file_name = os.path.join(ROOT_DIR, "conf.yaml") config = self.create_temp_conf(base_controller, temp_file_name) temp_key_file = open("my_key", "w") temp_key_file.close() ssh_access = config["ssh_access"] for security_server in config["security_server"]: ssh_access["private_key"] = 'my_key' security_server["api_key"] = 'TOOLKIT_API_KEY' base_controller.get_api_key(config, security_server) os.remove(temp_file_name) os.remove("my_key") self.assertRaises(Exception)
def test_get_api_key(self): with XRDSSTTest() as app: with patch.object(BaseController, 'create_api_key', return_value='88888888-8000-4000-a000-727272727272'): base_controller = BaseController() base_controller.app = app temp_file_name = os.path.join(ROOT_DIR, "conf.yaml") config = self.create_temp_conf(base_controller, temp_file_name) for security_server in config["security_server"]: security_server["api_key"] = 'some key' key = base_controller.get_api_key(config, security_server) assert key != 'api-key-123' os.environ["TOOLKIT_API_KEY"] = "" security_server["api_key"] = 'TOOLKIT_API_KEY' key = base_controller.get_api_key(config, security_server) assert key == '88888888-8000-4000-a000-727272727272' os.remove(temp_file_name)