示例#1
0
    def do_test_get_device(self, devs_authsets, user):
        da = ApiClient(deviceauth_v2.URL_MGMT)
        ua = ApiClient(useradm.URL_MGMT)

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

        utoken = r.text

        # existing devices
        for dev in devs_authsets:
            r = da.with_auth(utoken).call(
                "GET", deviceauth_v2.URL_DEVICE, path_params={"id": dev.id}
            )
            assert r.status_code == 200
            api_dev = r.json()

            self._compare_dev(dev, api_dev)

        # non-existent devices
        for id in ["foo", "bar"]:
            r = da.with_auth(utoken).call(
                "GET", deviceauth_v2.URL_DEVICE, path_params={"id": id}
            )
            assert r.status_code == 404
    def test_authenticated_user_is_rejected(self, tenants):
        tc = ApiClient(tenantadm.URL_INTERNAL)
        uc = ApiClient(useradm.URL_MGMT)
        dc = ApiClient(deviceauth_v2.URL_MGMT)

        u = tenants[0].users[0]

        # log in
        r = uc.call('POST',
                     useradm.URL_LOGIN,
                     auth=(u.name, u.pwd))
        assert r.status_code == 200

        token = r.text

        # check can access an api
        r = dc.with_auth(token).call('GET', deviceauth_v2.URL_DEVICES)
        assert r.status_code == 200

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

        time.sleep(10)

        # check token is rejected
        r = dc.with_auth(token).call('GET', deviceauth_v2.URL_DEVICES)
        assert r.status_code == 401
def create_tenant_test_setup(user_name, tenant_name, nr_deployments=3, nr_devices=100):
    """
    Creates a tenant, and a user belonging to the tenant belonging to the user
    with 'nr_deployments', and 'nr_devices'
    """
    api_mgmt_deploy = ApiClient(deployments.URL_MGMT)
    tenant = create_tenant(tenant_name)
    user = create_tenant_user(user_name, tenant)
    r = ApiClient(useradm.URL_MGMT).call(
        'POST', useradm.URL_LOGIN, auth=(user.name, user.pwd))
    assert r.status_code == 200
    user.utoken = r.text
    tenant.users = [user]
    upload_image("/tests/test-artifact.mender", user.utoken)
    # Create three deployments for the user
    for i in range(nr_deployments):
        request_body = {
            "name": str(i) + "st-dummy-deployment",
            "artifact_name": "deployments-phase-testing",
            "devices": ["uuid not needed" + str(i) for i in range(nr_devices)],
        }
        resp = api_mgmt_deploy.with_auth(user.utoken).call(
            'POST',
            '/deployments',
            body=request_body,
        )
        assert resp.status_code == 201
    # Verify that the 'nr_deployments' expected deployments have been created
    resp = api_mgmt_deploy.with_auth(user.utoken).call('GET', '/deployments')
    assert resp.status_code == 200
    assert len(resp.json()) == nr_deployments
    return tenant
def try_update(device,
               expected_status_code=200,
               artifact_name="bugs-bunny"):
    """
    Try to make an update with a device
    :param devices:              list of devices
    :param expected_status_code: expected status code
    :param artifact_name:        artifact name used in the request
    """
    api_dev_deploy = ApiClient(deployments.URL_DEVICES)
    # Try to retrieve next update and assert expected status code
    resp = api_dev_deploy.with_auth(device.token).call(
        'GET',
        deployments.URL_NEXT,
        qs_params={"artifact_name": artifact_name,
                   "device_type"  : "qemux86-64"}
    )
    assert resp.status_code == expected_status_code
    if resp.status_code == 200:
        # Update device status upon successful request
        api_dev_deploy.with_auth(device.token).call(
            "PUT",
            deployments.URL_STATUS.format(id=resp.json()["id"]),
            body={"status": "success"}
        )
