Ejemplo n.º 1
0
def create_authset(dauthd1,
                   dauthm,
                   id_data,
                   pubkey,
                   privkey,
                   utoken,
                   tenant_token=''):
    body, sighdr = deviceauth_v1.auth_req(id_data, pubkey, privkey,
                                          tenant_token)

    # submit auth req
    r = dauthd1.call('POST', deviceauth_v1.URL_AUTH_REQS, body, headers=sighdr)
    assert r.status_code == 401, r.text

    # dev must exist and have *this* aset
    api_dev = get_device_by_id_data(dauthm, id_data, utoken)
    assert api_dev is not None

    aset = [
        a for a in api_dev['auth_sets']
        if testutils.util.crypto.rsa_compare_keys(a['pubkey'], pubkey)
    ]
    assert len(aset) == 1, str(aset)

    aset = aset[0]

    assert aset['identity_data'] == id_data
    assert aset['status'] == 'pending'

    return Authset(aset['id'], api_dev['id'], id_data, pubkey, privkey,
                   'pending')
Ejemplo n.º 2
0
def initialize_os_setup(env):
    """ Seed the OS setup with all operational data - users and devices.
        Return {"os_devs": [...], "os_users": [...]}
    """
    uadmm = ApiClient(useradm.URL_MGMT, host=env.get_mender_gateway())
    dauthd = ApiClient(deviceauth.URL_DEVICES, host=env.get_mender_gateway())
    dauthm = ApiClient(deviceauth.URL_MGMT, host=env.get_mender_gateway())

    users = [
        create_user("*****@*****.**", "correcthorse", containers_namespace=env.name),
        create_user("*****@*****.**", "correcthorse", containers_namespace=env.name),
    ]

    r = uadmm.call("POST", useradm.URL_LOGIN, auth=(users[0].name, users[0].pwd))

    assert r.status_code == 200
    utoken = r.text

    # create and accept some devs; save tokens
    devs = []
    for _ in range(10):
        devs.append(make_accepted_device(dauthd, dauthm, utoken))

    # get tokens for all
    for d in devs:
        body, sighdr = deviceauth.auth_req(
            d.id_data, d.authsets[0].pubkey, d.authsets[0].privkey
        )

        r = dauthd.call("POST", deviceauth.URL_AUTH_REQS, body, headers=sighdr)

        assert r.status_code == 200
        d.token = r.text

    return {"os_devs": devs, "os_users": users}
Ejemplo n.º 3
0
def create_authset(dauthd1,
                   dauthm,
                   id_data,
                   pubkey,
                   privkey,
                   utoken,
                   tenant_token=""):
    body, sighdr = deviceauth.auth_req(id_data, pubkey, privkey, tenant_token)

    # submit auth req
    r = dauthd1.call("POST", deviceauth.URL_AUTH_REQS, body, headers=sighdr)
    assert r.status_code == 401, r.text

    # dev must exist and have *this* aset
    api_dev = get_device_by_id_data(dauthm, id_data, utoken)
    assert api_dev is not None

    aset = [
        a for a in api_dev["auth_sets"]
        if testutils.util.crypto.compare_keys(a["pubkey"], pubkey)
    ]
    assert len(aset) == 1, str(aset)

    aset = aset[0]

    assert aset["identity_data"] == id_data
    assert aset["status"] == "pending"

    return Authset(aset["id"], api_dev["id"], id_data, pubkey, privkey,
                   "pending")
Ejemplo n.º 4
0
    def test_ok(self, tenants_and_accepted_devs):
        """ Basic JWT inspection: are we getting the right claims?
        """
        for t in tenants_and_accepted_devs:
            dev = t.devices[0]
            aset = dev.authsets[0]

            body, sighdr = deviceauth_v1.auth_req(aset.id_data, aset.pubkey,
                                                  aset.privkey, t.tenant_token)

            r = dauthd.call("POST",
                            deviceauth_v1.URL_AUTH_REQS,
                            body,
                            headers=sighdr)

            assert r.status_code == 200
            token = r.text

            payload = token.split(".")[1]
            payload = base64.b64decode(payload + "==")
            payload = json.loads(payload.decode("utf-8"))

            # standard claims
            assert payload["sub"] == dev.id
            assert payload["iss"] == "Mender"
            assert payload["jti"] is not None
            assert payload["exp"] is not None

            # custom claims
            assert payload["mender.plan"] == t.plan
            assert payload["mender.tenant"] == t.id
            assert payload["mender.device"]
