def get_device(management_api, identity, token): if token: dev = management_api.find_device_by_identity( identity, Authorization='Bearer ' + token) else: # use default auth dev = management_api.find_device_by_identity(identity) return dev
def _test_delete_authset_OK(self, management_api, devices, **kwargs): d, da = devices[0] dev = management_api.find_device_by_identity(d.identity, **kwargs) assert dev devid = dev.id print('found matching device with ID:', dev.id) aid = dev.auth_sets[0].id rsp = management_api.delete_authset(devid, aid, **kwargs) assert rsp.status_code == 204 found = management_api.find_device_by_identity(d.identity, **kwargs) assert not found
def test_device_count_simple(self, devices, management_api): """We have 15 devices, each with a single auth set, verify that accepting/rejecting affects the count""" count = management_api.count_devices() assert count == 15 pending_count = management_api.count_devices(status='pending') assert pending_count == 15 # accept device[0] and reject device[1] for idx, (d, da) in enumerate(devices[0:2]): dev = management_api.find_device_by_identity(d.identity) assert dev devid = dev.id print('found matching device with ID:', dev.id) aid = dev.auth_sets[0].id try: with orchestrator.run_fake_for_device_id(devid) as server: if idx == 0: management_api.accept_device(devid, aid) elif idx == 1: management_api.reject_device(devid, aid) except bravado.exception.HTTPError as e: assert e.response.status_code == 204 TestDevice.verify_device_count(management_api, 'pending', 13) TestDevice.verify_device_count(management_api, 'accepted', 1) TestDevice.verify_device_count(management_api, 'rejected', 1)
def test_device_limit_applied(self, management_api, internal_api, tenant_foobar_devices, tenant_foobar): """Verify that max accepted devices limit is indeed applied. Since device limits can only be set on per-tenant basis, use fixtures that setup tenant 'foobar' with devices and a token """ expected = 2 internal_api.put_max_devices_limit('foobar', expected) accepted = 0 try: with orchestrator.run_fake_for_device_id(orchestrator.ANY_DEVICE): for dev, dev_auth in tenant_foobar_devices: auth = 'Bearer ' + tenant_foobar fdev = management_api.find_device_by_identity( dev.identity, Authorization=auth) aid = fdev.auth_sets[0].id management_api.accept_device(fdev.id, aid, Authorization=auth) accepted += 1 except bravado.exception.HTTPError as e: assert e.response.status_code == 422 finally: if accepted > expected: pytest.fail( "expected only {} devices to be accepted".format(expected))
def _do_test_error_preauth_limit(self, management_api, device_api, tenant_token=""): auth = management_api.make_auth(tenant_token) devs = management_api.list_devices(**auth) assert len(devs) == 6 limit = 3 for i in range(limit): dev = devs[i] aid = dev.auth_sets[0].id with orchestrator.run_fake_for_device_id(dev.id): management_api.accept_device(dev.id, aid, **auth) try: d = Device(IDDATA) d.public_key = PUBKEY d.private_key = PRIVKEY da = DevAuthorizer(tenant_token) rsp = device_auth_req(device_api.auth_requests_url, da, d) except bravado.exception.HTTPError as e: assert e.response.status_code == 401 dev = management_api.find_device_by_identity(d.identity, **auth) assert dev.auth_sets[0].status == 'preauthorized'
def accepted_device(device_api, management_api, clean_migrated_db): """Fixture that sets up an accepted device. Yields a tuple: (device ID, instance of Device, instance of DevAuthorizer)""" d = Device() da = DevAuthorizer() url = device_api.auth_requests_url # poke devauth so that device appears rsp = device_auth_req(url, da, d) assert rsp.status_code == 401 # try to find our devices in all devices listing dev = management_api.find_device_by_identity(d.identity) print('found matching device with ID', dev.id) devid = dev.id # extract authentication data set ID aid = dev.auth_sets[0].id try: with orchestrator.run_fake_for_device_id(devid) as server: management_api.accept_device(devid, aid) except bravado.exception.HTTPError as e: assert e.response.status_code == 204 yield (devid, d, da)
def accept_device(device_api, management_api, tenant_token=None): d = Device() da = DevAuthorizer(tenant_token) url = device_api.auth_requests_url kwargs = {} if tenant_token is not None: kwargs["Authorization"] = "Bearer " + tenant_token try: with orchestrator.run_fake_for_device_id(1) as server: with mock_tenantadm_auth(): # poke devauth so that device appears rsp = device_auth_req(url, da, d) assert rsp.status_code == 401 # try to find our devices in all devices listing dev = management_api.find_device_by_identity(d.identity, **kwargs) assert dev is not None print("found matching device with ID", dev.id) devid = dev.id # extract authentication data set ID aid = dev.auth_sets[0].id with orchestrator.run_fake_for_device_id(devid) as server: management_api.accept_device(devid, aid, **kwargs) except bravado.exception.HTTPError as e: assert e.response.status_code == 204 return devid, d, da
def test_get_device_single(self, management_api, devices): dev, _ = devices[0] # try to find our devices in all devices listing ourdev = management_api.find_device_by_identity(dev.identity) authdev = management_api.get_device(id=ourdev.id) assert authdev == ourdev
def test_get_device(self, management_api, devices): dev, _ = devices[0] ourdev = management_api.find_device_by_identity(dev.identity) authset, _ = self.client.devices.get_devices_id( id=ourdev.auth_sets[0].id, _request_options={ "headers": self.uauth }).result() assert authset.id == ourdev.auth_sets[0].id
def test_delete_device(self, management_api, devices): # try delete an existing device, verify decommissioning workflow was started # setup single device and poke devauth dev, _ = devices[0] ourdev = management_api.find_device_by_identity(dev.identity) assert ourdev try: with orchestrator.run_fake_for_device_id(ourdev.id) as server: rsp = management_api.delete_device( ourdev.id, { 'X-MEN-RequestID': 'delete_device', 'Authorization': 'Bearer foobar', }) print('decommission request finished with status:', rsp.status_code) except bravado.exception.HTTPError as e: assert e.response.status_code == 204 found = management_api.find_device_by_identity(dev.identity) assert not found
def _test_delete_authset_error_authset_not_found(self, management_api, devices, **kwargs): d, da = devices[0] dev = management_api.find_device_by_identity(d.identity, **kwargs) assert dev devid = dev.id print('found matching device with ID:', dev.id) rsp = management_api.delete_authset(devid, "foobar") assert rsp.status_code == 404
def test_device_count_multiple_auth_sets(self, devices, management_api, device_api): """"Verify that auth sets are properly counted. Take a device, make sure it has 2 auth sets, switch each auth sets between accepted/rejected/pending states """ dev, dauth = devices[0] # pretend device rotates its keys dev.rotate_key() with deviceadm.run_fake_for_device(deviceadm.ANY_DEVICE) as server: device_auth_req(device_api.auth_requests_url, dauth, dev) # should have 2 auth sets now found_dev = management_api.find_device_by_identity(dev.identity) assert len(found_dev.auth_sets) == 2 first_aid, second_aid = found_dev.auth_sets[0].id, found_dev.auth_sets[ 1].id # device [0] has 2 auth sets, but still counts as 1 device TestDevice.verify_device_count(management_api, 'pending', 5) devid = found_dev.id with orchestrator.run_fake_for_device_id( orchestrator.ANY_DEVICE) as server: # accept first auth set management_api.accept_device(devid, first_aid) TestDevice.verify_device_count(management_api, 'pending', 4) TestDevice.verify_device_count(management_api, 'accepted', 1) TestDevice.verify_device_count(management_api, 'rejected', 0) # reject the other management_api.reject_device(devid, second_aid) TestDevice.verify_device_count(management_api, 'pending', 4) TestDevice.verify_device_count(management_api, 'accepted', 1) TestDevice.verify_device_count(management_api, 'rejected', 0) # reject both management_api.reject_device(devid, first_aid) TestDevice.verify_device_count(management_api, 'pending', 4) TestDevice.verify_device_count(management_api, 'accepted', 0) TestDevice.verify_device_count(management_api, 'rejected', 1) # switch the first back to pending, 2nd remains rejected management_api.put_device_status(devid, first_aid, 'pending') TestDevice.verify_device_count(management_api, 'pending', 5) TestDevice.verify_device_count(management_api, 'accepted', 0) TestDevice.verify_device_count(management_api, 'rejected', 0)
def test_delete_device(self, management_api, devices): # try delete an existing device, verify decommissioning workflow was started # setup single device and poke devauth dev, _ = devices[0] ourdev = management_api.find_device_by_identity(dev.identity) assert ourdev # handler for orchestrator's job endpoint def decommission_device_handler(request): dreq = json.loads(request.body.decode()) print('decommision request', dreq) # verify that devauth tries to decommision correct device assert dreq.get('device_id', None) == ourdev.id # test is enforcing particular request ID assert dreq.get('request_id', None) == 'delete_device' # test is enforcing particular request ID assert dreq.get('authorization', None) == 'Bearer foobar' return (200, {}, '') handlers = [ ('POST', '/api/workflow/decommission_device', decommission_device_handler), ] with mockserver.run_fake(get_fake_orchestrator_addr(), handlers=handlers) as server: rsp = management_api.delete_device( ourdev.id, { 'X-MEN-RequestID': 'delete_device', 'Authorization': 'Bearer foobar', }) print('decommission request finished with status:', rsp.status_code) assert rsp.status_code == 204 found = management_api.find_device_by_identity(dev.identity) assert not found
def test_delete_device(self, management_api, devices): dev, _ = devices[0] ourdev = management_api.find_device_by_identity(dev.identity) rsp = self.delete_device_mgmt(ourdev.auth_sets[0].id) assert rsp.status_code == 204 #try to get deleted auth set try: self.client.devices.get_devices_id(id=ourdev.auth_sets[0].id, _request_options={ "headers": self.uauth }).result() except bravado.exception.HTTPError as e: assert e.response.status_code == 404 else: pytest.fail("Error code 404 not returned")
def test_delete_tokens_by_non_existent_tenant_ok(self, accepted_tenants_devices, internal_api, management_api, device_api): try: td = accepted_tenants_devices tenant_foo_token = make_fake_tenant_token("foo") da_foo = DevAuthorizer(tenant_token=tenant_foo_token) d1_foo = td["foo"][0] with orchestrator.run_fake_for_device_id(1) as server: token1 = request_token(d1_foo, da_foo, device_api.auth_requests_url) assert len(token1) > 0 d2_foo = td["foo"][1] with orchestrator.run_fake_for_device_id(2) as server: token2 = request_token(d2_foo, da_foo, device_api.auth_requests_url) assert len(token2) > 0 tenant_bar_token = make_fake_tenant_token("bar") da_bar = DevAuthorizer(tenant_token=tenant_bar_token) d1_bar = td["bar"][0] with orchestrator.run_fake_for_device_id(1) as server: token3 = request_token(d1_bar, da_bar, device_api.auth_requests_url) assert len(token2) > 0 verify_url = internal_api.make_api_url("/tokens/verify") verify_token(token1, 200, verify_url) verify_token(token2, 200, verify_url) verify_token(token3, 200, verify_url) dev1 = management_api.find_device_by_identity( d1_foo.identity, Authorization="Bearer " + tenant_foo_token) payload = {"tenant_id": "baz"} rsp = requests.delete(internal_api.make_api_url("/tokens"), params=payload) assert rsp.status_code == 204 verify_token(token1, 200, verify_url) verify_token(token2, 200, verify_url) verify_token(token3, 200, verify_url) except bravado.exception.HTTPError as e: assert e.response.status_code == 204
def _test_delete_authset_OK(self, management_api, devices, **kwargs): d, da = devices[0] dev = management_api.find_device_by_identity(d.identity, **kwargs) assert dev print("found matching device with ID:", dev.id) aid = dev.auth_sets[0].id with orchestrator.run_fake_for_device_id(dev.id) as server: rsp = management_api.delete_authset(dev.id, aid, **kwargs) assert rsp.status_code == 204 found = management_api.get_device(id=dev.id, **kwargs) assert found assert len(found.auth_sets) == 0
def test_delete_device(self, management_api, tenant_foobar_devices, tenant_foobar): auth = {"Authorization": "Bearer " + tenant_foobar} dev, _ = tenant_foobar_devices[0] ourdev = management_api.find_device_by_identity( dev.identity, Authorization="Bearer " + tenant_foobar) rsp = self.delete_device_mgmt(ourdev.auth_sets[0].id, auth=auth) assert rsp.status_code == 204 #try to get deleted auth set try: self.client.devices.get_devices_id(id=ourdev.auth_sets[0].id, _request_options={ "headers": auth }).result() except bravado.exception.HTTPError as e: assert e.response.status_code == 404 else: pytest.fail("Error code 404 not returned")
def test_device_accept_reject_cycle(self, devices, device_api, management_api): d, da = devices[0] url = device_api.auth_requests_url dev = management_api.find_device_by_identity(d.identity) assert dev devid = dev.id print("found matching device with ID:", dev.id) aid = dev.auth_sets[0].id try: with orchestrator.run_fake_for_device_id(devid) as server: management_api.accept_device(devid, aid) except bravado.exception.HTTPError as e: assert e.response.status_code == 204 # device is accepted, we should get a token now try: with orchestrator.run_fake_for_device_id(devid) as server: rsp = device_auth_req(url, da, d) assert rsp.status_code == 200 da.parse_rsp_payload(d, rsp.text) assert len(d.token) > 0 # reject it now try: management_api.reject_device(devid, aid) except bravado.exception.HTTPError as e: assert e.response.status_code == 204 # device is rejected, should get unauthorized rsp = device_auth_req(url, da, d) assert rsp.status_code == 401 except bravado.exception.HTTPError as e: assert e.response.status_code == 204
def test_delete_tokens_by_non_existent_tenant_ok(self, accepted_tenants_devices, internal_api, management_api, device_api): td = accepted_tenants_devices tenant_foo_token = make_fake_tenant_token('foo') da_foo = DevAuthorizer(tenant_token=tenant_foo_token) d1_foo = td['foo'][0] token1 = request_token(d1_foo, da_foo, device_api.auth_requests_url) assert len(token1) > 0 d2_foo = td['foo'][1] token2 = request_token(d2_foo, da_foo, device_api.auth_requests_url) assert len(token2) > 0 tenant_bar_token = make_fake_tenant_token('bar') da_bar = DevAuthorizer(tenant_token=tenant_bar_token) d1_bar = td['bar'][0] token3 = request_token(d1_bar, da_bar, device_api.auth_requests_url) assert len(token2) > 0 verify_url = internal_api.make_api_url("/tokens/verify") verify_token(token1, 200, verify_url) verify_token(token2, 200, verify_url) verify_token(token3, 200, verify_url) dev1 = management_api.find_device_by_identity(d1_foo.identity, Authorization='Bearer ' + tenant_foo_token) payload = {'tenant_id': 'baz'} rsp = requests.delete(internal_api.make_api_url("/tokens"), params=payload) assert rsp.status_code == 204 verify_token(token1, 200, verify_url) verify_token(token2, 200, verify_url) verify_token(token3, 200, verify_url)
def _do_test_ok_preauth(self, management_api, device_api, tenant_token=""): d = Device(IDDATA) d.public_key = PUBKEY d.private_key = PRIVKEY da = DevAuthorizer(tenant_token=tenant_token) # get the authset id - need it for the url auth = management_api.make_auth(tenant_token) dbg = management_api.list_devices() print(dbg) dev = management_api.find_device_by_identity(d.identity, **auth) assert dev with devadm_fake_status_update(AID), \ orchestrator.run_fake_for_device_id(DEVID): rsp = device_auth_req(device_api.auth_requests_url, da, d) assert rsp.status_code == 200 dev = management_api.get_device(id=dev.id, **auth) assert dev.auth_sets[0].status == 'accepted'
def accepted_tenants_devices(device_api, management_api, clean_migrated_db, cli, request): """Fixture that sets up an accepted devices for tenants. The fixture can be parametrized with a tenants, number of devices and number of authentication sets. Yields a dict: [tenant ID: [device object, ...], ]""" requested = request.param tenants_devices = dict() url = device_api.auth_requests_url for (tenant, dev_count, auth_count) in requested: tenant_devices = [] cli.migrate(tenant=tenant) tenant_token = make_fake_tenant_token(tenant) for _ in range(int(dev_count)): d = Device() for i in range(int(auth_count)): d.rotate_key() da = DevAuthorizer(tenant_token=tenant_token) # poke devauth so that device appears handlers = [ ( "POST", "/api/internal/v1/tenantadm/tenants/verify", lambda _: ( 200, {}, { "id": "507f191e810c19729de860ea", "name": "Acme", }, ), ), ] try: with orchestrator.run_fake_for_device_id(1) as server: with mockserver.run_fake(get_fake_tenantadm_addr(), handlers=handlers) as fake: rsp = device_auth_req(url, da, d) assert rsp.status_code == 401 except bravado.exception.HTTPError as e: assert e.response.status_code == 204 # try to find our devices in all devices listing dev = management_api.find_device_by_identity( d.identity, Authorization="Bearer " + tenant_token) devid = dev.id for a in dev.auth_sets: if compare_keys(a.pubkey, d.public_key): aid = a.id break try: with orchestrator.run_fake_for_device_id(devid) as server: management_api.accept_device(devid, aid, Authorization="Bearer " + tenant_token) token = request_token(d, da, device_api.auth_requests_url) assert len(token) > 0 except bravado.exception.HTTPError as e: assert e.response.status_code == 204 assert dev tenant_devices.append(d) tenants_devices[tenant] = tenant_devices yield tenants_devices