示例#5
0
    def _test_args_object(self, tenant_users, events):
        alogs = ApiClient(auditlogs.URL_MGMT)

        expected = events[0]

        # id filter
        resp = alogs.with_auth(tenant_users.users[0].token).call(
            "GET",
            auditlogs.URL_LOGS + "?object_id=" + expected["object"]["id"])

        resp = resp.json()
        assert len(resp) == 1

        for i in range(len(resp)):
            check_log(resp[0], expected)

        # type filter
        for obj_type in ["deployment"]:
            expected = [e for e in events if e["object"]["type"] == obj_type]
            resp = alogs.with_auth(tenant_users.users[0].token).call(
                "GET", auditlogs.URL_LOGS + "?object_type=" + obj_type)

            resp = resp.json()
            assert len(resp) == len(expected)

            for i in range(len(resp)):
                check_log(resp[i], expected[i])
示例#6
0
    def do_test_device_count(self, devs_authsets, user):
        ua = ApiClient(useradm.URL_MGMT)
        da = ApiClient(deviceauth_v2.URL_MGMT)

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

        utoken = r.text

        # test cases: successful counts
        for status in [None, "pending", "accepted", "rejected", "preauthorized"]:
            qs_params = {}
            if status is not None:
                qs_params = {"status": status}

            r = da.with_auth(utoken).call(
                "GET", deviceauth_v2.URL_DEVICES_COUNT, qs_params=qs_params
            )
            assert r.status_code == 200
            count = r.json()

            ref_devs = filter_and_page_devs(devs_authsets, status=status)

            ref_count = len(ref_devs)

            assert ref_count == count["count"]

        # fail: bad request
        r = da.with_auth(utoken).call(
            "GET", deviceauth_v2.URL_DEVICES_COUNT, qs_params={"status": "foo"}
        )
        assert r.status_code == 400
示例#7
0
    def do_test_get_authset_status(self, devs_authsets, user):
        devauthm = ApiClient(deviceauth_v2.URL_MGMT)
        useradmm = ApiClient(useradm.URL_MGMT)

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

        utoken = r.text

        # try valid authsets
        for d in devs_authsets:
            for a in d.authsets:
                r = devauthm.with_auth(utoken).call(
                    "GET",
                    deviceauth_v2.URL_AUTHSET_STATUS,
                    path_params={"did": d.id, "aid": a.id},
                )
                assert r.status_code == 200
                assert r.json()["status"] == a.status

        # invalid authset or device
        for did, aid in [(devs_authsets[0].id, "foo"), ("foo", "bar")]:
            r = devauthm.with_auth(utoken).call(
                "GET",
                deviceauth_v2.URL_AUTHSET_STATUS,
                path_params={"did": did, "aid": aid},
            )
            assert r.status_code == 404
示例#8
0
    def _test_args_actor(self, tenant_users, events):
        alogs = ApiClient(auditlogs.URL_MGMT)

        ids = [user.id for user in tenant_users.users]
        emails = [user.name for user in tenant_users.users]

        for id in ids:
            expected = [e for e in events if e["actor"]["id"] == id]

            resp = alogs.with_auth(tenant_users.users[0].token).call(
                "GET", auditlogs.URL_LOGS + "?actor_id=" + id)

            assert resp.status_code == 200
            resp = resp.json()

            assert len(resp) == len(expected)
            for i in range(len(resp)):
                check_log(resp[i], expected[i])

        for email in emails:
            expected = [e for e in events if e["actor"]["email"] == email]

            resp = alogs.with_auth(tenant_users.users[0].token).call(
                "GET", auditlogs.URL_LOGS + "?actor_email=" +
                urllib.parse.quote(email))

            assert resp.status_code == 200
            resp = resp.json()

            assert len(resp) == len(expected)
            for i in range(len(resp)):
                check_log(resp[i], expected[i])
    def test_authenticated_user_is_rejected(self, tenants):
        tc = ApiClient(tenantadm.URL_INTERNAL,
                       host=tenantadm.HOST,
                       schema="http://")
        uc = ApiClient(useradm.URL_MGMT)
        dc = ApiClient(deviceauth.URL_MGMT)

        u = tenants[0].users[0]

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

        token = r.text

        # check can access an api
        r = dc.with_auth(token).call("GET", deviceauth.URL_MGMT_DEVICES)
        assert r.status_code == 200

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

        time.sleep(10)

        # check token is rejected
        r = dc.with_auth(token).call("GET", deviceauth.URL_MGMT_DEVICES)
        assert r.status_code == 401