Ejemplo n.º 5
0
def make_accepted_device(
    dauthd1: ApiClient,
    dauthm: ApiClient,
    utoken: str,
    tenant_token: str = "",
    test_type: str = "regular",
) -> Device:
    """Create one device with "accepted" status."""
    test_types = ["regular", "azure"]
    if test_type not in test_types:
        raise RuntimeError("Given test type is not allowed")
    dev = make_pending_device(dauthd1, dauthm, utoken, tenant_token=tenant_token)
    aset_id = dev.authsets[0].id
    change_authset_status(dauthm, dev.id, aset_id, "accepted", utoken)
    aset = dev.authsets[0]
    aset.status = "accepted"

    # TODO: very bad workaround for Azure IoT Hub backend test; following part is responsible for creating
    # TODO: additonal, unnecessary auth set which causes Azure test to fail
    if test_type == "regular":
        # obtain auth token
        body, sighdr = deviceauth.auth_req(
            aset.id_data, aset.pubkey, aset.privkey, tenant_token
        )
        r = dauthd1.call("POST", deviceauth.URL_AUTH_REQS, body, headers=sighdr)
        assert r.status_code == 200
        dev.token = r.text

    dev.status = "accepted"

    return dev
Ejemplo n.º 6
0
    def test_accepted_dev_cant_authenticate(self, tenants_users_devices):
        dacd = ApiClient(deviceauth.URL_DEVICES)
        devauthm = ApiClient(deviceauth_v2.URL_MGMT)
        uc = ApiClient(useradm.URL_MGMT)
        tc = ApiClient(tenantadm.URL_INTERNAL)

        # accept a dev
        device = tenants_users_devices[0].devices[0]
        user = tenants_users_devices[0].users[0]

        r = uc.call('POST', useradm.URL_LOGIN, auth=(user.name, user.pwd))
        assert r.status_code == 200
        utoken = r.text

        aset = device.authsets[0]
        change_authset_status(devauthm, aset.did, aset.id, 'accepted', utoken)

        # suspend
        r = tc.call('PUT',
                    tenantadm.URL_INTERNAL_SUSPEND,
                    tenantadm.req_status('suspended'),
                    path_params={'tid': tenants_users_devices[0].id})
        assert r.status_code == 200

        time.sleep(10)

        # try requesting auth
        body, sighdr = deviceauth.auth_req(
            aset.id_data, aset.pubkey, aset.privkey,
            tenants_users_devices[0].tenant_token)

        r = dacd.call('POST', deviceauth.URL_AUTH_REQS, body, headers=sighdr)

        assert r.status_code == 401
        assert r.json()['error'] == 'Account suspended'
def make_accepted_device(utoken, devauthd, tenant_token=''):
    devauthm = ApiClient(deviceauth_v2.URL_MGMT)

    dev = make_pending_device(utoken, tenant_token=tenant_token)
    aset_id = dev.authsets[0].id
    change_authset_status(devauthm, dev.id, aset_id, 'accepted', utoken)

    aset = dev.authsets[0]
    aset.status = 'accepted'

    # obtain auth token
    body, sighdr = deviceauth_v1.auth_req(aset.id_data,
                                          aset.pubkey,
                                          aset.privkey,
                                          tenant_token)

    r = devauthd.call('POST',
                      deviceauth_v1.URL_AUTH_REQS,
                      body,
                      headers=sighdr)

    assert r.status_code == 200
    dev.token = r.text

    dev.status = 'accepted'

    return dev
