Repository: mesos Updated Branches: refs/heads/master 2f14af542 -> da60d1c4e
Added the 'Secret' protobuf message. This patch adds a new `Secret` protobuf message which is designed to serve as a generic mechanism for passing priviledged information within Mesos. Review: https://reviews.apache.org/r/56052/ Project: http://git-wip-us.apache.org/repos/asf/mesos/repo Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/c74ab59c Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/c74ab59c Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/c74ab59c Branch: refs/heads/master Commit: c74ab59c5e7df2213739567b8b9e5fccdef37754 Parents: 2f14af5 Author: Greg Mann <[email protected]> Authored: Fri Feb 17 11:47:36 2017 -0800 Committer: Vinod Kone <[email protected]> Committed: Fri Feb 17 11:47:36 2017 -0800 ---------------------------------------------------------------------- include/mesos/mesos.proto | 47 ++++++++++++++++++++++++ include/mesos/v1/mesos.proto | 47 ++++++++++++++++++++++++ src/common/validation.cpp | 38 +++++++++++++++++++ src/common/validation.hpp | 2 + src/tests/slave_validation_tests.cpp | 61 +++++++++++++++++++++++++++++++ 5 files changed, 195 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/mesos/blob/c74ab59c/include/mesos/mesos.proto ---------------------------------------------------------------------- diff --git a/include/mesos/mesos.proto b/include/mesos/mesos.proto index b3c022f..c2b2e6e 100644 --- a/include/mesos/mesos.proto +++ b/include/mesos/mesos.proto @@ -1956,6 +1956,53 @@ message Credentials { /** + * Secret used to pass privileged information. It is designed to provide + * pass-by-value or pass-by-reference semantics, where the REFERENCE type can be + * used by custom modules which interact with a secure back-end. + */ +message Secret +{ + enum Type { + UNKNOWN = 0; + REFERENCE = 1; + VALUE = 2; + } + + // Can be used by modules to refer to a secret stored in a secure back-end. + // The `key` field is provided to permit reference to a single value within a + // secret containing arbitrary key-value pairs. + // + // For example, given a back-end secret store with a secret named + // "my-secret" containing the following key-value pairs: + // + // { + // "username": "my-user", + // "password": "my-password + // } + // + // the username could be referred to in a `Secret` by specifying + // "my-secret" for the `name` and "username" for the `key`. + message Reference + { + required string name = 1; + optional string key = 2; + } + + // Used to pass the value of a secret. + message Value + { + required bytes data = 1; + } + + optional Type type = 1; + + // Only one of `reference` and `value` must be set. + optional Reference reference = 2; + optional Value value = 3; +} + + +/** * Rate (queries per second, QPS) limit for messages from a framework to master. * Strictly speaking they are the combined rate from all frameworks of the same * principal. http://git-wip-us.apache.org/repos/asf/mesos/blob/c74ab59c/include/mesos/v1/mesos.proto ---------------------------------------------------------------------- diff --git a/include/mesos/v1/mesos.proto b/include/mesos/v1/mesos.proto index 1019902..c5b4897 100644 --- a/include/mesos/v1/mesos.proto +++ b/include/mesos/v1/mesos.proto @@ -1955,6 +1955,53 @@ message Credentials { /** + * Secret used to pass privileged information. It is designed to provide + * pass-by-value or pass-by-reference semantics, where the REFERENCE type can be + * used by custom modules which interact with a secure back-end. + */ +message Secret +{ + enum Type { + UNKNOWN = 0; + REFERENCE = 1; + VALUE = 2; + } + + // Can be used by modules to refer to a secret stored in a secure back-end. + // The `key` field is provided to permit reference to a single value within a + // secret containing arbitrary key-value pairs. + // + // For example, given a back-end secret store with a secret named + // "my-secret" containing the following key-value pairs: + // + // { + // "username": "my-user", + // "password": "my-password + // } + // + // the username could be referred to in a `Secret` by specifying + // "my-secret" for the `name` and "username" for the `key`. + message Reference + { + required string name = 1; + optional string key = 2; + } + + // Used to pass the value of a secret. + message Value + { + required bytes data = 1; + } + + optional Type type = 1; + + // Only one of `reference` and `value` must be set. + optional Reference reference = 2; + optional Value value = 3; +} + + +/** * Rate (queries per second, QPS) limit for messages from a framework to master. * Strictly speaking they are the combined rate from all frameworks of the same * principal. http://git-wip-us.apache.org/repos/asf/mesos/blob/c74ab59c/src/common/validation.cpp ---------------------------------------------------------------------- diff --git a/src/common/validation.cpp b/src/common/validation.cpp index 0f1a022..2818261 100644 --- a/src/common/validation.cpp +++ b/src/common/validation.cpp @@ -20,6 +20,7 @@ #include <cctype> #include <stout/foreach.hpp> +#include <stout/unreachable.hpp> #include <stout/os/constants.hpp> @@ -80,6 +81,43 @@ Option<Error> validateFrameworkID(const FrameworkID& frameworkId) } +Option<Error> validateSecret(const Secret& secret) +{ + switch (secret.type()) { + case Secret::REFERENCE: + if (!secret.has_reference()) { + return Error( + "Secret of type REFERENCE must have the 'reference' field set"); + } + + if (secret.has_value()) { + return Error( + "Secret '" + secret.reference().name() + "' of type REFERENCE " + "must not have the 'value' field set"); + } + break; + + case Secret::VALUE: + if (!secret.has_value()) { + return Error("Secret of type VALUE must have the 'value' field set"); + } + + if (secret.has_reference()) { + return Error( + "Secret of type VALUE must not have the 'reference' field set"); + } + break; + + case Secret::UNKNOWN: + break; + + UNREACHABLE(); + } + + return None(); +} + + // TODO(greggomann): Do more than just validate the `Environment`. Option<Error> validateCommandInfo(const CommandInfo& command) { http://git-wip-us.apache.org/repos/asf/mesos/blob/c74ab59c/src/common/validation.hpp ---------------------------------------------------------------------- diff --git a/src/common/validation.hpp b/src/common/validation.hpp index 7946f06..caba07b 100644 --- a/src/common/validation.hpp +++ b/src/common/validation.hpp @@ -41,6 +41,8 @@ Option<Error> validateSlaveID(const SlaveID& slaveId); Option<Error> validateFrameworkID(const FrameworkID& frameworkId); +Option<Error> validateSecret(const Secret& secret); + Option<Error> validateCommandInfo(const CommandInfo& command); } // namespace validation { http://git-wip-us.apache.org/repos/asf/mesos/blob/c74ab59c/src/tests/slave_validation_tests.cpp ---------------------------------------------------------------------- diff --git a/src/tests/slave_validation_tests.cpp b/src/tests/slave_validation_tests.cpp index 3d17799..96218e8 100644 --- a/src/tests/slave_validation_tests.cpp +++ b/src/tests/slave_validation_tests.cpp @@ -32,6 +32,8 @@ namespace validation = mesos::internal::slave::validation; +using mesos::internal::common::validation::validateSecret; + using mesos::internal::slave::Slave; namespace mesos { @@ -86,6 +88,65 @@ TEST(AgentValidationTest, ContainerID) } +// Tests that the common validation code for the +// `Secret` message works as expected. +TEST(AgentValidationTest, Secret) +{ + // Test a secret of VALUE type. + { + Secret secret; + secret.set_type(Secret::VALUE); + + Option<Error> error = validateSecret(secret); + EXPECT_SOME(error); + EXPECT_EQ( + "Secret of type VALUE must have the 'value' field set", + error->message); + + secret.mutable_value()->set_data("SECRET_VALUE"); + secret.mutable_reference()->set_name("SECRET_NAME"); + + error = validateSecret(secret); + EXPECT_SOME(error); + EXPECT_EQ( + "Secret of type VALUE must not have the 'reference' field set", + error->message); + + // Test the valid case. + secret.clear_reference(); + error = validateSecret(secret); + EXPECT_NONE(error); + } + + // Test a secret of REFERENCE type. + { + Secret secret; + secret.set_type(Secret::REFERENCE); + + Option<Error> error = validateSecret(secret); + EXPECT_SOME(error); + EXPECT_EQ( + "Secret of type REFERENCE must have the 'reference' field set", + error->message); + + secret.mutable_reference()->set_name("SECRET_NAME"); + secret.mutable_value()->set_data("SECRET_VALUE"); + + error = validateSecret(secret); + EXPECT_SOME(error); + EXPECT_EQ( + "Secret 'SECRET_NAME' of type REFERENCE " + "must not have the 'value' field set", + error->message); + + // Test the valid case. + secret.clear_value(); + error = validateSecret(secret); + EXPECT_NONE(error); + } +} + + TEST(AgentCallValidationTest, LaunchNestedContainer) { // Missing `launch_nested_container`.
