def test_validate_storage(unvalidated_config, expected, app): validator = StorageValidator() if expected is not None: with pytest.raises(expected): validator.validate(ValidatorContext(unvalidated_config)) else: validator.validate(ValidatorContext(unvalidated_config))
def test_validate_oidc_login(app): url_hit = [False] @urlmatch(netloc=r'someserver', path=r'/\.well-known/openid-configuration') def handler(_, __): url_hit[0] = True data = { 'token_endpoint': 'foobar', } return {'status_code': 200, 'content': json.dumps(data)} with HTTMock(handler): validator = OIDCLoginValidator() unvalidated_config = ValidatorContext({ 'SOMETHING_LOGIN_CONFIG': { 'CLIENT_ID': 'foo', 'CLIENT_SECRET': 'bar', 'OIDC_SERVER': 'http://someserver', 'DEBUGGING': True, # Allows for HTTP. }, }) unvalidated_config.http_client = build_requests_session() validator.validate(unvalidated_config) assert url_hit[0]
def test_validate_google_login(app): url_hit = [False] @urlmatch(netloc=r"www.googleapis.com", path="/oauth2/v3/token") def handler(_, __): url_hit[0] = True return {"status_code": 200, "content": ""} validator = GoogleLoginValidator() with HTTMock(handler): unvalidated_config = ValidatorContext( { "GOOGLE_LOGIN_CONFIG": { "CLIENT_ID": "foo", "CLIENT_SECRET": "bar", }, } ) unvalidated_config.http_client = build_requests_session() validator.validate(unvalidated_config) assert url_hit[0]
def test_validate_oidc_login(app): url_hit = [False] @urlmatch(netloc=r"someserver", path=r"/\.well-known/openid-configuration") def handler(_, __): url_hit[0] = True data = { "token_endpoint": "foobar", } return {"status_code": 200, "content": json.dumps(data)} with HTTMock(handler): validator = OIDCLoginValidator() unvalidated_config = ValidatorContext({ "SOMETHING_LOGIN_CONFIG": { "CLIENT_ID": "foo", "CLIENT_SECRET": "bar", "OIDC_SERVER": "http://someserver", "DEBUGGING": True, # Allows for HTTP. }, }) unvalidated_config.http_client = build_requests_session() validator.validate(unvalidated_config) assert url_hit[0]
def test_validate_invalid_oidc_login_config(unvalidated_config, expected_exception, app): validator = AccessSettingsValidator() if expected_exception is not None: with pytest.raises(expected_exception): validator.validate(ValidatorContext(unvalidated_config)) else: validator.validate(ValidatorContext(unvalidated_config))
def test_validate(default_exp, options, expected_exception, app): config = {} config["DEFAULT_TAG_EXPIRATION"] = default_exp config["TAG_EXPIRATION_OPTIONS"] = options if expected_exception is not None: with pytest.raises(ConfigValidationException) as cve: TimeMachineValidator.validate(ValidatorContext(config)) assert str(cve.value) == str(expected_exception) else: TimeMachineValidator.validate(ValidatorContext(config))
def test_validate_redis(unvalidated_config, user, user_password, use_mock, expected, app): with patch("redis.StrictRedis" if use_mock else "redis.None", mock_strict_redis_client): validator = RedisValidator() unvalidated_config = ValidatorContext(unvalidated_config) unvalidated_config.user = AttrDict(dict(username=user)) unvalidated_config.user_password = user_password if expected is not None: with pytest.raises(expected): validator.validate(unvalidated_config) else: validator.validate(unvalidated_config)
def test_validate_s3_storage(app): validator = StorageValidator() with mock_s3(): with pytest.raises(ConfigValidationException) as ipe: validator.validate( ValidatorContext( { "DISTRIBUTED_STORAGE_CONFIG": { "default": ( "S3Storage", { "s3_access_key": "invalid", "s3_secret_key": "invalid", "s3_bucket": "somebucket", "storage_path": "", }, ), } } ) ) assert ( str(ipe.value) == "Invalid storage configuration: default: S3ResponseError: 404 Not Found" )
def test_validate_bitbucket_trigger(app): url_hit = [False] @urlmatch(netloc=r'bitbucket.org') def handler(url, request): url_hit[0] = True return { 'status_code': 200, 'content': 'oauth_token=foo&oauth_token_secret=bar', } with HTTMock(handler): validator = BitbucketTriggerValidator() url_scheme_and_hostname = URLSchemeAndHostname('http', 'localhost:5000') unvalidated_config = ValidatorContext( { 'BITBUCKET_TRIGGER_CONFIG': { 'CONSUMER_KEY': 'foo', 'CONSUMER_SECRET': 'bar', }, }, url_scheme_and_hostname=url_scheme_and_hostname) validator.validate(unvalidated_config) assert url_hit[0]
def test_validate_gitlab_enterprise_trigger(app): url_hit = [False] @urlmatch(netloc=r'somegitlab', path='/oauth/token') def handler(_, __): url_hit[0] = True return { 'status_code': 400, 'content': json.dumps({'error': 'invalid code'}) } with HTTMock(handler): validator = GitLabTriggerValidator() url_scheme_and_hostname = URLSchemeAndHostname('http', 'localhost:5000') unvalidated_config = ValidatorContext( { 'GITLAB_TRIGGER_CONFIG': { 'GITLAB_ENDPOINT': 'http://somegitlab', 'CLIENT_ID': 'foo', 'CLIENT_SECRET': 'bar', }, }, http_client=build_requests_session(), url_scheme_and_hostname=url_scheme_and_hostname) validator.validate(unvalidated_config) assert url_hit[0]
def test_validate_bitbucket_trigger(app): url_hit = [False] @urlmatch(netloc=r"bitbucket.org") def handler(url, request): url_hit[0] = True return { "status_code": 200, "content": "oauth_token=foo&oauth_token_secret=bar", } with HTTMock(handler): validator = BitbucketTriggerValidator() url_scheme_and_hostname = URLSchemeAndHostname("http", "localhost:5000") unvalidated_config = ValidatorContext( { "BITBUCKET_TRIGGER_CONFIG": { "CONSUMER_KEY": "foo", "CONSUMER_SECRET": "bar", }, }, url_scheme_and_hostname=url_scheme_and_hostname, ) validator.validate(unvalidated_config) assert url_hit[0]
def test_invalid_config(config, expected_error, app): validator = ActionLogArchivingValidator() with pytest.raises(ConfigValidationException) as ipe: validator.validate(ValidatorContext(config)) assert str(ipe.value) == expected_error
def test_validate_gitlab_enterprise_trigger(app): url_hit = [False] @urlmatch(netloc=r"somegitlab", path="/oauth/token") def handler(_, __): url_hit[0] = True return { "status_code": 400, "content": json.dumps({"error": "invalid code"}) } with HTTMock(handler): validator = GitLabTriggerValidator() url_scheme_and_hostname = URLSchemeAndHostname("http", "localhost:5000") unvalidated_config = ValidatorContext( { "GITLAB_TRIGGER_CONFIG": { "GITLAB_ENDPOINT": "http://somegitlab", "CLIENT_ID": "foo", "CLIENT_SECRET": "bar", }, }, http_client=build_requests_session(), url_scheme_and_hostname=url_scheme_and_hostname, ) validator.validate(unvalidated_config) assert url_hit[0]
def test_validate_auth(app): config = ValidatorContext({ 'AUTHENTICATION_TYPE': 'AppToken', 'FEATURE_APP_SPECIFIC_TOKENS': True, 'FEATURE_DIRECT_LOGIN': False, }) validator = AppTokenAuthValidator() validator.validate(config)
def test_validate_auth(app): config = ValidatorContext({ "AUTHENTICATION_TYPE": "AppToken", "FEATURE_APP_SPECIFIC_TOKENS": True, "FEATURE_DIRECT_LOGIN": False, }) validator = AppTokenAuthValidator() validator.validate(config)
def test_validate_noop(unvalidated_config, app): unvalidated_config = ValidatorContext( unvalidated_config, feature_sec_scanner=False, is_testing=True, http_client=build_requests_session(), url_scheme_and_hostname=URLSchemeAndHostname('http', 'localhost:5000')) SecurityScannerValidator.validate(unvalidated_config)
def test_validate_ssl(cert, server_hostname, expected_error, error_message, app): with NamedTemporaryFile(delete=False) as cert_file: cert_file.write(Bytes.for_string_or_unicode(cert[0]).as_encoded_str()) cert_file.seek(0) with NamedTemporaryFile(delete=False) as key_file: key_file.write( Bytes.for_string_or_unicode(cert[1]).as_encoded_str()) key_file.seek(0) def return_true(filename): return True def get_volume_file(filename, mode="r"): if filename == SSL_FILENAMES[0]: return open(cert_file.name, mode=mode) if filename == SSL_FILENAMES[1]: return open(key_file.name, mode=mode) return None config = { "PREFERRED_URL_SCHEME": "https", "SERVER_HOSTNAME": server_hostname, } with patch("app.config_provider.volume_file_exists", return_true): with patch("app.config_provider.get_volume_file", get_volume_file): validator = SSLValidator() config = ValidatorContext(config) config.config_provider = config_provider if expected_error is not None: with pytest.raises(expected_error) as ipe: validator.validate(config) assert str(ipe.value) == error_message else: validator.validate(config)
def test_valid_config(app): config = ValidatorContext({ "FEATURE_ACTION_LOG_ROTATION": True, "ACTION_LOG_ARCHIVE_PATH": "somepath", "ACTION_LOG_ARCHIVE_LOCATION": "somelocation", "DISTRIBUTED_STORAGE_CONFIG": { "somelocation": {}, }, }) validator = ActionLogArchivingValidator() validator.validate(config)
def test_valid_config(app): config = ValidatorContext({ 'FEATURE_ACTION_LOG_ROTATION': True, 'ACTION_LOG_ARCHIVE_PATH': 'somepath', 'ACTION_LOG_ARCHIVE_LOCATION': 'somelocation', 'DISTRIBUTED_STORAGE_CONFIG': { 'somelocation': {}, }, }) validator = ActionLogArchivingValidator() validator.validate(config)
def test_validate_elasticsearch(unvalidated_config, expected): validator = KinesisValidator() unvalidated_config = ValidatorContext(unvalidated_config) with patch("botocore.client") as bc: bc.Kinesis.describe_stream.return_value = _TEST_RESPONSE if expected is not None: with pytest.raises(expected): validator.validate(unvalidated_config) else: validator.validate(unvalidated_config)
def test_invalid_uri(uri, app): config = {} config['AUTHENTICATION_TYPE'] = 'LDAP' config['LDAP_BASE_DN'] = ['dc=quay', 'dc=io'] config['LDAP_ADMIN_DN'] = 'uid=testy,ou=employees,dc=quay,dc=io' config['LDAP_ADMIN_PASSWD'] = 'password' config['LDAP_USER_RDN'] = ['ou=employees'] config['LDAP_URI'] = uri with pytest.raises(ConfigValidationException): config = ValidatorContext(config, config_provider=config_provider) LDAPValidator.validate(config)
def test_invalid_uri(uri, app): config = {} config["AUTHENTICATION_TYPE"] = "LDAP" config["LDAP_BASE_DN"] = ["dc=quay", "dc=io"] config["LDAP_ADMIN_DN"] = "uid=testy,ou=employees,dc=quay,dc=io" config["LDAP_ADMIN_PASSWD"] = "password" config["LDAP_USER_RDN"] = ["ou=employees"] config["LDAP_URI"] = uri with pytest.raises(ConfigValidationException): config = ValidatorContext(config, config_provider=config_provider) LDAPValidator.validate(config)
def test_validate_torrent(unvalidated_config, expected, app): announcer_hit = [False] @urlmatch(netloc=r"faketorrent", path="/announce") def handler(url, request): announcer_hit[0] = True return {"status_code": 200, "content": ""} with HTTMock(handler): validator = BittorrentValidator() if expected is not None: with pytest.raises(expected): config = ValidatorContext(unvalidated_config, instance_keys=instance_keys) config.http_client = build_requests_session() validator.validate(config) assert not announcer_hit[0] else: config = ValidatorContext(unvalidated_config, instance_keys=instance_keys) config.http_client = build_requests_session() validator.validate(config) assert announcer_hit[0]
def test_validate_github(github_validator, app): url_hit = [False, False] @urlmatch(netloc=r"somehost") def handler(url, request): url_hit[0] = True return { "status_code": 200, "content": "", "headers": { "X-GitHub-Request-Id": "foo" } } @urlmatch(netloc=r"somehost", path=r"/api/v3/applications/foo/tokens/foo") def app_handler(url, request): url_hit[1] = True return { "status_code": 404, "content": "", "headers": { "X-GitHub-Request-Id": "foo" } } with HTTMock(app_handler, handler): unvalidated_config = ValidatorContext({ github_validator.config_key: { "GITHUB_ENDPOINT": "http://somehost", "CLIENT_ID": "foo", "CLIENT_SECRET": "bar", }, }) unvalidated_config.http_client = build_requests_session() github_validator.validate(unvalidated_config) assert url_hit[0] assert url_hit[1]
def test_validate_github(github_validator, app): url_hit = [False, False] @urlmatch(netloc=r'somehost') def handler(url, request): url_hit[0] = True return { 'status_code': 200, 'content': '', 'headers': { 'X-GitHub-Request-Id': 'foo' } } @urlmatch(netloc=r'somehost', path=r'/api/v3/applications/foo/tokens/foo') def app_handler(url, request): url_hit[1] = True return { 'status_code': 404, 'content': '', 'headers': { 'X-GitHub-Request-Id': 'foo' } } with HTTMock(app_handler, handler): unvalidated_config = ValidatorContext({ github_validator.config_key: { 'GITHUB_ENDPOINT': 'http://somehost', 'CLIENT_ID': 'foo', 'CLIENT_SECRET': 'bar', }, }) unvalidated_config.http_client = build_requests_session() github_validator.validate(unvalidated_config) assert url_hit[0] assert url_hit[1]
def test_validate_google_login(app): url_hit = [False] @urlmatch(netloc=r'www.googleapis.com', path='/oauth2/v3/token') def handler(_, __): url_hit[0] = True return {'status_code': 200, 'content': ''} validator = GoogleLoginValidator() with HTTMock(handler): unvalidated_config = ValidatorContext({ 'GOOGLE_LOGIN_CONFIG': { 'CLIENT_ID': 'foo', 'CLIENT_SECRET': 'bar', }, }) unvalidated_config.http_client = build_requests_session() validator.validate(unvalidated_config) assert url_hit[0]
def test_validate(unvalidated_config, expected_error, app): unvalidated_config = ValidatorContext( unvalidated_config, feature_sec_scanner=True, is_testing=True, http_client=build_requests_session(), url_scheme_and_hostname=URLSchemeAndHostname('http', 'localhost:5000')) with fake_security_scanner(hostname='fakesecurityscanner'): if expected_error is not None: with pytest.raises(expected_error): SecurityScannerValidator.validate(unvalidated_config) else: SecurityScannerValidator.validate(unvalidated_config)
def post(self, service): """ Validates the given config for the given service. """ # Note: This method is called to validate the database configuration before super users exists, # so we also allow it to be called if there is no valid registry configuration setup. Note that # this is also safe since this method does not access any information not given in the request. config = request.get_json()['config'] validator_context = ValidatorContext.from_app( app, config, request.get_json().get('password', ''), instance_keys=instance_keys, ip_resolver=ip_resolver, config_provider=config_provider, init_scripts_location=INIT_SCRIPTS_LOCATION) return validate_service_for_config(service, validator_context)
def test_validate_elasticsearch(unvalidated_config, expected, app): validator = ElasticsearchValidator() path = unvalidated_config.get("index_prefix") or INDEX_NAME_PREFIX path = "/" + path + "*" unvalidated_config = ValidatorContext(unvalidated_config) @urlmatch(netloc=r"", path=path) def handler(url, request): return {"status_code": 200, "content": b"{}"} with HTTMock(handler): if expected is not None: with pytest.raises(expected): validator.validate(unvalidated_config) else: validator.validate(unvalidated_config)
def test_validated_keystone(admin_tenant_id, expected_exception, app): with fake_keystone(2) as keystone_auth: auth_url = keystone_auth.auth_url config = {} config["AUTHENTICATION_TYPE"] = "Keystone" config["KEYSTONE_AUTH_URL"] = auth_url config["KEYSTONE_ADMIN_USERNAME"] = "******" config["KEYSTONE_ADMIN_PASSWORD"] = "******" config["KEYSTONE_ADMIN_TENANT"] = admin_tenant_id unvalidated_config = ValidatorContext(config) if expected_exception is not None: with pytest.raises(ConfigValidationException): KeystoneValidator.validate(unvalidated_config) else: KeystoneValidator.validate(unvalidated_config)