def request_resource_machine_access( self, machine_token: str, resource: str, machine_id: "Optional[str]" = None, ) -> "Dict[str, Any]": """Requests machine access context for a given resource @param machine_token: The authentication token needed to talk to this contract service endpoint. @param resource: Entitlement name. @param machine_id: Optional unique system machine id. When absent, contents of /etc/machine-id will be used. @return: Dict of the JSON response containing entitlement accessInfo. """ if not machine_id: machine_id = util.get_machine_id(self.cfg.data_dir) headers = self.headers() headers.update({"Authorization": "Bearer {}".format(machine_token)}) url = API_V1_TMPL_RESOURCE_MACHINE_ACCESS.format(resource=resource, machine=machine_id) resource_access, headers = self.request_url(url, headers=headers) if headers.get("expires"): resource_access["expires"] = headers["expires"] self.cfg.write_cache("machine-access-{}".format(resource), resource_access) return resource_access
def request_machine_token_refresh(self, machine_token, contract_id, machine_id=None): """Request machine token refresh from contract server. @param machine_token: The machine token needed to talk to this contract service endpoint. @param contract_id: Unique contract id provided by contract service. @param machine_id: Optional unique system machine id. When absent, contents of /etc/machine-id will be used. @return: Dict of the JSON response containing refreshed machine-token """ if not machine_id: machine_id = util.get_machine_id(self.cfg.data_dir) headers = self.headers() headers.update({"Authorization": "Bearer {}".format(machine_token)}) url = API_V1_TMPL_CONTEXT_MACHINE_TOKEN_REFRESH.format( contract=contract_id, machine=machine_id) response, headers = self.request_url(url, headers=headers) if headers.get("expires"): response["expires"] = headers["expires"] self.cfg.write_cache("machine-token", response) return response
def _get_platform_data(self, machine_id): """"Return a dict of platform-relateddata for contract requests""" if not machine_id: machine_id = util.get_machine_id(self.cfg.data_dir) platform = util.get_platform_info() arch = platform.pop("arch") return {"machineId": machine_id, "architecture": arch, "os": platform}
def request_resource_machine_access( self, machine_token: str, resource: str, machine_id: 'Optional[str]' = None) -> 'Dict[str, Any]': """Requests machine access context for a given resource @param machine_token: The authentication token needed to talk to this contract service endpoint. @param resource: Entitlement name. One of: livepatch, esm, fips or fips-updates. @param machine_id: Optional unique system machine id. When absent, contents of /etc/machine-id will be used. @return: Dict of the JSON response containing entitlement accessInfo. """ if not machine_id: machine_id = util.get_machine_id(self.cfg.data_dir) headers = self.headers() headers.update({'Authorization': 'Bearer %s' % machine_token}) url = API_V1_TMPL_RESOURCE_MACHINE_ACCESS.format(resource=resource, machine=machine_id) resource_access, headers = self.request_url(url, headers=headers) if headers.get('expires'): resource_access['expires'] = headers['expires'] self.cfg.write_cache('machine-access-%s' % resource, resource_access) return resource_access
def request_machine_contract_status( self, machine_token, contract_machine_id, machine_id=None, product_name=None): """Request contract and entitlement status details for a given machine. @param machine_token: The authentication token needed to talk to the contract service endpoints. @param contract_machine_id: The machine id obtained from the contract service. @param machine_id: Optional unique system machine id. When absent, contents of /etc/machine-id will be used. @param product_name: Optional specific product name to limit query to a specific entitlement: livepatch, esm, fips, or fips-updates. @return: Dict of JSON response from machine contracts endpoint """ if not machine_id: machine_id = util.get_machine_id(self.cfg.data_dir) data = {'machine': machine_id} if product_name: data['product'] = product_name url = API_PATH_TMPL_MACHINE_CONTRACT.format( machine=contract_machine_id) contracts, _headers = self.request_url(url, data=data) self.cfg.write_cache('machine-contracts', contracts) return contracts
def test_get_machine_id_from_etc_machine_id(self): """Presence of /etc/machine-id is returned if it exists.""" etc_machine_id = self.tmp_path('etc-machine-id', dir=self.tdir) self.assertEqual('/etc/machine-id', util.ETC_MACHINE_ID) util.write_file(etc_machine_id, 'etc-machine-id') with mock.patch('uaclient.util.ETC_MACHINE_ID', etc_machine_id): value = util.get_machine_id(data_dir=None) self.assertEqual('etc-machine-id', value)
def test_get_machine_id_from_etc_machine_id(self, tmpdir): """Presence of /etc/machine-id is returned if it exists.""" etc_machine_id = tmpdir.join('etc-machine-id') assert '/etc/machine-id' == util.ETC_MACHINE_ID etc_machine_id.write('etc-machine-id') with mock.patch('uaclient.util.ETC_MACHINE_ID', etc_machine_id.strpath): value = util.get_machine_id(data_dir=None) assert 'etc-machine-id' == value
def test_get_machine_id_from_etc_machine_id(self, tmpdir): """Presence of /etc/machine-id is returned if it exists.""" etc_machine_id = tmpdir.join("etc-machine-id") assert "/etc/machine-id" == util.ETC_MACHINE_ID etc_machine_id.write("etc-machine-id") with mock.patch("uaclient.util.ETC_MACHINE_ID", etc_machine_id.strpath): value = util.get_machine_id( data_dir=tmpdir.join("non-existent").strpath) assert "etc-machine-id" == value
def test_get_machine_id_from_var_lib_dbus_machine_id(self): """On trusty, machine id lives in of /var/lib/dbus/machine-id.""" etc_machine_id = self.tmp_path('etc-machine-id', dir=self.tdir) dbus_machine_id = self.tmp_path('dbus-machine-id', dir=self.tdir) self.assertEqual('/var/lib/dbus/machine-id', util.DBUS_MACHINE_ID) util.write_file(dbus_machine_id, 'dbus-machine-id') with mock.patch('uaclient.util.DBUS_MACHINE_ID', dbus_machine_id): with mock.patch('uaclient.util.ETC_MACHINE_ID', etc_machine_id): value = util.get_machine_id(data_dir=None) self.assertEqual('dbus-machine-id', value)
def test_get_machine_id_create_machine_id_in_data_dir(self, tmpdir): """When no machine-id is found, create one in data_dir using uuid4.""" data_machine_id = tmpdir.join('machine-id') with mock.patch('uaclient.util.os.path.exists') as m_exists: with mock.patch('uaclient.util.uuid.uuid4') as m_uuid4: m_exists.return_value = False m_uuid4.return_value = uuid.UUID( '0123456789abcdef0123456789abcdef') value = util.get_machine_id(data_dir=tmpdir.strpath) assert '01234567-89ab-cdef-0123-456789abcdef' == value assert '01234567-89ab-cdef-0123-456789abcdef' == data_machine_id.read()
def test_get_machine_id_from_var_lib_dbus_machine_id(self, tmpdir): """On trusty, machine id lives in of /var/lib/dbus/machine-id.""" etc_machine_id = tmpdir.join('etc-machine-id') dbus_machine_id = tmpdir.join('dbus-machine-id') assert '/var/lib/dbus/machine-id' == util.DBUS_MACHINE_ID dbus_machine_id.write('dbus-machine-id') with mock.patch('uaclient.util.DBUS_MACHINE_ID', dbus_machine_id.strpath): with mock.patch('uaclient.util.ETC_MACHINE_ID', etc_machine_id.strpath): value = util.get_machine_id(data_dir=None) assert 'dbus-machine-id' == value
def test_get_machine_id_create_machine_id_in_data_dir(self): """When no machine-id is found, create one in data_dir using uuid4.""" data_machine_id = self.tmp_path('machine-id', dir=self.tdir) with mock.patch('uaclient.util.os.path.exists') as m_exists: with mock.patch('uaclient.util.uuid.uuid4') as m_uuid4: m_exists.return_value = False m_uuid4.return_value = '1234...1234' value = util.get_machine_id(data_dir=self.tdir) self.assertEqual('1234...1234', value) self.assertEqual('1234...1234', util.load_file(data_machine_id))
def test_get_machine_id_uses_machine_id_from_data_dir(self, tmpdir): """When no machine-id is found, use machine-id from data_dir.""" data_machine_id = tmpdir.join('machine-id') data_machine_id.write('data-machine-id') def fake_exists(path): return bool(path == data_machine_id.strpath) with mock.patch('uaclient.util.os.path.exists') as m_exists: m_exists.side_effect = fake_exists value = util.get_machine_id(data_dir=tmpdir.strpath) assert 'data-machine-id' == value
def test_get_machine_id_uses_machine_id_from_data_dir(self): """When no machine-id is found, use machine-id from data_dir.""" data_machine_id = self.tmp_path('machine-id', dir=self.tdir) util.write_file(data_machine_id, 'data-machine-id') def fake_exists(path): return bool(path == data_machine_id) with mock.patch('uaclient.util.os.path.exists') as m_exists: m_exists.side_effect = fake_exists value = util.get_machine_id(data_dir=self.tdir) self.assertEqual('data-machine-id', value)
def test_fallback_used_if_all_other_files_are_empty( self, tmpdir, empty_value): data_machine_id = tmpdir.join("machine-id") with mock.patch("uaclient.util.os.path.exists") as m_exists: m_exists.return_value = True with mock.patch("uaclient.util.load_file", return_value=empty_value): with mock.patch("uaclient.util.uuid.uuid4") as m_uuid4: m_uuid4.return_value = uuid.UUID( "0123456789abcdef0123456789abcdef") value = util.get_machine_id(data_dir=tmpdir.strpath) assert "01234567-89ab-cdef-0123-456789abcdef" == value assert "01234567-89ab-cdef-0123-456789abcdef" == data_machine_id.read()
def test_get_machine_id_from_var_lib_dbus_machine_id(self, tmpdir): """On trusty, machine id lives in of /var/lib/dbus/machine-id.""" etc_machine_id = tmpdir.join("etc-machine-id") dbus_machine_id = tmpdir.join("dbus-machine-id") assert "/var/lib/dbus/machine-id" == util.DBUS_MACHINE_ID dbus_machine_id.write("dbus-machine-id") with mock.patch("uaclient.util.DBUS_MACHINE_ID", dbus_machine_id.strpath): with mock.patch("uaclient.util.ETC_MACHINE_ID", etc_machine_id.strpath): value = util.get_machine_id( data_dir=tmpdir.join("non-existent").strpath) assert "dbus-machine-id" == value
def request_contract_machine_attach(self, contract_token, machine_id=None): """Requests machine attach to the provided contact_id. @param contract_id: Unique contract id provided by contract service. @param contract_token: Token string providing authentication to ContractBearer service endpoint. @param machine_id: Optional unique system machine id. When absent, contents of /etc/machine-id will be used. @return: Dict of the JSON response containing the machine-token. """ if not machine_id: machine_id = util.get_machine_id(self.cfg.data_dir) os = util.get_platform_info() arch = os.pop("arch") headers = self.headers() headers.update({"Authorization": "Bearer {}".format(contract_token)}) data = {"machineId": machine_id, "architecture": arch, "os": os} machine_token, _headers = self.request_url( API_V1_CONTEXT_MACHINE_TOKEN, data=data, headers=headers) self.cfg.write_cache("machine-token", machine_token) return machine_token
def request_contract_machine_attach(self, contract_token, machine_id=None): """Requests machine attach to the provided contact_id. @param contract_id: Unique contract id provided by contract service. @param contract_token: Token string providing authentication to ContractBearer service endpoint. @param machine_id: Optional unique system machine id. When absent, contents of /etc/machine-id will be used. @return: Dict of the JSON response containing the machine-token. """ if not machine_id: machine_id = util.get_machine_id(self.cfg.data_dir) os = util.get_platform_info() arch = os.pop('arch') headers = self.headers() headers.update({'Authorization': 'Bearer %s' % contract_token}) data = {'machineId': machine_id, 'architecture': arch, 'os': os} machine_token, _headers = self.request_url( API_V1_CONTEXT_MACHINE_TOKEN, data=data, headers=headers) self.cfg.write_cache('machine-token', machine_token) redacted_content = util.redact_sensitive(machine_token) self.cfg.write_cache('machine-token', redacted_content, private=False) return machine_token