aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Julien Boeuf <jboeuf@google.com>2015-08-10 12:45:17 -0700
committerGravatar Julien Boeuf <jboeuf@google.com>2015-08-13 17:25:52 -0700
commitc2274e706937c1742e72a20a889ce1283d12af52 (patch)
treee33b3eb2b86119ed634c587e8bfb62ad1e7e1bfe
parent8d428f1e6d0f7b76f8b737ae63f7a74b97279a1d (diff)
Adding C++ auth metadata processor.
- We always do the processing asynchronously but maintain a synchronous API for the implementor of the processor. - there are a lot of string copies right now. Having a StringPiece object in grpc++ would really help with that (as we would use it for C++ metadata). - Please review the API carefully and if you're happy with it, I'll proceed with tests.
-rw-r--r--include/grpc++/auth_context.h5
-rw-r--r--include/grpc++/auth_metadata_processor.h60
-rw-r--r--include/grpc++/server_credentials.h5
-rw-r--r--src/cpp/common/secure_auth_context.cc12
-rw-r--r--src/cpp/common/secure_auth_context.h6
-rw-r--r--src/cpp/server/insecure_server_credentials.cc2
-rw-r--r--src/cpp/server/secure_server_credentials.cc50
-rw-r--r--src/cpp/server/secure_server_credentials.h27
-rw-r--r--test/cpp/common/secure_auth_context_test.cc20
9 files changed, 176 insertions, 11 deletions
diff --git a/include/grpc++/auth_context.h b/include/grpc++/auth_context.h
index f8ea8ad6f4..0b5f856d3f 100644
--- a/include/grpc++/auth_context.h
+++ b/include/grpc++/auth_context.h
@@ -87,6 +87,11 @@ class AuthContext {
// Iteration over all the properties.
virtual AuthPropertyIterator begin() const = 0;
virtual AuthPropertyIterator end() const = 0;
+
+ // Mutation functions: should only be used by an AuthMetadataProcessor.
+ virtual void AddProperty(const grpc::string& key,
+ const grpc::string& value) = 0;
+ virtual bool SetPeerIdentityPropertyName(const grpc::string& name) = 0;
};
} // namespace grpc
diff --git a/include/grpc++/auth_metadata_processor.h b/include/grpc++/auth_metadata_processor.h
new file mode 100644
index 0000000000..e077ec0c60
--- /dev/null
+++ b/include/grpc++/auth_metadata_processor.h
@@ -0,0 +1,60 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GRPCXX_AUTH_METADATA_PROCESSOR_H_
+#define GRPCXX_AUTH_METADATA_PROCESSOR_H_
+
+#include <map>
+#include <string>
+
+#include <grpc++/auth_context.h>
+
+namespace grpc {
+
+class AuthMetadataProcessor {
+ public:
+ virtual ~AuthMetadataProcessor() {}
+
+ // context is read/write: it contains the properties of the channel peer and
+ // it is the job of the Process method to augment it with properties derived
+ // from the passed-in auth_metadata.
+ virtual bool Process(
+ std::multimap<grpc::string, grpc::string>& auth_metadata,
+ AuthContext* context,
+ std::multimap<grpc::string, grpc::string>* consumed_auth_metadata) = 0;
+};
+
+} // namespace grpc
+
+#endif // GRPCXX_AUTH_METADATA_PROCESSOR_H_
+
diff --git a/include/grpc++/server_credentials.h b/include/grpc++/server_credentials.h
index 11acd67e8a..d540b95e21 100644
--- a/include/grpc++/server_credentials.h
+++ b/include/grpc++/server_credentials.h
@@ -38,6 +38,7 @@
#include <vector>
#include <grpc++/config.h>
+#include <grpc++/auth_metadata_processor.h>
struct grpc_server;
@@ -54,6 +55,10 @@ class ServerCredentials {
virtual int AddPortToServer(const grpc::string& addr,
grpc_server* server) = 0;
+
+ // Has to be called before the server is started.
+ virtual void SetAuthMetadataProcessor(
+ const std::shared_ptr<AuthMetadataProcessor>& processor) = 0;
};
// Options to create ServerCredentials with SSL
diff --git a/src/cpp/common/secure_auth_context.cc b/src/cpp/common/secure_auth_context.cc
index 87d7bab75c..dc41083a48 100644
--- a/src/cpp/common/secure_auth_context.cc
+++ b/src/cpp/common/secure_auth_context.cc
@@ -93,4 +93,16 @@ AuthPropertyIterator SecureAuthContext::end() const {
return AuthPropertyIterator();
}
+void SecureAuthContext::AddProperty(const grpc::string& key,
+ const grpc::string& value) {
+ if (!ctx_) return;
+ grpc_auth_context_add_property(ctx_, key.c_str(), value.data(), value.size());
+}
+
+bool SecureAuthContext::SetPeerIdentityPropertyName(const grpc::string& name) {
+ if (!ctx_) return false;
+ return grpc_auth_context_set_peer_identity_property_name(ctx_,
+ name.c_str()) != 0;
+}
+
} // namespace grpc
diff --git a/src/cpp/common/secure_auth_context.h b/src/cpp/common/secure_auth_context.h
index 264ed620a3..1b27bf5c32 100644
--- a/src/cpp/common/secure_auth_context.h
+++ b/src/cpp/common/secure_auth_context.h
@@ -57,6 +57,12 @@ class SecureAuthContext GRPC_FINAL : public AuthContext {
AuthPropertyIterator end() const GRPC_OVERRIDE;
+ void AddProperty(const grpc::string& key,
+ const grpc::string& value) GRPC_OVERRIDE;
+
+ virtual bool SetPeerIdentityPropertyName(const grpc::string& name)
+ GRPC_OVERRIDE;
+
private:
grpc_auth_context* ctx_;
};
diff --git a/src/cpp/server/insecure_server_credentials.cc b/src/cpp/server/insecure_server_credentials.cc
index 800cd36caa..96458477f0 100644
--- a/src/cpp/server/insecure_server_credentials.cc
+++ b/src/cpp/server/insecure_server_credentials.cc
@@ -43,6 +43,8 @@ class InsecureServerCredentialsImpl GRPC_FINAL : public ServerCredentials {
grpc_server* server) GRPC_OVERRIDE {
return grpc_server_add_insecure_http2_port(server, addr.c_str());
}
+ void SetAuthMetadataProcessor(
+ const std::shared_ptr<AuthMetadataProcessor>& processor) GRPC_OVERRIDE {}
};
} // namespace
diff --git a/src/cpp/server/secure_server_credentials.cc b/src/cpp/server/secure_server_credentials.cc
index 32c45e2280..bdb7ba6e48 100644
--- a/src/cpp/server/secure_server_credentials.cc
+++ b/src/cpp/server/secure_server_credentials.cc
@@ -31,15 +31,65 @@
*
*/
+#include <functional>
+#include <map>
+#include <memory>
+
+
+#include "src/cpp/common/secure_auth_context.h"
#include "src/cpp/server/secure_server_credentials.h"
+#include <grpc++/auth_metadata_processor.h>
+
namespace grpc {
+void AuthMetadataProcessorAyncWrapper::Process(
+ void* self, grpc_auth_context* context, const grpc_metadata* md,
+ size_t md_count, grpc_process_auth_metadata_done_cb cb, void* user_data) {
+ AuthMetadataProcessorAyncWrapper* instance =
+ reinterpret_cast<AuthMetadataProcessorAyncWrapper*>(self);
+ instance->thread_pool_->Add(
+ std::bind(&AuthMetadataProcessorAyncWrapper::ProcessAsync, instance,
+ context, md, md_count, cb, user_data));
+}
+
+void AuthMetadataProcessorAyncWrapper::ProcessAsync(
+ grpc_auth_context* ctx, const grpc_metadata* md, size_t md_count,
+ grpc_process_auth_metadata_done_cb cb, void* user_data) {
+ SecureAuthContext context(ctx);
+ std::multimap<grpc::string, grpc::string> metadata;
+ for (size_t i = 0; i < md_count; i++) {
+ metadata.insert(std::make_pair(
+ md[i].key, grpc::string(md[i].value, md[i].value_length)));
+ }
+ std::multimap<grpc::string, grpc::string> consumed_metadata;
+ bool ok = processor_->Process(metadata, &context, &consumed_metadata);
+ if (ok) {
+ std::vector<grpc_metadata> consumed_md(consumed_metadata.size());
+ for (const auto& entry : consumed_metadata) {
+ consumed_md.push_back({entry.first.c_str(),
+ entry.second.data(),
+ entry.second.size(),
+ {{nullptr, nullptr, nullptr}}});
+ }
+ cb(user_data, &consumed_md[0], consumed_md.size(), 1);
+ } else {
+ cb(user_data, nullptr, 0, 0);
+ }
+}
+
int SecureServerCredentials::AddPortToServer(
const grpc::string& addr, grpc_server* server) {
return grpc_server_add_secure_http2_port(server, addr.c_str(), creds_);
}
+void SecureServerCredentials::SetAuthMetadataProcessor(
+ const std::shared_ptr<AuthMetadataProcessor>& processor) {
+ processor_.reset(new AuthMetadataProcessorAyncWrapper(processor));
+ grpc_server_credentials_set_auth_metadata_processor(
+ creds_, {AuthMetadataProcessorAyncWrapper::Process, processor_.get()});
+}
+
std::shared_ptr<ServerCredentials> SslServerCredentials(
const SslServerCredentialsOptions& options) {
std::vector<grpc_ssl_pem_key_cert_pair> pem_key_cert_pairs;
diff --git a/src/cpp/server/secure_server_credentials.h b/src/cpp/server/secure_server_credentials.h
index b9803f107e..2707336d7f 100644
--- a/src/cpp/server/secure_server_credentials.h
+++ b/src/cpp/server/secure_server_credentials.h
@@ -34,12 +34,33 @@
#ifndef GRPC_INTERNAL_CPP_SERVER_SECURE_SERVER_CREDENTIALS_H
#define GRPC_INTERNAL_CPP_SERVER_SECURE_SERVER_CREDENTIALS_H
+#include <memory>
+
#include <grpc/grpc_security.h>
#include <grpc++/server_credentials.h>
+#include <grpc++/thread_pool_interface.h>
namespace grpc {
+class AuthMetadataProcessorAyncWrapper GRPC_FINAL {
+ public:
+ static void Process(void* self, grpc_auth_context* context,
+ const grpc_metadata* md, size_t md_count,
+ grpc_process_auth_metadata_done_cb cb, void* user_data);
+
+ AuthMetadataProcessorAyncWrapper(
+ const std::shared_ptr<AuthMetadataProcessor>& processor)
+ : thread_pool_(CreateDefaultThreadPool()), processor_(processor) {}
+
+ private:
+ void ProcessAsync(grpc_auth_context* context, const grpc_metadata* md,
+ size_t md_count, grpc_process_auth_metadata_done_cb cb,
+ void* user_data);
+ std::unique_ptr<ThreadPoolInterface> thread_pool_;
+ std::shared_ptr<AuthMetadataProcessor> processor_;
+};
+
class SecureServerCredentials GRPC_FINAL : public ServerCredentials {
public:
explicit SecureServerCredentials(grpc_server_credentials* creds)
@@ -51,8 +72,12 @@ class SecureServerCredentials GRPC_FINAL : public ServerCredentials {
int AddPortToServer(const grpc::string& addr,
grpc_server* server) GRPC_OVERRIDE;
+ void SetAuthMetadataProcessor(
+ const std::shared_ptr<AuthMetadataProcessor>& processor) GRPC_OVERRIDE;
+
private:
- grpc_server_credentials* const creds_;
+ grpc_server_credentials* creds_;
+ std::unique_ptr<AuthMetadataProcessorAyncWrapper> processor_;
};
} // namespace grpc
diff --git a/test/cpp/common/secure_auth_context_test.cc b/test/cpp/common/secure_auth_context_test.cc
index 075d4ce8c9..e208189720 100644
--- a/test/cpp/common/secure_auth_context_test.cc
+++ b/test/cpp/common/secure_auth_context_test.cc
@@ -57,12 +57,12 @@ TEST_F(SecureAuthContextTest, EmptyContext) {
TEST_F(SecureAuthContextTest, Properties) {
grpc_auth_context* ctx = grpc_auth_context_create(NULL);
- grpc_auth_context_add_cstring_property(ctx, "name", "chapi");
- grpc_auth_context_add_cstring_property(ctx, "name", "chapo");
- grpc_auth_context_add_cstring_property(ctx, "foo", "bar");
- EXPECT_EQ(1, grpc_auth_context_set_peer_identity_property_name(ctx, "name"));
-
SecureAuthContext context(ctx);
+ context.AddProperty("name", "chapi");
+ context.AddProperty("name", "chapo");
+ context.AddProperty("foo", "bar");
+ EXPECT_TRUE(context.SetPeerIdentityPropertyName("name"));
+
std::vector<grpc::string> peer_identity = context.GetPeerIdentity();
EXPECT_EQ(2u, peer_identity.size());
EXPECT_EQ("chapi", peer_identity[0]);
@@ -75,12 +75,12 @@ TEST_F(SecureAuthContextTest, Properties) {
TEST_F(SecureAuthContextTest, Iterators) {
grpc_auth_context* ctx = grpc_auth_context_create(NULL);
- grpc_auth_context_add_cstring_property(ctx, "name", "chapi");
- grpc_auth_context_add_cstring_property(ctx, "name", "chapo");
- grpc_auth_context_add_cstring_property(ctx, "foo", "bar");
- EXPECT_EQ(1, grpc_auth_context_set_peer_identity_property_name(ctx, "name"));
-
SecureAuthContext context(ctx);
+ context.AddProperty("name", "chapi");
+ context.AddProperty("name", "chapo");
+ context.AddProperty("foo", "bar");
+ EXPECT_TRUE(context.SetPeerIdentityPropertyName("name"));
+
AuthPropertyIterator iter = context.begin();
EXPECT_TRUE(context.end() != iter);
AuthProperty p0 = *iter;