def test_dbus_get_jwt_token(self, bitbake_variables, connection, setup_mock_server):
        """Test the JWT token can be retrieved using D-Bus."""

        try:
            # bootstrap the client
            result = connection.run("mender bootstrap --forcebootstrap")
            assert result.exited == 0

            # start the mender-client service
            result = connection.run("systemctl start mender-client")
            assert result.exited == 0

            # get the JWT token via D-Bus
            output = ""
            for i in range(12):
                result = connection.run(
                    "dbus-send --system --dest=io.mender.AuthenticationManager --print-reply /io/mender/AuthenticationManager io.mender.Authentication1.GetJwtToken || true"
                )
                if self.JWT_TOKEN in result.stdout:
                    output = result.stdout
                    break
                time.sleep(5)

            assert f'string "{self.JWT_TOKEN}' in output
        finally:
            connection.run("systemctl stop mender-client")
            cleanup_mender_state(connection)
    def test_dbus_non_root_access(self, bitbake_variables, connection):
        """Test that only root user can access Mender DBus API."""

        # This is the command that is expected to fail for non-root user
        dbus_send_command = "dbus-send --system --dest=io.mender.AuthenticationManager --print-reply /io/mender/AuthenticationManager io.mender.Authentication1.GetJwtToken"

        try:
            connection.run("mender bootstrap", warn=True)
            connection.run("systemctl start mender-client")

            # Wait one state machine cycle for the D-Bus API to be available
            for _ in range(12):
                result = connection.run("journalctl -u mender-client")
                if "Authorize failed:" in result.stdout:
                    break
                time.sleep(5)
            else:
                pytest.fail("failed to detect a full state machine cycle")

            result = connection.run(dbus_send_command)
            assert "string" in result.stdout, result.stdout

            result = connection.run(
                "sudo -u mender-ci-tester %s" % dbus_send_command, warn=True
            )
            assert result.exited == 1
            assert (
                "Error org.freedesktop.DBus.Error.AccessDenied" in result.stderr
            ), result.stderr

        finally:
            connection.run("systemctl stop mender-client")
            cleanup_mender_state(connection)
    def test_mender_connect_reconnect(
        self, connection, with_mock_files, with_mock_servers,
    ):
        """Test that mender-connect can re-establish the connection on remote errors"""

        try:
            dbus_set_token_and_url(connection, "badtoken", "http://localhost:12345")

            # start the mender-connect service
            startup_time = time.time()
            connection.run(
                "systemctl --job-mode=ignore-dependencies start mender-connect"
            )

            # wait for error
            _ = wait_for_string_in_log(
                connection,
                startup_time,
                300,
                "eventLoop: error reconnecting: failed to connect after max number of retries",
            )

            # Set correct parameters
            signal_time = time.time()
            dbus_set_token_and_url_and_emit_signal(
                connection, "goodtoken", "http://localhost:5000"
            )
            _ = wait_for_string_in_log(
                connection,
                signal_time,
                300,
                "Connection established with http://localhost:5000",
            )

            dbus_set_token_and_url(connection, "", "")
            kill_time = time.time()
            # kill the server and wait for error
            with_mock_servers[1].kill()
            _ = wait_for_string_in_log(
                connection, kill_time, 300, "error reconnecting:",
            )

            # Signal the other server
            signal_time = time.time()
            dbus_set_token_and_url_and_emit_signal(
                connection, "goodtoken", "http://localhost:6000"
            )
            _ = wait_for_string_in_log(
                connection,
                signal_time,
                300,
                "Connection established with http://localhost:6000",
            )

        finally:
            connection.run(
                "systemctl --job-mode=ignore-dependencies stop mender-connect || true"
            )
            cleanup_mender_state(connection)
