Added authorization tests when trying to attach to a container input. Introduced a test where a principal is allowed to launch a container session, but not to attach to its input, therefore its attempts should fail.
Review: https://reviews.apache.org/r/54784/ Project: http://git-wip-us.apache.org/repos/asf/mesos/repo Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/190c9e0f Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/190c9e0f Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/190c9e0f Branch: refs/heads/master Commit: 190c9e0f1e4e9e847474dd48a928dbcca125a957 Parents: 80644e2 Author: Alexander Rojas <[email protected]> Authored: Mon Feb 20 20:13:55 2017 -0800 Committer: Adam B <[email protected]> Committed: Mon Feb 20 20:13:55 2017 -0800 ---------------------------------------------------------------------- src/tests/api_tests.cpp | 130 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/mesos/blob/190c9e0f/src/tests/api_tests.cpp ---------------------------------------------------------------------- diff --git a/src/tests/api_tests.cpp b/src/tests/api_tests.cpp index 2c3ad54..378612d 100644 --- a/src/tests/api_tests.cpp +++ b/src/tests/api_tests.cpp @@ -4643,6 +4643,136 @@ TEST_F(AgentAPITest, AttachContainerInputFailure) } +// Verifies that unauthorized users are not able to attach to a +// nested container input. +TEST_P(AgentAPITest, AttachContainerInputAuthorization) +{ + ContentType contentType = GetParam(); + + Try<Owned<cluster::Master>> master = StartMaster(); + ASSERT_SOME(master); + + slave::Flags flags = CreateSlaveFlags(); + { + mesos::ACL::AttachContainerInput* acl = + flags.acls.get().add_attach_containers_input(); + acl->mutable_principals()->add_values(DEFAULT_CREDENTIAL.principal()); + acl->mutable_users()->set_type(mesos::ACL::Entity::NONE); + } + + Fetcher fetcher; + + Try<MesosContainerizer*> _containerizer = + MesosContainerizer::create(flags, false, &fetcher); + + ASSERT_SOME(_containerizer); + + Owned<slave::Containerizer> containerizer(_containerizer.get()); + + Owned<MasterDetector> detector = master.get()->createDetector(); + + Try<Owned<cluster::Slave>> slave = + StartSlave(detector.get(), containerizer.get(), flags); + + ASSERT_SOME(slave); + + MockScheduler sched; + MesosSchedulerDriver driver( + &sched, DEFAULT_FRAMEWORK_INFO, master.get()->pid, DEFAULT_CREDENTIAL); + + EXPECT_CALL(sched, registered(&driver, _, _)); + + Future<vector<Offer>> offers; + EXPECT_CALL(sched, resourceOffers(_, _)) + .WillOnce(FutureArg<1>(&offers)); + + driver.start(); + + AWAIT_READY(offers); + EXPECT_NE(0u, offers.get().size()); + + Future<TaskStatus> status; + EXPECT_CALL(sched, statusUpdate(_, _)) + .WillOnce(FutureArg<1>(&status)); + + TaskInfo task = createTask(offers.get()[0], "sleep 1000"); + + driver.launchTasks(offers.get()[0].id(), {task}); + + AWAIT_READY(status); + ASSERT_EQ(TASK_RUNNING, status->state()); + + // Launch a nested container session which runs a shell. + + Future<hashset<ContainerID>> containerIds = containerizer->containers(); + AWAIT_READY(containerIds); + ASSERT_EQ(1u, containerIds->size()); + + v1::ContainerID containerId; + containerId.set_value(UUID::random().toString()); + containerId.mutable_parent()->set_value(containerIds->begin()->value()); + + { + string command = "sh"; + + v1::agent::Call call; + call.set_type(v1::agent::Call::LAUNCH_NESTED_CONTAINER_SESSION); + + call.mutable_launch_nested_container_session()->mutable_container_id() + ->CopyFrom(containerId); + + call.mutable_launch_nested_container_session() + ->mutable_command()->set_value(command); + + http::Headers headers = createBasicAuthHeaders(DEFAULT_CREDENTIAL); + headers["Accept"] = stringify(contentType); + + Future<http::Response> response = http::streaming::post( + slave.get()->pid, + "api/v1", + headers, + serialize(contentType, call), + stringify(contentType)); + + AWAIT_EXPECT_RESPONSE_STATUS_EQ(http::OK().status, response); + } + + // Attempt to attach to the container session's input. + + { + v1::agent::Call call; + call.set_type(v1::agent::Call::ATTACH_CONTAINER_INPUT); + + call.mutable_attach_container_input() + ->set_type(v1::agent::Call::AttachContainerInput::CONTAINER_ID); + + call.mutable_attach_container_input()->mutable_container_id() + ->CopyFrom(containerId); + + ContentType contentType = ContentType::RECORDIO; + ContentType messageContentType = ContentType::PROTOBUF; + + ::recordio::Encoder<v1::agent::Call> encoder( + lambda::bind(serialize, messageContentType, lambda::_1)); + + http::Headers headers = createBasicAuthHeaders(DEFAULT_CREDENTIAL); + headers[MESSAGE_CONTENT_TYPE] = stringify(messageContentType); + + Future<http::Response> response = http::post( + slave.get()->pid, + "api/v1", + headers, + encoder.encode(call), + stringify(contentType)); + + AWAIT_EXPECT_RESPONSE_STATUS_EQ(http::Forbidden().status, response); + } + + driver.stop(); + driver.join(); +} + + TEST_F(AgentAPITest, AttachContainerInputValidation) { Clock::pause();