示例#10
0
    def do_test_fail_duplicate(self, user, devices):
        useradmm = ApiClient(useradm.URL_MGMT)
        devauthm = ApiClient(deviceauth_v2.URL_MGMT)

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

        utoken = r.text

        # preauth duplicate device
        priv, pub = testutils.util.crypto.rsa_get_keypair()
        id_data = devices[0].id_data
        body = deviceauth_v2.preauth_req(id_data, pub)
        r = devauthm.with_auth(utoken).call("POST", deviceauth_v2.URL_DEVICES, body)
        assert r.status_code == 409

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

        assert len(api_devs) == len(devices)

        # existing device has no new auth sets
        existing = [d for d in api_devs if d["identity_data"] == id_data]
        assert len(existing) == 1
        existing = existing[0]

        assert len(existing["auth_sets"]) == 1
        aset = existing["auth_sets"][0]
        assert testutils.util.crypto.rsa_compare_keys(aset["pubkey"], devices[0].pubkey)
        assert aset["status"] == "pending"
示例#11
0
def try_update(device,
               default_artifact_name="bugs-bunny",
               default_device_type="qemux86-64"):
    """
    Try to make an update with a device
    :param devices:               list of devices
    :param expected_status_code:  expected status code
    :param default_artifact_name: default artifact name of the
                                  artifact used in the request

    NOTE: You can override the device type and artifact name 
          by creating a device_type/artifact_name member of the
          Device object.
    """
    api_dev_deploy = ApiClient(deployments.URL_DEVICES)
    # Try to retrieve next update and assert expected status code
    resp = api_dev_deploy.with_auth(device.token).call(
        'GET',
        deployments.URL_NEXT,
        qs_params={"artifact_name": getattr(
            device, "artifact_name", default_artifact_name),
            "device_type": getattr(
            device, "device_type", default_device_type)}
    )
    if resp.status_code == 200:
        # Update device status upon successful request
        api_dev_deploy.with_auth(device.token).call(
            "PUT",
            deployments.URL_STATUS.format(id=resp.json()["id"]),
            body={"status": "success"}
        )
    return resp.status_code