示例#4
0
    def test_invalid_update_control_map(self, setup_board, connection,
                                        second_connection, setup_mock_server):
        try:
            start_and_ready_mender_client(connection, second_connection)

            status = connection.run(
                """dbus-send --system --dest=io.mender.UpdateManager --print-reply /io/mender/UpdateManager io.mender.Update1.SetUpdateControlMap string:'{"not-a":"valid-map"}'""",
                warn=True,
            )
            assert status.return_code != 0
        finally:
            connection.run("systemctl stop mender-client")
            cleanup_mender_state(connection)
    def test_mender_connect_auth_changes(
        self, connection, with_mock_files, with_mock_servers,
    ):
        """Test that mender-connect can re-establish the connection on D-Bus signals"""

        try:
            dbus_set_token_and_url(connection, "token1", "http://localhost:5000")

            # start the mender-connect service
            startup_time = time.time()
            connection.run(
                "systemctl --job-mode=ignore-dependencies start mender-connect"
            )

            # wait for first connect
            _ = wait_for_string_in_log(
                connection,
                startup_time,
                30,
                "Connection established with http://localhost:5000",
            )

            # 1. Change token
            signal_time = time.time()
            dbus_set_token_and_url_and_emit_signal(
                connection, "token2", "http://localhost:5000"
            )
            _ = wait_for_string_in_log(
                connection,
                signal_time,
                30,
                "Connection established with http://localhost:5000",
            )

            # 2. Change url
            signal_time = time.time()
            dbus_set_token_and_url_and_emit_signal(
                connection, "token2", "http://localhost:6000"
            )
            _ = wait_for_string_in_log(
                connection,
                signal_time,
                30,
                "Connection established with http://localhost:6000",
            )

            # 3. Change token and url
            signal_time = time.time()
            dbus_set_token_and_url_and_emit_signal(
                connection, "token3", "http://localhost:5000"
            )
            _ = wait_for_string_in_log(
                connection,
                signal_time,
                30,
                "Connection established with http://localhost:5000",
            )

            # 4. Unauthorize and re-authorize
            signal_time = time.time()
            dbus_set_token_and_url_and_emit_signal(connection, "", "")
            _ = wait_for_string_in_log(
                connection,
                signal_time,
                30,
                "dbusEventLoop terminated 0 sessions, 0 shells",
            )
            dbus_set_token_and_url_and_emit_signal(
                connection, "token4", "http://localhost:6000"
            )
            _ = wait_for_string_in_log(
                connection,
                signal_time,
                30,
                "Connection established with http://localhost:6000",
            )

        finally:
            connection.run(
                "systemctl --job-mode=ignore-dependencies stop mender-connect || true"
            )
            cleanup_mender_state(connection)
示例#6
0
    def test_many_state_transitions_with_update_control(
        self,
        setup_board,
        connection,
        second_connection,
        setup_mock_server,
        bitbake_variables,
        bitbake_path,
    ):
        """Test whether we can make many state transitions with update control without
        triggering the "too many state transitions" error."""

        try:
            start_and_ready_mender_client(connection, second_connection)

            ucm = ("""{
    "ID": "%s",
    "states": {
        "ArtifactInstall_Enter": {
            "action": "pause"
        }
    }
}""" % MUID)

            with tempfile.TemporaryDirectory() as tmpdir:
                script = os.path.join(tmpdir, "map-insert.sh")
                with open(script, "w") as fd:
                    fd.write("""#!/bin/sh
while sleep 0.2; do
    dbus-send --system --dest=io.mender.UpdateManager --print-reply /io/mender/UpdateManager io.mender.Update1.SetUpdateControlMap string:'%s'
done
""" % ucm)
                put_no_sftp(script, connection, remote="/data/map-insert.sh")

            # Constantly reinsert map over and over in the background, to force
            # state transitions.
            connection.run("systemd-run sh /data/map-insert.sh")

            now = time.time()

            make_and_deploy_artifact(connection,
                                     bitbake_variables["MENDER_DEVICE_TYPE"])

            timeout = now + 300
            # Wait until we have received 100 state transitions, which is way
            # more than would cause a failure.
            while time.time() < timeout:
                output = connection.run(
                    "journalctl -u mender-client -S '%s' | grep 'State transition: mender-update-control '"
                    % time.strftime("%Y-%m-%d %H:%M:%S UTC", time.gmtime(now)),
                    warn=True,
                ).stdout
                if len(output.split("\n")) >= 100:
                    break
            else:
                pytest.fail(
                    "Timed out without reaching the required number of state transitions."
                )

            # Just double check that we are indeed paused, as we expect.
            log = wait_for_state(connection, "Download")
            assert "Cleanup" not in log

            # Force it to continue.
            set_update_control_map(
                connection,
                {
                    "ID": MUID2,
                    "priority": 10,
                    "states": {
                        "ArtifactInstall_Enter": {
                            "action": "force_continue"
                        }
                    },
                },
            )

            # Rest of deployment should finish successfully.
            log = wait_for_state(connection, "Cleanup")
            assert "ArtifactFailure" not in log

        except:
            connection.run("journalctl -u mender-client | cat")
            connection.run("journalctl -u mender-mock-server | cat")
            raise

        finally:
            connection.run("pkill -f map-insert.sh", warn=True)
            cleanup_deployment_response(connection)
            # Reset update control maps.
            clear_update_control_maps(connection)
            connection.run("systemctl stop mender-client")
            cleanup_mender_state(connection)
            connection.run("rm -f /data/logger-update-module.log")
