def test_fail_no_upgrade(self, api_client_int, clean_db, mongo):
        # start with a valid deployment
        tenant_id = str(ObjectId())
        _, r = api_client_int.create_tenant(tenant_id)
        assert r.status_code == 201

        deployment_id = str(uuid4())
        dev = Device()
        configuration_deployment = {"name": "foo", "configuration": '{"foo":"bar"}'}

        make_deployment(
            api_client_int,
            tenant_id,
            deployment_id,
            dev.devid,
            configuration_deployment,
        )

        # try get upgrade
        # valid device id + type, but different tenant
        other_tenant_id = str(ObjectId())
        _, r = api_client_int.create_tenant(other_tenant_id)
        assert r.status_code == 201

        dc = SimpleDeviceClient()
        nodep = dc.get_next_deployment(
            dev.fake_token_mt(other_tenant_id),
            artifact_name="dontcare",
            device_type=dev.device_type,
        )
        assert nodep is None

        # correct tenant, incorrect device id (but correct type)
        otherdev = Device()
        nodep = dc.get_next_deployment(
            otherdev.fake_token_mt(tenant_id),
            artifact_name="dontcare",
            device_type=dev.device_type,
        )
        assert nodep is None

        # correct tenant, correct device id, incorrect type
        nodep = dc.get_next_deployment(
            otherdev.fake_token_mt(tenant_id),
            artifact_name="dontcare",
            device_type=otherdev.device_type,
        )
        assert nodep is None
    def test_ok(self, api_client_int, clean_db, mongo):
        tenant_id = str(ObjectId())
        _, r = api_client_int.create_tenant(tenant_id)
        assert r.status_code == 201

        deployment_id = "foo"
        deployment_id = str(uuid4())
        device_id = "bar"
        url = api_client_int.make_api_url(
            "/tenants/{}/configuration/deployments/{}/devices/{}".format(
                tenant_id, deployment_id, device_id
            )
        )
        configuration_deployment = {"name": "foo", "configuration": '{"foo":"bar"}'}
        rsp = requests.post(url, json=configuration_deployment, verify=False)
        assert rsp.status_code == 201
        loc = rsp.headers.get("Location", None)
        assert loc
        api_deployment_id = os.path.basename(loc)
        assert api_deployment_id == deployment_id

        # verify the deployment has been stored correctly in mongodb
        deployment = mongo[
            "deployment_service-{}".format(tenant_id)
        ].deployments.find_one({"_id": deployment_id})
        assert deployment is not None
        assert deployment["type"] == "configuration"
        assert deployment["configuration"]
    def test_create_ok(self, api_client_int, clean_db):
        _, r = api_client_int.create_tenant('foobar')
        assert r.status_code == 201

        assert 'deviceadm-foobar' in clean_db.database_names()
        assert 'migration_info' in clean_db[
            'deviceadm-foobar'].collection_names()
    def test_ok(self, api_client_int, clean_db, mongo, test_set):
        """ 
             Happy path - correct link obtained from the service, leading to a successful download
             of a correct artifact.
        """

        # set up deployment
        tenant_id = str(ObjectId())
        _, r = api_client_int.create_tenant(tenant_id)
        assert r.status_code == 201

        deployment_id = str(uuid4())

        dev = Device()
        dev.device_type = test_set["dev_type"]

        configuration_deployment = {
            "name": test_set["name"],
            "configuration": test_set["config"],
        }

        make_deployment(
            api_client_int,
            tenant_id,
            deployment_id,
            dev.devid,
            configuration_deployment,
        )

        # obtain + verify deployment instructions
        dc = SimpleDeviceClient()
        nextdep = dc.get_next_deployment(
            dev.fake_token_mt(tenant_id),
            artifact_name="dontcare",
            device_type=test_set["dev_type"],
        )

        assert nextdep.artifact["artifact_name"] == test_set["name"]
        assert nextdep.artifact["source"]["uri"] is not None
        assert nextdep.artifact["source"]["expire"] is not None
        assert nextdep.artifact["device_types_compatible"] == [test_set["dev_type"]]

        # get/verify download contents
        r = requests.get(
            nextdep.artifact["source"]["uri"],
            verify=False,
        )
        assert r.status_code == 200

        with open("/testing/out.mender", "wb+") as f:
            f.write(r.content)

        self.verify_artifact(
            "/testing/out.mender",
            test_set["name"],
            test_set["dev_type"],
            test_set["config"],
        )
    def test_fail_wrong_deployment_id(self, api_client_int, clean_db):
        tenant_id = str(ObjectId())
        _, r = api_client_int.create_tenant(tenant_id)
        assert r.status_code == 201

        deployment_id = "foo"
        deployment_id = "baz"
        device_id = "bar"
        url = api_client_int.make_api_url(
            "/tenants/{}/configuration/deployments/{}/devices/{}".format(
                tenant_id, deployment_id, device_id
            )
        )
        configuration_deployment = {"name": "foo", "configuration": '{"foo":"bar"}'}
        rsp = requests.post(url, json=configuration_deployment, verify=False)
        assert rsp.status_code == 400
    def test_fail_duplicate_deployment(self, api_client_int, clean_db):
        tenant_id = str(ObjectId())
        _, r = api_client_int.create_tenant(tenant_id)
        assert r.status_code == 201

        deployment_id = "foo"
        deployment_id = str(uuid4())
        device_id = "bar"
        url = api_client_int.make_api_url(
            "/tenants/{}/configuration/deployments/{}/devices/{}".format(
                tenant_id, deployment_id, device_id
            )
        )
        configuration_deployment = {"name": "foo", "configuration": '{"foo":"bar"}'}
        rsp = requests.post(url, json=configuration_deployment, verify=False)
        assert rsp.status_code == 201
        loc = rsp.headers.get("Location", None)
        assert loc
        api_deployment_id = os.path.basename(loc)
        assert api_deployment_id == deployment_id

        rsp = requests.post(url, json=configuration_deployment, verify=False)
        assert rsp.status_code == 409
    def test_failures(self, api_client_int, clean_db, mongo):
        """ 
             Simulate invalid or malicious download requests.
        """
        # for reference - get a real, working link to an actual deployment
        tenant_id = str(ObjectId())
        _, r = api_client_int.create_tenant(tenant_id)
        assert r.status_code == 201

        deployment_id = str(uuid4())
        dev = Device()
        configuration_deployment = {"name": "foo", "configuration": '{"foo":"bar"}'}

        make_deployment(
            api_client_int,
            tenant_id,
            deployment_id,
            dev.devid,
            configuration_deployment,
        )

        dc = SimpleDeviceClient()
        nextdep = dc.get_next_deployment(
            dev.fake_token_mt(tenant_id),
            artifact_name="dontcare",
            device_type="hammer",
        )
        uri = nextdep.artifact["source"]["uri"]
        qs = parse_qs(urlparse(uri).query)

        # now break the url in various ways

        # wrong deployment (signature error)
        uri_bad_depl = uri.replace(deployment_id, str(uuid4()))
        r = requests.get(
            uri_bad_depl,
            verify=False,
        )
        assert r.status_code == 403

        # wrong tenant in url (signature error)
        other_tenant_id = str(ObjectId())
        _, r = api_client_int.create_tenant(other_tenant_id)
        assert r.status_code == 201

        uri_bad_tenant = uri.replace(tenant_id, other_tenant_id)
        r = requests.get(
            uri_bad_tenant,
            verify=False,
        )
        assert r.status_code == 403

        # wrong dev type (signature error)
        other_dev = Device()
        other_dev.device_type = "foo"
        uri_bad_devtype = uri.replace(dev.device_type, other_dev.device_type)
        r = requests.get(
            uri_bad_devtype,
            verify=False,
        )
        assert r.status_code == 403

        # wrong dev id (signature error)
        uri_bad_devid = uri.replace(dev.devid, other_dev.devid)
        r = requests.get(
            uri_bad_devid,
            verify=False,
        )
        assert r.status_code == 403

        # wrong x-men-signature
        uri_bad_sig = uri.replace(
            qs["x-men-signature"][0], "mftJRzBafnvMXhmMBH3THQertiEk0dZKP075bjBKccc"
        )
        r = requests.get(
            uri_bad_sig,
            verify=False,
        )
        assert r.status_code == 403

        # no x-men-signature
        uri_no_sig = uri.replace("&x-men-signature=", "")
        r = requests.get(
            uri_no_sig,
            verify=False,
        )
        assert r.status_code == 400

        # no x-men-expire
        uri_no_exp = uri.replace("&x-men-expire=", "")
        r = requests.get(
            uri_no_exp,
            verify=False,
        )
        assert r.status_code == 400