Ejemplo n.º 8
0
    def do_test_delete_device_ok(self, devs_authsets, user, tenant_token=""):
        devapim = ApiClient(deviceauth_v2.URL_MGMT)
        devapid = ApiClient(deviceauth_v1.URL_DEVICES)
        userapi = ApiClient(useradm.URL_MGMT)
        depapi = ApiClient(deployments.URL_DEVICES)

        # log in user
        r = userapi.call("POST", useradm.URL_LOGIN, auth=(user.name, user.pwd))
        assert r.status_code == 200

        utoken = r.text

        # decommission a pending device
        dev_pending = filter_and_page_devs(devs_authsets, status="pending")[0]
        r = devapim.with_auth(utoken).call(
            "DELETE", deviceauth_v2.URL_DEVICE, path_params={"id": dev_pending.id}
        )
        assert r.status_code == 204

        # only verify the device is gone
        r = devapim.with_auth(utoken).call(
            "GET", deviceauth_v2.URL_DEVICE, path_params={"id": dev_pending.id}
        )
        assert r.status_code == 404

        # log in an accepted device
        dev_acc = filter_and_page_devs(devs_authsets, status="accepted")[0]

        body, sighdr = deviceauth_v1.auth_req(
            dev_acc.id_data,
            dev_acc.authsets[0].pubkey,
            dev_acc.authsets[0].privkey,
            tenant_token,
        )

        r = devapid.call("POST", deviceauth_v1.URL_AUTH_REQS, body, headers=sighdr)
        assert r.status_code == 200
        dtoken = r.text

        # decommission the accepted device
        r = devapim.with_auth(utoken).call(
            "DELETE", deviceauth_v2.URL_DEVICE, path_params={"id": dev_acc.id}
        )
        assert r.status_code == 204

        # verify the device lost access
        r = depapi.with_auth(dtoken).call(
            "GET",
            deployments.URL_NEXT,
            qs_params={"device_type": "foo", "artifact_name": "bar"},
        )
        assert r.status_code == 401

        # verify the device is gone
        r = devapim.with_auth(utoken).call(
            "GET", deviceauth_v2.URL_DEVICE, path_params={"id": dev_acc.id}
        )
        assert r.status_code == 404
    def test_devs_ok(self, migrated_enterprise_setup):
        mender_gateway = migrated_enterprise_setup.get_mender_gateway()
        uadmm = ApiClient(
            "https://{}/api/management/v1/useradm".format(mender_gateway))
        dauthd = ApiClient(
            "https://{}/api/devices/v1/authentication".format(mender_gateway))
        dauthm = ApiClient(
            "https://{}/api/management/v2/devauth".format(mender_gateway))
        depld = ApiClient(
            "https://{}/api/devices/v1/deployments".format(mender_gateway))

        # current dev tokens don't work right off the bat
        # the deviceauth db is empty
        for d in migrated_enterprise_setup.init_data["os_devs"]:
            resp = depld.with_auth(d.token).call(
                "GET",
                deployments.URL_NEXT,
                qs_params={
                    "artifact_name": "foo",
                    "device_type": "bar"
                },
            )

            assert resp.status_code == 401

        # but even despite the 'dummy' tenant token
        # os devices can get into the deviceauth db for acceptance
        ent_user = migrated_enterprise_setup.init_data["tenant"].users[0]
        r = uadmm.call("POST",
                       useradm.URL_LOGIN,
                       auth=(ent_user.name, ent_user.pwd))
        assert r.status_code == 200
        utoken = r.text

        for d in migrated_enterprise_setup.init_data["os_devs"]:
            body, sighdr = deviceauth_v1.auth_req(
                d.id_data,
                d.authsets[0].pubkey,
                d.authsets[0].privkey,
                tenant_token="dummy",
            )

            r = dauthd.call("POST",
                            deviceauth_v1.URL_AUTH_REQS,
                            body,
                            headers=sighdr)

            assert r.status_code == 401

        r = dauthm.with_auth(utoken).call("GET",
                                          deviceauth_v2.URL_DEVICES,
                                          path_params={"id": d.id})

        assert r.status_code == 200
        assert len(r.json()) == len(
            migrated_enterprise_setup.init_data["os_devs"])