示例#7
0
            if case.get("state_before_pause"):
                assert (pause_state_observed >= PAUSE_STATE_OBSERVE_COUNT
                        ), "Looks like the client did not pause!"

        except:
            connection.run("journalctl -u mender-client | cat")
            connection.run("journalctl -u mender-mock-server | cat")
            raise

        finally:
            cleanup_deployment_response(connection)
            # Reset update control maps.
            clear_update_control_maps(connection)
            connection.run("systemctl stop mender-client")
            cleanup_mender_state(connection)
            connection.run("rm -f /data/logger-update-module.log")

    @pytest.mark.min_mender_version("2.7.0")
    def test_invalid_update_control_map(self, setup_board, connection,
                                        second_connection, setup_mock_server):
        try:
            start_and_ready_mender_client(connection, second_connection)

            status = connection.run(
                """dbus-send --system --dest=io.mender.UpdateManager --print-reply /io/mender/UpdateManager io.mender.Update1.SetUpdateControlMap string:'{"not-a":"valid-map"}'""",
                warn=True,
            )
            assert status.return_code != 0
        finally:
            connection.run("systemctl stop mender-client")
    def test_dbus_fetch_jwt_token(
        self, bitbake_variables, connection, second_connection, setup_mock_server
    ):
        """Test the JWT token can be fetched using D-Bus."""

        # bootstrap the client
        result = connection.run("mender bootstrap --forcebootstrap")
        assert result.exited == 0

        try:
            # start monitoring the D-Bus
            def dbus_monitor():
                second_connection.run(
                    "dbus-monitor --system \"type='signal',interface='io.mender.Authentication1'\" > /tmp/dbus-monitor.log"
                )

            p = Process(target=dbus_monitor, daemon=True)
            p.start()

            # get the JWT token via D-Bus
            try:
                # start the mender-client service
                result = connection.run("systemctl start mender-client")
                assert result.exited == 0

                # fetch the JWT token
                fetched = False
                for i in range(12):
                    result = connection.run(
                        "dbus-send --system --dest=io.mender.AuthenticationManager --print-reply /io/mender/AuthenticationManager io.mender.Authentication1.FetchJwtToken || true"
                    )
                    if "true" in result.stdout:
                        fetched = True
                        break
                    time.sleep(5)

                # fetch was successful
                assert fetched

                # verify we received the D-Bus signal JwtTokenStateChange and that it contains the JWT token
                found = False
                output = ""
                for i in range(12):
                    output = connection.run("cat /tmp/dbus-monitor.log").stdout.strip()
                    if (
                        "path=/io/mender/AuthenticationManager; interface=io.mender.Authentication1; member=JwtTokenStateChange"
                        in output
                    ):
                        found = True
                        break
                    time.sleep(5)
                assert found, output

                # token is now available
                result = connection.run(
                    "dbus-send --system --dest=io.mender.AuthenticationManager --print-reply /io/mender/AuthenticationManager io.mender.Authentication1.GetJwtToken"
                )
                assert result.exited == 0

                output = result.stdout.strip()
                assert f'string "{self.JWT_TOKEN}' in output

            finally:
                p.terminate()
                connection.run("systemctl stop mender-client")
                connection.run("rm -f /tmp/dbus-monitor.log")

        finally:
            cleanup_mender_state(connection)