def __init__(self): """Initializes the EnvironCredentialProvider.""" log.warning("Security warning: Storing credentials in environment variables " "is insecure and is not recommended.") url = os.environ.get('CBC_URL', os.environ.get('CBAPI_URL', None)) token = os.environ.get('CBC_TOKEN', os.environ.get('CBAPI_TOKEN', None)) ssl_verify = os.environ.get('CBC_SSL_VERIFY', os.environ.get('CBAPI_SSL_VERIFY', True)) org_key = os.environ.get('CBC_ORG_KEY', os.environ.get('CBAPI_ORG_KEY', None)) self._credentials = Credentials({CredentialValue.URL: url, CredentialValue.TOKEN: token, CredentialValue.ORG_KEY: org_key, CredentialValue.SSL_VERIFY: ssl_verify})
def test_session_ignore_system_proxy(): """Test to make sure the ignore system proxy parameter has the right effect.""" creds = Credentials({ 'url': 'https://example.com', 'token': 'ABCDEFGH', 'ignore_system_proxy': True }) conn = Connection(creds) assert conn.proxies['http'] == '' assert conn.proxies['https'] == '' assert conn.proxies['no'] == 'pass'
def test_session_cert_file_and_proxies(): """Test to make sure the certificate file and proxy parameters get stashed in the right place.""" creds = Credentials({ 'url': 'https://example.com', 'token': 'ABCDEFGH', 'ssl_cert_file': 'blort', 'proxy': 'foobie.bletch.com' }) conn = Connection(creds) assert conn.ssl_verify == 'blort' assert conn.proxies['http'] == 'foobie.bletch.com' assert conn.proxies['https'] == 'foobie.bletch.com'
def test_BaseAPI_init_credential_provider_raises_error(): """Test initializing the credentials when the provider raises an error.""" creds = Credentials({ 'url': 'https://example.com', 'token': 'ABCDEFGHIJKLM', 'org_key': 'A1B2C3D4' }) mock_provider = MockCredentialProvider({'my_section': creds}) with pytest.raises(CredentialError): BaseAPI(integration_name='test4', credential_provider=mock_provider, profile='notexist')
def test_BaseAPI_init_external_credential_provider(): """Test initializing the credentials from an externally-supplied provider.""" creds = Credentials({'url': 'https://example.com', 'token': 'ABCDEFGHIJKLM', 'org_key': 'A1B2C3D4'}) mock_provider = MockCredentialProvider({'my_section': creds}) sut = BaseAPI(integration_name='test3', credential_provider=mock_provider, profile='my_section') assert sut.credentials is creds assert sut.credentials.url == 'https://example.com' assert sut.credentials.token == 'ABCDEFGHIJKLM' assert sut.credentials.org_key == 'A1B2C3D4' assert sut.credential_profile_name == 'my_section' assert sut.credential_provider is mock_provider assert sut.session.server == 'https://example.com' assert sut.session.token == 'ABCDEFGHIJKLM' assert sut.session.token_header['User-Agent'].startswith('test3')
def test_credential_partial_loads(): """Test that we can have credentials with some values from dict and some default.""" init_dict = {"url": "http://example.com", "ssl_verify": 0} creds = Credentials(init_dict) assert creds.url == "http://example.com" assert creds.token is None assert creds.org_key is None assert not creds.ssl_verify assert creds.ssl_verify_hostname assert creds.ssl_cert_file is None assert not creds.ssl_force_tls_1_2 assert creds.proxy is None assert not creds.ignore_system_proxy assert creds.integration is None
def test_session_adapter_creation_failure(mox, adapter_raises, msg_prefix): """Test the failure cases that come from the failure to create the session adapter.""" creds = Credentials({'url': 'https://example.com', 'token': 'ABCDEFGH'}) import cbc_sdk.connection mox.StubOutWithMock(cbc_sdk.connection, 'CBCSDKSessionAdapter', use_mock_anything=True) cbc_sdk.connection.CBCSDKSessionAdapter(force_tls_1_2=False, max_retries=IgnoreArg(), verify_hostname=True)\ .AndRaise(adapter_raises) mox.ReplayAll() with pytest.raises(ApiError) as excinfo: Connection(creds) assert excinfo.value.message.startswith(msg_prefix) mox.VerifyAll()
def test_credential_default_values(): """Tests the default credential values, and also the AttributeError mechanism.""" creds = Credentials() assert creds.url is None assert creds.token is None assert creds.org_key is None assert creds.ssl_verify assert creds.ssl_verify_hostname assert creds.ssl_cert_file is None assert not creds.ssl_force_tls_1_2 assert creds.proxy is None assert not creds.ignore_system_proxy assert creds.integration is None with pytest.raises(AttributeError): assert creds.notexist is None
def test_BaseAPI_init_with_only_profile_specified(mox): """Test the case where we only supply a profile string to the BaseAPI.""" mox.StubOutWithMock(default_provider_object, 'get_default_provider') creds = Credentials({'url': 'https://example.com', 'token': 'ABCDEFGHIJKLM', 'org_key': 'A1B2C3D4'}) mock_provider = MockCredentialProvider({'Valid': creds}) default_provider_object.get_default_provider(None).AndReturn(mock_provider) mox.ReplayAll() sut = BaseAPI(profile='Valid') assert sut.credentials is creds assert sut.credentials.url == 'https://example.com' assert sut.credentials.token == 'ABCDEFGHIJKLM' assert sut.credentials.org_key == 'A1B2C3D4' assert sut.credential_profile_name == 'Valid' assert sut.session.server == 'https://example.com' assert sut.session.token == 'ABCDEFGHIJKLM' mox.VerifyAll()
def test_http_request_error_code_cases(mox, response, exception_caught, prefix): """Test the cases in which http_request throws an exception as a result of receiving an error status.""" creds = Credentials({'url': 'https://example.com', 'token': 'ABCDEFGH'}) conn = Connection(creds) mox.StubOutWithMock(conn.session, 'request') conn.session.request('GET', 'https://example.com/path', headers=IgnoreArg(), verify=True, proxies=conn.proxies, timeout=conn._timeout).AndReturn(response) mox.ReplayAll() with pytest.raises(exception_caught) as excinfo: conn.http_request('get', '/path') assert excinfo.value.message.startswith(prefix) mox.VerifyAll()
def test_http_request_exception_cases(mox, exception_raised, exception_caught, prefix): """Test the cases in which the underlying session object throws an exception as a result of a request.""" creds = Credentials({'url': 'https://example.com', 'token': 'ABCDEFGH'}) conn = Connection(creds) mox.StubOutWithMock(conn.session, 'request') conn.session.request('GET', 'https://example.com/path', headers=IgnoreArg(), verify=True, proxies=conn.proxies, timeout=conn._timeout).AndRaise(exception_raised) mox.ReplayAll() with pytest.raises(exception_caught) as excinfo: conn.http_request('get', '/path') if prefix: assert excinfo.value.message.startswith(prefix) mox.VerifyAll()
def test_session_custom_session(): """Test to make sure custom session is passed""" import requests session = requests.Session() creds = Credentials({ 'url': 'https://example.com', 'token': 'ABCDEFGH', 'ssl_cert_file': 'blort', 'proxy': None }) session.proxies = { 'http': 'foobie.bletch.com', 'https': 'foobie.bletch.com' } conn = Connection(creds, proxy_session=session) assert conn.ssl_verify == 'blort' assert conn.proxies['http'] == 'foobie.bletch.com' assert conn.proxies['https'] == 'foobie.bletch.com'
def test_request_helper_methods(mox): """Test the four helper methods of http_request.""" creds = Credentials({'url': 'https://example.com', 'token': 'ABCDEFGH'}) conn = Connection(creds) mox.StubOutWithMock(conn.session, 'request') conn.session.request('GET', 'https://example.com/getpath', headers=IgnoreArg(), verify=True, proxies=conn.proxies, timeout=conn._timeout).AndReturn( StubResponse({'get': True})) conn.session.request('POST', 'https://example.com/postpath', headers=IgnoreArg(), verify=True, proxies=conn.proxies, timeout=conn._timeout).AndReturn( StubResponse({'post': True})) conn.session.request('PUT', 'https://example.com/putpath', headers=IgnoreArg(), verify=True, proxies=conn.proxies, timeout=conn._timeout).AndReturn( StubResponse({'put': True})) conn.session.request('DELETE', 'https://example.com/delpath', headers=IgnoreArg(), verify=True, proxies=conn.proxies, timeout=conn._timeout).AndReturn( StubResponse({'delete': True})) mox.ReplayAll() resp = conn.get('/getpath') assert resp.json()['get'] resp = conn.post('/postpath') assert resp.json()['post'] resp = conn.put('/putpath') assert resp.json()['put'] resp = conn.delete('/delpath') assert resp.json()['delete'] mox.VerifyAll()
def get_credentials(self, section=None): """ Return a Credentials object containing the configured credentials. Args: section (str): The credential section to retrieve. Returns: Credentials: The credentials retrieved from that source. Raises: CredentialError: If there is any error retrieving the credentials. """ if section is None: section = 'default' if self._cached_credentials is None: new_creds = {} cred_files = [ p for p in self._search_path if self._security_check(p) ] if not cred_files: raise CredentialError( f"Unable to locate credential file(s) from {self._search_path}" ) raw_cred_files = [ str(p) for p in cred_files ] # needed to support 3.6.0 correctly & for error message try: parser = configparser.ConfigParser() parser.read(raw_cred_files) for sect in parser.sections(): new_creds[sect] = Credentials( {name: value for (name, value) in parser.items(sect)}) except configparser.Error as e: raise CredentialError( f"Unable to read credential file(s) {raw_cred_files}" ) from e self._cached_credentials = new_creds if section in self._cached_credentials: return self._cached_credentials[section] raise CredentialError( f"Section {section} not found in credential file(s)")
def test_http_request_happy_path(mox): """Test the happy-path case of http_request.""" def validate_headers(hdrs): assert hdrs['X-Auth-Token'] == 'ABCDEFGH' assert hdrs['User-Agent'].startswith("CBC_SDK/") assert hdrs['X-Test'] == 'yes' return True creds = Credentials({'url': 'https://example.com', 'token': 'ABCDEFGH'}) conn = Connection(creds) mox.StubOutWithMock(conn.session, 'request') conn.session.request('GET', 'https://example.com/path', headers=Func(validate_headers), verify=True, proxies=conn.proxies, timeout=conn._timeout).AndReturn( StubResponse({'ok': True})) mox.ReplayAll() resp = conn.http_request('get', '/path', headers={'X-Test': 'yes'}) assert resp.json()['ok'] mox.VerifyAll()
def test_credential_dict_value_load(input_dict): """Test loading credentials from a dict, and also access through both attributes and get_value.""" creds = Credentials(input_dict) assert creds.url == "http://example.com" assert creds.token == "ABCDEFGH" assert creds.org_key == "A1B2C3D4" assert not creds.ssl_verify assert not creds.ssl_verify_hostname assert creds.ssl_cert_file == "foo.certs" assert creds.ssl_force_tls_1_2 assert creds.proxy == "proxy.example" assert creds.ignore_system_proxy assert creds.integration == 'Bronski' assert creds.get_value(CredentialValue.URL) == "http://example.com" assert creds.get_value(CredentialValue.TOKEN) == "ABCDEFGH" assert creds.get_value(CredentialValue.ORG_KEY) == "A1B2C3D4" assert not creds.get_value(CredentialValue.SSL_VERIFY) assert not creds.get_value(CredentialValue.SSL_VERIFY_HOSTNAME) assert creds.get_value(CredentialValue.SSL_CERT_FILE) == "foo.certs" assert creds.get_value(CredentialValue.SSL_FORCE_TLS_1_2) assert creds.get_value(CredentialValue.PROXY) == "proxy.example" assert creds.get_value(CredentialValue.IGNORE_SYSTEM_PROXY) assert creds.get_value(CredentialValue.INTEGRATION) == 'Bronski'
def _read_credentials(self, key): """ Read in a complete credentials set from a registry key. Args: key (PyHKEY): The registry key to be read in. Returns: Credentials: A new credentials object containing the credentials that were read in. Raises: CredentialError: If there was any issue reading the credentials in. """ input = {} for cv in list(CredentialValue): if cv.requires_boolean_value(): value = self._read_bool(key, cv.name.lower()) if value is not None: input[cv] = value else: value = self._read_str(key, cv.name.lower()) if value is not None: input[cv] = value return Credentials(input)
def test_credential_boolean_parsing_failure(): """Tests failure of parsing a Boolean credential value.""" init_dict = {"url": "http://example.com", "ssl_verify": "bogus"} with pytest.raises(CredentialError): Credentials(init_dict)
def test_initial_connection_error(cdata, msg_prefix): """Test the initial raising of a ConnectionError by the connection.""" creds = Credentials(cdata) with pytest.raises(ConnectionError) as excinfo: Connection(creds) assert excinfo.value.message.startswith(msg_prefix)