示例#12
0
    def test_regular_deployment(self, clean_mongo):
        user, tenant, utoken, devs = setup_devices_and_management()

        api_mgmt_dep = ApiClient(deployments.URL_MGMT)

        # Make deployment request
        deployment_req = {
            "name": "phased-deployment",
            "artifact_name": "deployments-phase-testing",
            "devices": [dev.id for dev in devs],
        }
        api_mgmt_dep.with_auth(utoken).call("POST",
                                            deployments.URL_DEPLOYMENTS,
                                            deployment_req)

        for dev in devs:
            status_code = try_update(dev)
            assert status_code == 200
            dev.artifact_name = deployment_req["artifact_name"]

        for dev in devs:
            # Deployment already finished
            status_code = try_update(dev)
            assert status_code == 204

        deployment_req["name"] = "really-old-update"
        api_mgmt_dep.with_auth(utoken).call("POST",
                                            deployments.URL_DEPLOYMENTS,
                                            deployment_req)
        for dev in devs:
            # Already installed
            status_code = try_update(dev)
            assert status_code == 204
    def test_ok(self, user):
        useradmm = ApiClient(useradm.URL_MGMT)
        devauthd = ApiClient(deviceauth_v1.URL_DEVICES)
        invm = ApiClient(inventory.URL_MGMT)
        invd = ApiClient(inventory.URL_DEV)

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

        # prepare accepted devices
        devs = make_accepted_devices(utoken, devauthd, 3)

        # wait for devices to be provisioned
        time.sleep(3)

        for i, d in enumerate(devs):
            payload = [
                {
                    "name": "mac",
                    "value": "mac-new-" + str(d.id)
                },
                {
                    #empty value for existing
                    "name": "sn",
                    "value": "",
                },
                {
                    #empty value for new
                    "name": "new-empty",
                    "value": "",
                }
            ]
            r = invd.with_auth(d.token).call('PATCH',
                                             inventory.URL_DEVICE_ATTRIBUTES,
                                             payload)
            assert r.status_code == 200

        for d in devs:
            r = invm.with_auth(utoken).call('GET',
                                            inventory.URL_DEVICE,
                                            path_params={'id': d.id})
            assert r.status_code == 200

            api_dev = r.json()
            assert len(api_dev['attributes']) == 3

            for a in api_dev['attributes']:
                if a['name'] == 'mac':
                    assert a['value'] == 'mac-new-' + str(api_dev['id'])
                elif a['name'] == 'sn':
                    assert a['value'] == ''
                elif a['name'] == 'new-empty':
                    assert a['value'] == ''
                else:
                    assert False, 'unexpected attribute ' + a['name']
示例#14
0
    def test_deploy_to_group(self, clean_mongo, test_case):
        """
        Tests adding group restrinction to roles and checking that users
        are not allowed to deploy to devices outside the restricted
        groups.
        """
        dplmnt_MGMT = ApiClient(deployments.URL_MGMT)

        i = 0
        self.logger.info("RUN: %s", test_case["name"])
        tenant = create_org("org%d" % i,
                            "*****@*****.**" % i,
                            "password",
                            plan="enterprise")
        test_user = create_user(tid=tenant.id, **test_case["user"])
        tenant.users.append(test_user)
        login_tenant_users(tenant)

        # Initialize tenant's devices
        grouped_devices = setup_tenant_devices(tenant,
                                               test_case["device_groups"])

        # Add user to deployment group
        role = UserRole("RBAC_DEVGRP", test_case["permissions"])
        add_user_to_role(test_user, tenant, role)

        # Upload a bogus artifact
        artifact = Artifact("tester", ["qemux86-64"], payload="bogus")
        rsp = dplmnt_MGMT.with_auth(test_user.token).call(
            "POST",
            deployments.URL_DEPLOYMENTS_ARTIFACTS,
            files=((
                "artifact",
                (
                    "artifact.mender",
                    artifact.make(),
                    "application/octet-stream",
                ),
            ), ),
        )
        assert rsp.status_code == 201, rsp.text

        # Attempt to create deployment with test user
        devices = []
        for group in test_case["deploy_groups"]:
            for device in grouped_devices[group]:
                devices.append(device.id)

        rsp = dplmnt_MGMT.with_auth(test_user.token).call(
            "POST",
            deployments.URL_DEPLOYMENTS,
            body={
                "artifact_name": "tester",
                "name": "dplmnt",
                "devices": devices
            },
        )
        assert rsp.status_code == test_case["status_code"], rsp.text
        self.logger.info("PASS: %s" % test_case["name"])