Ejemplo n.º 10
0
    def do_test_ok(self, user, tenant_token=""):
        useradmm = ApiClient(useradm.URL_MGMT)
        devauthm = ApiClient(deviceauth_v2.URL_MGMT)
        devauthd = ApiClient(deviceauth_v1.URL_DEVICES)

        # log in user
        r = useradmm.call("POST", useradm.URL_LOGIN, auth=(user.name, user.pwd))
        assert r.status_code == 200

        utoken = r.text

        # preauth device
        priv, pub = testutils.util.crypto.rsa_get_keypair()
        id_data = {"mac": "pretenditsamac"}
        body = deviceauth_v2.preauth_req(id_data, pub)
        r = devauthm.with_auth(utoken).call("POST", deviceauth_v2.URL_DEVICES, body)
        assert r.status_code == 201

        # device appears in device list
        r = devauthm.with_auth(utoken).call("GET", deviceauth_v2.URL_DEVICES)
        assert r.status_code == 200
        api_devs = r.json()

        assert len(api_devs) == 1
        api_dev = api_devs[0]

        assert api_dev["status"] == "preauthorized"
        assert api_dev["identity_data"] == id_data
        assert len(api_dev["auth_sets"]) == 1
        aset = api_dev["auth_sets"][0]

        assert aset["identity_data"] == id_data
        assert testutils.util.crypto.rsa_compare_keys(aset["pubkey"], pub)
        assert aset["status"] == "preauthorized"

        # actual device can obtain auth token
        body, sighdr = deviceauth_v1.auth_req(id_data, pub, priv, tenant_token)

        r = devauthd.call("POST", deviceauth_v1.URL_AUTH_REQS, body, headers=sighdr)

        assert r.status_code == 200

        # device and authset changed status to 'accepted'
        r = devauthm.with_auth(utoken).call(
            "GET", deviceauth_v2.URL_DEVICES, path_params={"id": api_dev["id"]}
        )

        api_devs = r.json()
        assert len(api_devs) == 1

        api_dev = api_devs[0]
        assert api_dev["status"] == "accepted"
        assert len(api_dev["auth_sets"]) == 1

        aset = api_dev["auth_sets"][0]
        assert aset["status"] == "accepted"
    def test_authenticated_dev_is_rejected(self, tenants_users_devices):
        dacd = ApiClient(deviceauth.URL_DEVICES)
        devauthm = ApiClient(deviceauth_v2.URL_MGMT)
        uc = ApiClient(useradm.URL_MGMT)
        tc = ApiClient(tenantadm.URL_INTERNAL)
        dc = ApiClient(deployments.URL_DEVICES)

        # accept a dev
        user = tenants_users_devices[0].users[0]

        r = uc.call('POST',
                    useradm.URL_LOGIN,
                    auth=(user.name, user.pwd))
        assert r.status_code == 200
        utoken = r.text

        aset = tenants_users_devices[0].devices[0].authsets[0]
        change_authset_status(devauthm, aset.did, aset.id, 'accepted', utoken)

        # request auth
        body, sighdr = deviceauth.auth_req(aset.id_data,
                                           aset.pubkey,
                                           aset.privkey,
                                           tenants_users_devices[0].tenant_token)

        r = dacd.call('POST',
                      deviceauth.URL_AUTH_REQS,
                      body,
                      headers=sighdr)
        assert r.status_code == 200
        dtoken = r.text

        # check device can access APIs
        r = dc.with_auth(dtoken).call('GET',
                                      deployments.URL_NEXT,
                                      qs_params={'device_type': 'foo',
                                                 'artifact_name': 'bar'})
        assert r.status_code == 204

        # suspend
        r = tc.call('PUT',
                tenantadm.URL_INTERNAL_SUSPEND,
                tenantadm.req_status('suspended'),
                path_params={'tid': tenants_users_devices[0].id})
        assert r.status_code == 200

        time.sleep(10)

        # check device is rejected
        r = dc.with_auth(dtoken).call('GET',
                                      deployments.URL_NEXT,
                                      qs_params={'device_type': 'foo',
                                                 'artifact_name': 'bar'})
        assert r.status_code == 401
Ejemplo n.º 12
0
def initialize_os_setup():
    """ Seed the OS setup with all operational data - users and devices.
        Return {"os_devs": [...], "os_users": [...]}
    """
    uadmm = ApiClient('https://{}/api/management/v1/useradm'.format(
        get_mender_gateway()))
    dauthd = ApiClient('https://{}/api/devices/v1/authentication'.format(
        get_mender_gateway()))
    dauthm = ApiClient('https://{}/api/management/v2/devauth'.format(
        get_mender_gateway()))

    users = [
        create_user("*****@*****.**",
                    "correcthorse",
                    docker_prefix=docker_compose_instance),
        create_user("*****@*****.**",
                    "correcthorse",
                    docker_prefix=docker_compose_instance)
    ]

    r = uadmm.call('POST',
                   useradm.URL_LOGIN,
                   auth=(users[0].name, users[0].pwd))

    assert r.status_code == 200
    utoken = r.text

    # create and accept some devs; save tokens
    devs = []
    for i in range(10):
        devs.append(make_accepted_device(dauthd, dauthm, utoken))

    # get tokens for all
    for d in devs:
        body, sighdr = deviceauth_v1.auth_req(d.id_data, d.authsets[0].pubkey,
                                              d.authsets[0].privkey)

        r = dauthd.call('POST',
                        deviceauth_v1.URL_AUTH_REQS,
                        body,
                        headers=sighdr)

        assert r.status_code == 200
        d.token = r.text

    return {"os_devs": devs, "os_users": users}
