Added validation for UUID's to master/agent validation helpers. This change adds logic to the master/agent validation helpers to see if the status update acknowledgments have a valid UUID set conforming to one of the supported versions.
Review: https://reviews.apache.org/r/48614/ Project: http://git-wip-us.apache.org/repos/asf/mesos/repo Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/e3a825a5 Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/e3a825a5 Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/e3a825a5 Branch: refs/heads/master Commit: e3a825a5c172fb75227909b964db924543c83f75 Parents: d260aeb Author: Deshna Jain <deshna...@gmail.com> Authored: Mon Jun 20 15:47:09 2016 -0700 Committer: Vinod Kone <vinodk...@gmail.com> Committed: Mon Jun 20 15:47:09 2016 -0700 ---------------------------------------------------------------------- src/master/validation.cpp | 8 ++- src/slave/validation.cpp | 6 ++ src/tests/scheduler_http_api_tests.cpp | 87 +++++++++++++++++++++++++++++ 3 files changed, 100 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/mesos/blob/e3a825a5/src/master/validation.cpp ---------------------------------------------------------------------- diff --git a/src/master/validation.cpp b/src/master/validation.cpp index 7f139fb..9120b71 100644 --- a/src/master/validation.cpp +++ b/src/master/validation.cpp @@ -301,11 +301,17 @@ Option<Error> validate( } return None(); - case mesos::scheduler::Call::ACKNOWLEDGE: + case mesos::scheduler::Call::ACKNOWLEDGE: { if (!call.has_acknowledge()) { return Error("Expecting 'acknowledge' to be present"); } + + Try<UUID> uuid = UUID::fromBytes(call.acknowledge().uuid()); + if (uuid.isError()) { + return uuid.error(); + } return None(); + } case mesos::scheduler::Call::RECONCILE: if (!call.has_reconcile()) { http://git-wip-us.apache.org/repos/asf/mesos/blob/e3a825a5/src/slave/validation.cpp ---------------------------------------------------------------------- diff --git a/src/slave/validation.cpp b/src/slave/validation.cpp index 86e95a2..610829e 100644 --- a/src/slave/validation.cpp +++ b/src/slave/validation.cpp @@ -19,6 +19,7 @@ #include <mesos/agent/agent.hpp> #include <stout/unreachable.hpp> +#include <stout/uuid.hpp> #include "slave/validation.hpp" @@ -142,6 +143,11 @@ Option<Error> validate(const mesos::executor::Call& call) return Error("Expecting 'uuid' to be present"); } + Try<UUID> uuid = UUID::fromBytes(status.uuid()).get(); + if (uuid.isError()) { + return uuid.error(); + } + if (status.has_executor_id() && status.executor_id().value() != call.executor_id().value()) { http://git-wip-us.apache.org/repos/asf/mesos/blob/e3a825a5/src/tests/scheduler_http_api_tests.cpp ---------------------------------------------------------------------- diff --git a/src/tests/scheduler_http_api_tests.cpp b/src/tests/scheduler_http_api_tests.cpp index c12205f..80a2ef0 100644 --- a/src/tests/scheduler_http_api_tests.cpp +++ b/src/tests/scheduler_http_api_tests.cpp @@ -935,6 +935,93 @@ TEST_P(SchedulerHttpApiTest, TeardownWrongStreamId) } } + +// This test verifies that the scheduler will receive a `BadRequest` response +// when it tries to acknowledge a status update with a malformed UUID. +TEST_P(SchedulerHttpApiTest, MalformedUUID) +{ + Try<Owned<cluster::Master>> master = StartMaster(); + ASSERT_SOME(master); + + // Retrieve the parameter passed as content type to this test. + const string contentType = GetParam(); + + process::http::Headers headers = createBasicAuthHeaders(DEFAULT_CREDENTIAL); + headers["Accept"] = contentType; + v1::FrameworkID frameworkId; + string streamId; + + // Subscribe once to get a valid stream ID. + { + Call call; + call.set_type(Call::SUBSCRIBE); + + Call::Subscribe* subscribe = call.mutable_subscribe(); + subscribe->mutable_framework_info()->CopyFrom(DEFAULT_V1_FRAMEWORK_INFO); + + Future<Response> response = process::http::streaming::post( + master.get()->pid, + "api/v1/scheduler", + headers, + serialize(call, contentType), + contentType); + + AWAIT_EXPECT_RESPONSE_STATUS_EQ(OK().status, response); + ASSERT_EQ(Response::PIPE, response.get().type); + ASSERT_TRUE(response.get().headers.contains("Mesos-Stream-Id")); + + streamId = response.get().headers.at("Mesos-Stream-Id"); + + Option<Pipe::Reader> reader = response.get().reader; + ASSERT_SOME(reader); + + auto deserializer = lambda::bind( + &SchedulerHttpApiTest::deserialize, this, contentType, lambda::_1); + + Reader<Event> responseDecoder(Decoder<Event>(deserializer), reader.get()); + + Future<Result<Event>> event = responseDecoder.read(); + AWAIT_READY(event); + ASSERT_SOME(event.get()); + + // Check that the event type is subscribed and the framework ID is set. + ASSERT_EQ(Event::SUBSCRIBED, event.get().get().type()); + + frameworkId = event.get().get().subscribed().framework_id(); + EXPECT_NE("", frameworkId.value()); + } + + // Make an acknowledge call with a malformed UUID. This should result in a + // `BadResponse`. + { + headers["Mesos-Stream-Id"] = streamId; + + Call call; + call.set_type(Call::ACKNOWLEDGE); + + // Set the framework ID in the subscribe call. + call.mutable_framework_id()->CopyFrom(frameworkId); + + Call::Acknowledge* acknowledge = call.mutable_acknowledge(); + acknowledge->mutable_task_id()->set_value("task-id"); + acknowledge->mutable_agent_id()->set_value("agent-id"); + + // Set a malformed uuid. + acknowledge->set_uuid("bad-uuid"); + + Future<Response> response = process::http::post( + master.get()->pid, + "api/v1/scheduler", + headers, + serialize(call, contentType), + contentType); + + AWAIT_EXPECT_RESPONSE_STATUS_EQ(BadRequest().status, response); + AWAIT_EXPECT_RESPONSE_BODY_EQ( + "Failed to validate scheduler::Call: Not a valid UUID", response); + } +} + } // namespace tests { } // namespace internal { } // namespace mesos {