示例#15
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"])
示例#17
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"
示例#18
0
    def test_deploy_to_devices(self, clean_mongo, test_case):
        """
        Tests adding group restrinction to roles and checking that users
        are not allowed to deploy to devices by providing list of device IDs.
        The only exception is single device deployment.
        """
        self.logger.info("RUN: %s", test_case["name"])

        uuidv4 = str(uuid.uuid4())
        tenant, username, password = (
            "test.mender.io-" + uuidv4,
            "some.user+" + uuidv4 + "@example.com",
            "secretsecret",
        )
        tenant = create_org(tenant, username, password, "enterprise")
        test_case["user"]["name"] = test_case["user"]["name"].replace("UUID", uuidv4)
        test_user = create_user(tid=tenant.id, **test_case["user"])
        tenant.users.append(test_user)
        login_tenant_users(tenant)

        # Initialize tenant's devices
        grouped_devices = setup_tenant_devices(tenant, test_case["device_groups"])

        # Add user to deployment group
        role = UserRole("RBAC_DEVGRP", test_case["permissions"])
        add_user_to_role(test_user, tenant, role)

        # Upload a bogus artifact
        artifact = Artifact("tester", ["qemux86-64"], payload="bogus")

        dplmnt_MGMT = ApiClient(deployments.URL_MGMT)
        rsp = dplmnt_MGMT.with_auth(test_user.token).call(
            "POST",
            deployments.URL_DEPLOYMENTS_ARTIFACTS,
            files=(
                (
                    "artifact",
                    ("artifact.mender", artifact.make(), "application/octet-stream"),
                ),
            ),
        )
        assert rsp.status_code == 201, rsp.text

        # Attempt to create deployment with test user
        devices = []
        for group in test_case["deploy_groups"]:
            for device in grouped_devices[group]:
                devices.append(device.id)

        rsp = dplmnt_MGMT.with_auth(test_user.token).call(
            "POST",
            deployments.URL_DEPLOYMENTS,
            body={"artifact_name": "tester", "name": "dplmnt", "devices": devices},
        )
        assert rsp.status_code == test_case["status_code"], rsp.text
        self.logger.info("PASS: %s" % test_case["name"])
示例#19
0
    def setup_upload_artifact_selection(self, plan, artifacts=()):
        tenant, username, password = self.get_tenant_username_and_password(
            plan=plan)
        auth_token = self.get_auth_token(username, password)

        api_client = ApiClient(deployments.URL_MGMT)
        api_client.headers = {}  # avoid default Content-Type: application/json
        api_client.with_auth(auth_token)

        # create and upload the mender artifact
        for artifact_kw in artifacts:
            artifact_kw.setdefault("artifact_name", "test")
            artifact_kw.setdefault("device_types", ["arm1"])
            with get_mender_artifact(**artifact_kw) as artifact:
                r = api_client.with_auth(auth_token).call(
                    "POST",
                    deployments.URL_DEPLOYMENTS_ARTIFACTS,
                    files=(
                        ("description", (None, "description")),
                        ("size", (None, str(os.path.getsize(artifact)))),
                        (
                            "artifact",
                            (
                                artifact,
                                open(artifact, "rb"),
                                "application/octet-stream",
                            ),
                        ),
                    ),
                )
            assert r.status_code == 201

        # create a new accepted device
        devauthd = ApiClient(deviceauth.URL_DEVICES)
        devauthm = ApiClient(deviceauth.URL_MGMT)
        dev = make_accepted_device(
            devauthd,
            devauthm,
            auth_token,
            tenant.tenant_token if tenant is not None else "",
        )
        assert dev is not None

        # create a deployment
        resp = api_client.with_auth(auth_token).call(
            "POST",
            deployments.URL_DEPLOYMENTS,
            body={
                "name": "deployment-1",
                "artifact_name": "test",
                "devices": [dev.id],
            },
        )
        assert resp.status_code == 201

        return dev