Ejemplo n.º 13
0
    def test_accepted_dev_cant_authenticate(self, tenants_users_devices):
        dacd = ApiClient(deviceauth.URL_DEVICES)
        devauthm = ApiClient(deviceauth.URL_MGMT)
        uc = ApiClient(useradm.URL_MGMT)
        tc = ApiClient(tenantadm.URL_INTERNAL,
                       host=tenantadm.HOST,
                       schema="http://")

        # accept a dev
        device = tenants_users_devices[0].devices[0]
        user = tenants_users_devices[0].users[0]

        r = uc.call("POST", useradm.URL_LOGIN, auth=(user.name, user.pwd))
        assert r.status_code == 200
        utoken = r.text

        aset = device.authsets[0]
        change_authset_status(devauthm, aset.did, aset.id, "accepted", utoken)

        # suspend
        r = tc.call(
            "PUT",
            tenantadm.URL_INTERNAL_SUSPEND,
            tenantadm.req_status("suspended"),
            path_params={"tid": tenants_users_devices[0].id},
        )
        assert r.status_code == 200

        time.sleep(10)

        # try requesting auth
        body, sighdr = deviceauth.auth_req(
            aset.id_data,
            aset.pubkey,
            aset.privkey,
            tenants_users_devices[0].tenant_token,
        )

        r = dacd.call("POST", deviceauth.URL_AUTH_REQS, body, headers=sighdr)

        assert r.status_code == 401
        assert r.json()["error"] == "Account suspended"
Ejemplo n.º 14
0
def make_accepted_device(dauthd1, dauthm, utoken, tenant_token=""):
    dev = make_pending_device(dauthd1, dauthm, utoken, tenant_token=tenant_token)
    aset_id = dev.authsets[0].id
    change_authset_status(dauthm, dev.id, aset_id, "accepted", utoken)

    aset = dev.authsets[0]
    aset.status = "accepted"

    # obtain auth token
    body, sighdr = deviceauth_v1.auth_req(
        aset.id_data, aset.pubkey, aset.privkey, tenant_token
    )

    r = dauthd1.call("POST", deviceauth_v1.URL_AUTH_REQS, body, headers=sighdr)

    assert r.status_code == 200
    dev.token = r.text

    dev.status = "accepted"

    return dev
Ejemplo n.º 15
0
    def do_test_ok(self, user, device, tenant_token=None):
        devauthd = ApiClient(deviceauth.URL_DEVICES)
        devauthm = ApiClient(deviceauth_v2.URL_MGMT)
        useradmm = ApiClient(useradm.URL_MGMT)
        deploymentsd = ApiClient(deployments.URL_DEVICES)
        inventoryd = ApiClient(inventory.URL_DEV)
        inventorym = ApiClient(inventory.URL_MGMT)

        r = useradmm.call("POST",
                          useradm.URL_LOGIN,
                          auth=(user.name, user.pwd))
        assert r.status_code == 200
        utoken = r.text

        aset = device.authsets[0]
        change_authset_status(devauthm, aset.did, aset.id, "accepted", utoken)

        # request auth
        body, sighdr = deviceauth.auth_req(aset.id_data, aset.pubkey,
                                           aset.privkey, tenant_token)

        r = devauthd.call("POST",
                          deviceauth.URL_AUTH_REQS,
                          body,
                          headers=sighdr)
        assert r.status_code == 200
        dtoken = r.text

        # wait for the device provisioning workflow to do its job
        timeout = time.time() + 60
        while time.time() < timeout:
            r = inventorym.with_auth(utoken).call("GET",
                                                  inventory.URL_DEVICE,
                                                  path_params={"id": aset.did})
            if r.status_code == 200:
                break
            else:
                logger.debug(
                    "waiting for the device to be added to inventory...")
                time.sleep(1)
        else:
            assert False, "device not added to the inventory"

        # check if the device can access API by patching device inventory
        payload = [{"name": "mac", "value": "foo"}]
        r = inventoryd.with_auth(dtoken).call("PATCH",
                                              inventory.URL_DEVICE_ATTRIBUTES,
                                              payload)
        assert r.status_code == 200

        # decommission
        r = devauthm.with_auth(utoken).call(
            "DELETE", deviceauth_v2.URL_DEVICE.format(id=aset.did))

        # check device is rejected
        r = deploymentsd.with_auth(dtoken).call(
            "GET",
            deployments.URL_NEXT,
            qs_params={
                "device_type": "foo",
                "artifact_name": "bar"
            },
        )
        assert r.status_code == 401

        # check device gone from inventory
        # this may take some time because it's done as an async job (workflow)
        timeout = time.time() + (60 * 3)
        while time.time() < timeout:
            r = inventorym.with_auth(utoken).call("GET",
                                                  inventory.URL_DEVICE,
                                                  path_params={"id": aset.did})
            if r.status_code == 404:
                break
            else:
                logger.debug(
                    "waiting for the device to be removed from inventory...")
                time.sleep(1)
        else:
            assert False, "device not removed from the inventory"

        # check device gone from deviceauth
        timeout = time.time() + 60
        while time.time() < timeout:
            r = devauthm.with_auth(utoken).call(
                "GET", deviceauth_v2.URL_DEVICE.format(id=aset.did))
            if r.status_code == 404:
                break
            else:
                logger.debug(
                    "waiting for the device to be removed from deviceauth...")
                time.sleep(1)
        else:
            assert False, "device not removed from the deviceauth"