示例#20
0
    def test_set_and_deploy_configuration(self, clean_mongo, test_case):
        """
        Tests adding group restrinction to roles and checking that users
        are not allowed to set and deploy configuration to devices outside the restricted
        groups.
        """
        self.logger.info("RUN: %s", test_case["name"])

        uuidv4 = str(uuid.uuid4())
        tenant, username, password = (
            "test.mender.io-" + uuidv4,
            "some.user+" + uuidv4 + "@example.com",
            "secretsecret",
        )
        tenant = create_org(tenant, username, password, "enterprise")

        update_tenant(tenant.id, addons=["configure"])

        test_case["user"]["name"] = test_case["user"]["name"].replace(
            "UUID", uuidv4)
        test_user = create_user(tid=tenant.id, **test_case["user"])
        tenant.users.append(test_user)
        login_tenant_users(tenant)

        # Initialize tenant's devices
        grouped_devices = setup_tenant_devices(tenant,
                                               test_case["device_groups"])

        # Add user to deployment group
        role = UserRole("RBAC_DEVGRP", test_case["permissions"])
        add_user_to_role(test_user, tenant, role)

        deviceconf_MGMT = ApiClient(deviceconfig.URL_MGMT)

        device_id = grouped_devices[test_case["deploy_group"]][0].id

        # Attempt to set configuration
        rsp = deviceconf_MGMT.with_auth(test_user.token).call(
            "PUT",
            deviceconfig.URL_MGMT_DEVICE_CONFIGURATION.format(id=device_id),
            body={"foo": "bar"},
        )
        assert rsp.status_code == test_case[
            "set_configuration_status_code"], rsp.text

        # Attempt to deploy the configuration
        rsp = deviceconf_MGMT.with_auth(test_user.token).call(
            "POST",
            deviceconfig.URL_MGMT_DEVICE_CONFIGURATION_DEPLOY.format(
                id=device_id),
            body={"retries": 0},
        )
        assert (rsp.status_code ==
                test_case["deploy_configuration_status_code"]), rsp.text
        self.logger.info("PASS: %s" % test_case["name"])
    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
示例#22
0
    def do_test_put_status_failed(self, devs_authsets, user):
        useradmm = ApiClient(useradm.URL_MGMT)
        devauthm = ApiClient(deviceauth_v2.URL_MGMT)

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

        # not found: valid device, bogus authset
        r = devauthm.with_auth(utoken).call(
            "PUT",
            deviceauth_v2.URL_AUTHSET_STATUS,
            deviceauth_v2.req_status("accepted"),
            path_params={"did": devs_authsets[0].id, "aid": "foo"},
        )
        assert r.status_code == 404

        # not found: bogus device
        r = devauthm.with_auth(utoken).call(
            "PUT",
            deviceauth_v2.URL_AUTHSET_STATUS,
            deviceauth_v2.req_status("accepted"),
            path_params={"did": "foo", "aid": "bar"},
        )
        assert r.status_code == 404

        # bad request - invalid status
        r = devauthm.with_auth(utoken).call(
            "PUT",
            deviceauth_v2.URL_AUTHSET_STATUS,
            deviceauth_v2.req_status("invalid"),
            path_params={
                "did": devs_authsets[0].id,
                "aid": devs_authsets[0].authsets[0].id,
            },
        )
        assert r.status_code == 400

        # bad request - invalid payload
        r = devauthm.with_auth(utoken).call(
            "PUT",
            deviceauth_v2.URL_AUTHSET_STATUS,
            '{"foo": "bar"}',
            path_params={
                "did": devs_authsets[0].id,
                "aid": devs_authsets[0].authsets[0].id,
            },
        )
        assert r.status_code == 400
def setup_devices_and_management(nr_devices=100):
    """
    Sets up user and tenant and creates authorized devices.
    """
    tenant = create_tenant('acme')
    user = create_tenant_user('bugs-bunny', tenant)
    useradmm = ApiClient(useradm.URL_MGMT)
    devauthd = ApiClient(deviceauth_v1.URL_DEVICES)
    invm = ApiClient(inventory.URL_MGMT)
    api_mgmt_deploy = ApiClient(deployments.URL_MGMT)
    # log in user
    r = useradmm.call('POST', useradm.URL_LOGIN, auth=(user.name, user.pwd))
    assert r.status_code == 200
    utoken = r.text
    # Upload a dummy artifact to the server
    upload_image("/tests/test-artifact.mender", utoken)
    # prepare accepted devices
    devs = make_accepted_devices(utoken, devauthd, nr_devices,
                                 tenant.tenant_token)
    # wait for devices to be provisioned
    time.sleep(3)

    # Check that the number of devices were created
    r = invm.with_auth(utoken).call(
        'GET', inventory.URL_DEVICES, qs_params={
            'per_page': nr_devices
        })
    assert r.status_code == 200
    api_devs = r.json()
    assert len(api_devs) == nr_devices

    return user, tenant, utoken, devs
    def test_fail_no_attr_value(self, user):
        useradmm = ApiClient(useradm.URL_MGMT)
        devauthd = ApiClient(deviceauth_v1.URL_DEVICES)
        invm = ApiClient(inventory.URL_MGMT)
        invd = ApiClient(inventory.URL_DEV)

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

        # prepare accepted devices
        devs = make_accepted_devices(utoken, devauthd, 1)

        # wait for devices to be provisioned
        time.sleep(3)

        for i, d in enumerate(devs):
            payload = [{
                "name": "mac",
            }]
            r = invd.with_auth(d.token).call('PATCH',
                                             inventory.URL_DEVICE_ATTRIBUTES,
                                             payload)
            assert r.status_code == 400
示例#25
0
def make_device_with_inventory(attributes, utoken, tenant_token):
    devauthm = ApiClient(deviceauth.URL_MGMT)
    devauthd = ApiClient(deviceauth.URL_DEVICES)
    invm = ApiClient(inventory.URL_MGMT)

    d = make_accepted_device(devauthd, devauthm, utoken, tenant_token)
    """
    verify that the status of the device in inventory is "accepted"
    """
    accepted = False
    timeout = 10
    for i in range(timeout):
        r = invm.with_auth(utoken).call("GET",
                                        inventory.URL_DEVICE.format(id=d.id))
        if r.status_code == 200:
            dj = r.json()
            for attr in dj["attributes"]:
                if attr["name"] == "status" and attr["value"] == "accepted":
                    accepted = True
                    break
        if accepted:
            break
        time.sleep(1)
    if not accepted:
        raise ValueError(
            "status for device %s has not been propagated within %d seconds" %
            (d.id, timeout))

    submit_inventory(attributes, d.token)

    d.attributes = attributes

    return d
    def do_test_get_devices_ok(self, user, tenant_token=''):
        useradmm = ApiClient(useradm.URL_MGMT)
        devauthd = ApiClient(deviceauth_v1.URL_DEVICES)
        invm = ApiClient(inventory.URL_MGMT)
        invd = ApiClient(inventory.URL_DEV)

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

        # prepare accepted devices
        devs = make_accepted_devices(utoken, devauthd, 40, tenant_token)

        # wait for devices to be provisioned
        time.sleep(3)

        r = invm.with_auth(utoken).call('GET',
                                        inventory.URL_DEVICES,
                                        qs_params={'per_page': 100})
        assert r.status_code == 200
        api_devs = r.json()
        assert len(api_devs) == 40
示例#27
0
 def test_upload_artifact_selection_match_depends_multiple_artifacts(
         self, mongo, clean_mongo):
     dev = self.setup_upload_artifact_selection(
         plan="enterprise",
         artifacts=(
             {
                 "artifact_name": "test",
                 "device_types": ["arm1"],
                 "depends": ("rootfs_image_checksum:checksum", ),
                 "provides": ("rootfs_image_checksum:provided", ),
             },
             {
                 "artifact_name": "test",
                 "device_types": ["arm1"],
                 "depends": ("rootfs_image_checksum:another-checksum", ),
                 "provides": ("rootfs_image_checksum:provided", ),
             },
         ),
     )
     deploymentsd = ApiClient(deployments.URL_DEVICES)
     r = deploymentsd.with_auth(dev.token).call(
         "POST",
         deployments.URL_NEXT,
         body={
             "device_type": "arm1",
             "artifact_name": "old-artifact",
             "rootfs_image_checksum": "another-checksum",
         },
     )
     assert r.status_code == 200