Ejemplo n.º 16
0
    def do_test_put_status_reject(self, devs_authsets, user, tenant_token=""):
        devauthm = ApiClient(deviceauth_v2.URL_MGMT)
        devauthd = ApiClient(deviceauth_v1.URL_DEVICES)
        useradmm = ApiClient(useradm.URL_MGMT)
        deploymentsd = ApiClient(deployments.URL_DEVICES)

        # log in user
        r = useradmm.call("POST", useradm.URL_LOGIN, auth=(user.name, user.pwd))
        assert r.status_code == 200
        utoken = r.text

        devs = []
        for status in ["pending", "accepted", "preauthorized"]:
            found = filter_and_page_devs(devs_authsets, status=status)
            devs.extend(found)

        for dev in devs:
            aset = None
            dtoken = None

            # for accepted or preauthd devs, reject the accepted/preauthd set
            # otherwise just select something
            if dev.status in ["accepted", "preauthorized"]:
                aset = [a for a in dev.authsets if a.status == dev.status]
                assert len(aset) == 1
                aset = aset[0]
            else:
                aset = dev.authsets[0]

            # for accepted devs, also have an active device and check it loses api access
            if dev.status == "accepted":
                body, sighdr = deviceauth_v1.auth_req(
                    aset.id_data, aset.pubkey, aset.privkey, tenant_token
                )

                r = devauthd.call(
                    "POST", deviceauth_v1.URL_AUTH_REQS, body, headers=sighdr
                )

                assert r.status_code == 200
                dtoken = r.text

            # reject the authset
            change_authset_status(devauthm, dev.id, aset.id, "rejected", utoken)

            # the given authset always changes to 'rejected'
            aset.status = "rejected"

            # if all other asets are also rejected, the device becomes too
            # otherwise it's 'pending'
            rej_asets = [
                a for a in dev.authsets if a.id != aset.id and a.status == "rejected"
            ]

            if len(rej_asets) == len(dev.authsets) - 1:
                dev.status = "rejected"
            else:
                dev.status = "pending"

            # check if the api device is consistent
            self.verify_dev_after_status_update(dev, utoken)

            # if we rejected an accepted, active device, check that it lost access
            if dtoken is not None:
                r = deploymentsd.with_auth(dtoken).call(
                    "GET",
                    deployments.URL_NEXT,
                    qs_params={"device_type": "foo", "artifact_name": "bar"},
                )
                assert r.status_code == 401
Ejemplo n.º 17
0
    def do_test_put_status_accept(self, devs_authsets, user, tenant_token=""):
        devauthm = ApiClient(deviceauth_v2.URL_MGMT)
        devauthd = ApiClient(deviceauth_v1.URL_DEVICES)
        useradmm = ApiClient(useradm.URL_MGMT)
        deploymentsd = ApiClient(deployments.URL_DEVICES)

        # log in user
        r = useradmm.call("POST", useradm.URL_LOGIN, auth=(user.name, user.pwd))
        assert r.status_code == 200
        utoken = r.text

        # select interesting devices - pending, rejected, or accepted/preauthd with extra authsets
        devs = []
        for status in ["pending", "rejected", "accepted", "preauthorized"]:
            found = filter_and_page_devs(devs_authsets, status=status)
            if status == "accepted" or status == "preauthorized":
                found = [d for d in found if len(d.authsets) > 1]

            devs.extend(found)

        # test acceptance for various kinds of devs
        for dev in devs:
            # for accepted devs - first actually get a device token
            dtoken = None
            if dev.status == "accepted":
                accepted = [a for a in dev.authsets if a.status == "accepted"][0]
                body, sighdr = deviceauth_v1.auth_req(
                    accepted.id_data, accepted.pubkey, accepted.privkey, tenant_token
                )

                r = devauthd.call(
                    "POST", deviceauth_v1.URL_AUTH_REQS, body, headers=sighdr
                )

                assert r.status_code == 200
                dtoken = r.text

            # find some pending or rejected authset
            aset = [
                a
                for a in dev.authsets
                if a.status == "pending" or a.status == "rejected"
            ][0]

            # accept the authset
            change_authset_status(devauthm, dev.id, aset.id, "accepted", utoken)

            # in case of originally preauthd/accepted devs: the original authset must be rejected now
            if dev.status in ["accepted", "preauthorized"]:
                aset_to_reject = [a for a in dev.authsets if a.status == dev.status]
                assert len(aset_to_reject) == 1
                aset_to_reject[0].status = "rejected"

            # in all cases, device is now 'accepted', along with the just accepted authset
            dev.status = "accepted"
            aset.status = "accepted"

            # verify device is correct in the api
            self.verify_dev_after_status_update(dev, utoken)

            # if the device used to be accepted - check it lost access
            if dtoken is not None:
                r = deploymentsd.with_auth(dtoken).call(
                    "GET",
                    deployments.URL_NEXT,
                    qs_params={"device_type": "foo", "artifact_name": "bar"},
                )
                assert r.status_code == 401

            # device should also be provisioned in inventory
            time.sleep(1)
            self.verify_dev_provisioned(dev, utoken)
Ejemplo n.º 18
0
    def test_limits_max_devices(self, tenants_devs_authsets):
        devauthi = ApiClient(deviceauth_v1.URL_INTERNAL)
        devauthm = ApiClient(deviceauth_v2.URL_MGMT)
        devauthd = ApiClient(deviceauth_v1.URL_DEVICES)
        useradmm = ApiClient(useradm.URL_MGMT)

        for t in tenants_devs_authsets:
            # get num currently accepted devices
            num_acc = len(filter_and_page_devs(t.devices, status="accepted"))

            # set limit to that
            r = devauthi.call(
                "PUT",
                deviceauth_v1.URL_LIMITS_MAX_DEVICES,
                {"limit": num_acc},
                path_params={"tid": t.id},
            )
            assert r.status_code == 204

            # get limit via internal api
            r = devauthi.call(
                "GET", deviceauth_v1.URL_LIMITS_MAX_DEVICES, path_params={"tid": t.id}
            )
            assert r.status_code == 200

            assert r.json()["limit"] == num_acc

            # get limit via mgmt api
            r = useradmm.call(
                "POST", useradm.URL_LOGIN, auth=(t.users[0].name, t.users[0].pwd)
            )
            assert r.status_code == 200

            utoken = r.text

            r = devauthm.with_auth(utoken).call(
                "GET", deviceauth_v2.URL_LIMITS_MAX_DEVICES
            )
            assert r.status_code == 200

            assert r.json()["limit"] == num_acc

            # try accept a device manually
            pending = filter_and_page_devs(t.devices, status="pending")[0]

            r = devauthm.with_auth(utoken).call(
                "PUT",
                deviceauth_v2.URL_AUTHSET_STATUS,
                deviceauth_v2.req_status("accepted"),
                path_params={"did": pending.id, "aid": pending.authsets[0].id},
            )
            assert r.status_code == 422

            # try exceed the limit via preauth'd device
            preauthd = filter_and_page_devs(t.devices, status="preauthorized")[0]

            body, sighdr = deviceauth_v1.auth_req(
                preauthd.id_data,
                preauthd.authsets[0].pubkey,
                preauthd.authsets[0].privkey,
                t.tenant_token,
            )

            r = devauthd.call("POST", deviceauth_v1.URL_AUTH_REQS, body, headers=sighdr)
            assert r.status_code == 401