示例#28
0
def create_org(name, username, password, plan="os"):
    cli = CliTenantadm()
    user_id = None
    tenant_id = cli.create_org(name, username, password, plan=plan)
    tenant_token = json.loads(cli.get_tenant(tenant_id))["tenant_token"]
    api = ApiClient(useradm.URL_MGMT)
    # Try log in every second for 3 minutes.
    # - There usually is a slight delay (in order of ms) for propagating
    #   the created user to the db.
    for i in range(3 * 60):
        rsp = api.call("POST", useradm.URL_LOGIN, auth=(username, password))
        if rsp.status_code == 200:
            break
        time.sleep(1)

    if rsp.status_code != 200:
        raise ValueError(
            "User could not log in within three minutes after organization has been created."
        )

    user_token = rsp.text
    rsp = api.with_auth(user_token).call("GET", useradm.URL_USERS)
    users = json.loads(rsp.text)
    for user in users:
        if user["email"] == username:
            user_id = user["id"]
            break
    if user_id == None:
        raise ValueError("Error retrieving user id.")

    tenant = Tenant(name, tenant_id, tenant_token)
    user = User(user_id, username, password)
    tenant.users.append(user)
    return tenant
示例#29
0
 def test_reporting_search(self, user_reporting, test_case):
     reporting_client = ApiClient(reporting.URL_MGMT)
     rsp = reporting_client.with_auth(user_reporting.api_token).call(
         "POST", reporting.URL_MGMT_DEVICES_SEARCH, test_case["request"]
     )
     assert rsp.status_code == test_case["status_code"], (
         "Unexpected status code (%d) from /devices/search response: %s"
         % (rsp.status_code, rsp.text)
     )
     if rsp.status_code == 200 and "response" in test_case:
         body = rsp.json()
         if body is None:
             body = []
         test_case_response = test_case["response"](user_reporting)
         self.logger.info("expected: %r", test_case_response)
         self.logger.info("received: %r", body)
         assert len(body) == len(test_case_response), (
             "Unexpected number of results: %s != %s"
             % (
                 [dev["id"] for dev in test_case_response],
                 [dev["id"] for dev in body],
             )
         )
         if len(test_case_response) > 0:
             if "sort" not in test_case["request"]:
                 body = sorted(body, key=lambda dev: dev["id"])
                 test_case_response = sorted(
                     test_case_response, key=lambda dev: dev["id"]
                 )
             for i, dev in enumerate(test_case_response):
                 assert dev["id"] == body[i]["id"], "Unexpected device in response"
                 assert_device_attributes(dev, body[i])
示例#30
0
def add_devices_to_user(user, dev_inventories):
    try:
        user.devices
    except AttributeError:
        user.devices = []

    useradmm = ApiClient(useradm.URL_MGMT)
    devauthd = ApiClient(deviceauth.URL_DEVICES)
    devauthm = ApiClient(deviceauth.URL_MGMT)
    invd = ApiClient(inventory.URL_DEV)

    utoken = useradmm.call("POST", useradm.URL_LOGIN, auth=(user.name, user.pwd)).text
    assert utoken != ""
    user.api_token = utoken

    for inv in dev_inventories:
        device = make_accepted_device(devauthd, devauthm, utoken)
        user.devices.append(device)

        attrs = dict_to_inventoryattrs(inv)
        rsp = invd.with_auth(device.token).call(
            "PATCH", inventory.URL_DEVICE_ATTRIBUTES, body=attrs
        )
        assert rsp.status_code == 200
        device.inventory = inv

    return user