Ejemplo n.º 19
0
    def test_authenticated_dev_is_rejected(self, tenants_users_devices):
        dacd = ApiClient(deviceauth.URL_DEVICES)
        devauthm = ApiClient(deviceauth.URL_MGMT)
        uc = ApiClient(useradm.URL_MGMT)
        tc = ApiClient(tenantadm.URL_INTERNAL,
                       host=tenantadm.HOST,
                       schema="http://")
        dc = ApiClient(deployments.URL_DEVICES)

        # accept a dev
        user = tenants_users_devices[0].users[0]

        r = uc.call("POST", useradm.URL_LOGIN, auth=(user.name, user.pwd))
        assert r.status_code == 200
        utoken = r.text

        aset = tenants_users_devices[0].devices[0].authsets[0]
        change_authset_status(devauthm, aset.did, aset.id, "accepted", utoken)

        # request auth
        body, sighdr = deviceauth.auth_req(
            aset.id_data,
            aset.pubkey,
            aset.privkey,
            tenants_users_devices[0].tenant_token,
        )

        r = dacd.call("POST", deviceauth.URL_AUTH_REQS, body, headers=sighdr)
        assert r.status_code == 200
        dtoken = r.text

        # check device can access APIs
        r = dc.with_auth(dtoken).call(
            "GET",
            deployments.URL_NEXT,
            qs_params={
                "device_type": "foo",
                "artifact_name": "bar"
            },
        )
        assert r.status_code == 204

        # suspend
        r = tc.call(
            "PUT",
            tenantadm.URL_INTERNAL_SUSPEND,
            tenantadm.req_status("suspended"),
            path_params={"tid": tenants_users_devices[0].id},
        )
        assert r.status_code == 200

        time.sleep(10)

        # check device is rejected
        r = dc.with_auth(dtoken).call(
            "GET",
            deployments.URL_NEXT,
            qs_params={
                "device_type": "foo",
                "artifact_name": "bar"
            },
        )
        assert r.status_code == 401
Ejemplo n.º 20
0
    def do_test_delete_status(self, devs_authsets, user, tenant_token=""):
        devauthm = ApiClient(deviceauth_v2.URL_MGMT)
        devauthd = ApiClient(deviceauth_v1.URL_DEVICES)
        useradmm = ApiClient(useradm.URL_MGMT)
        deploymentsd = ApiClient(deployments.URL_DEVICES)

        # log in user
        r = useradmm.call("POST", useradm.URL_LOGIN, auth=(user.name, user.pwd))
        assert r.status_code == 200
        utoken = r.text

        for dev in devs_authsets:
            aset = None
            dtoken = None

            # for accepted or preauthd devs, reject the accepted/preauthd set
            # otherwise just select something
            if dev.status in ["accepted", "preauthorized"]:
                aset = [a for a in dev.authsets if a.status == dev.status]
                assert len(aset) == 1
                aset = aset[0]
            else:
                aset = dev.authsets[0]

            # for accepted devs, also have an active device and check it loses api access
            if dev.status == "accepted":
                body, sighdr = deviceauth_v1.auth_req(
                    aset.id_data, aset.pubkey, aset.privkey, tenant_token
                )

                r = devauthd.call(
                    "POST", deviceauth_v1.URL_AUTH_REQS, body, headers=sighdr
                )

                assert r.status_code == 200
                dtoken = r.text

            # delete authset
            r = devauthm.with_auth(utoken).call(
                "DELETE",
                deviceauth_v2.URL_AUTHSET,
                path_params={"did": dev.id, "aid": aset.id},
            )
            assert r.status_code == 204

            # authset should be gone
            dev.authsets.remove(aset)

            # removing preauth authset - the device should be completely gone
            if dev.status == "preauthorized":
                r = devauthm.with_auth(utoken).call(
                    "GET", deviceauth_v2.URL_DEVICE, path_params={"id": dev.id}
                )
                assert r.status_code == 404
                return
            else:
                # in other cases the device remains
                dev.status = self.compute_dev_status(dev.authsets)

            # check api dev is consistent
            self.verify_dev_after_status_update(dev, utoken)

            # verify the device lost access, if we had one
            if dtoken is not None:
                r = deploymentsd.with_auth(dtoken).call(
                    "GET",
                    deployments.URL_NEXT,
                    qs_params={"device_type": "foo", "artifact_name": "bar"},
                )
                assert r.status_code == 401