mirror of https://github.com/grpc/grpc.git
Merge pull request #24227 from ZhenLian/zhen_dynamic_file_reloading_3
C-core changes for TLS credentialspull/24573/head
commit
4d80f376a3
53 changed files with 1957 additions and 2177 deletions
@ -0,0 +1,80 @@ |
|||||||
|
//
|
||||||
|
// Copyright 2020 gRPC authors.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef GRPCPP_SECURITY_TLS_CERTIFICATE_PROVIDER_H |
||||||
|
#define GRPCPP_SECURITY_TLS_CERTIFICATE_PROVIDER_H |
||||||
|
|
||||||
|
#include <grpc/grpc_security_constants.h> |
||||||
|
#include <grpc/status.h> |
||||||
|
#include <grpc/support/log.h> |
||||||
|
#include <grpcpp/impl/codegen/grpc_library.h> |
||||||
|
#include <grpcpp/support/config.h> |
||||||
|
|
||||||
|
#include <memory> |
||||||
|
#include <vector> |
||||||
|
|
||||||
|
// TODO(yihuazhang): remove the forward declaration here and include
|
||||||
|
// <grpc/grpc_security.h> directly once the insecure builds are cleaned up.
|
||||||
|
typedef struct grpc_tls_certificate_provider grpc_tls_certificate_provider; |
||||||
|
|
||||||
|
namespace grpc { |
||||||
|
namespace experimental { |
||||||
|
|
||||||
|
// Interface for a class that handles the process to fetch credential data.
|
||||||
|
// Implementations should be a wrapper class of an internal provider
|
||||||
|
// implementation.
|
||||||
|
class CertificateProviderInterface { |
||||||
|
public: |
||||||
|
virtual ~CertificateProviderInterface() = default; |
||||||
|
virtual grpc_tls_certificate_provider* c_provider() = 0; |
||||||
|
}; |
||||||
|
|
||||||
|
// A struct that stores the credential data presented to the peer in handshake
|
||||||
|
// to show local identity. The private_key and certificate_chain should always
|
||||||
|
// match.
|
||||||
|
struct IdentityKeyCertPair { |
||||||
|
std::string private_key; |
||||||
|
std::string certificate_chain; |
||||||
|
}; |
||||||
|
|
||||||
|
// A basic CertificateProviderInterface implementation that will load credential
|
||||||
|
// data from static string during initialization. This provider will always
|
||||||
|
// return the same cert data for all cert names, and reloading is not supported.
|
||||||
|
class StaticDataCertificateProvider : public CertificateProviderInterface { |
||||||
|
public: |
||||||
|
StaticDataCertificateProvider( |
||||||
|
const std::string& root_certificate, |
||||||
|
const std::vector<IdentityKeyCertPair>& identity_key_cert_pairs); |
||||||
|
|
||||||
|
StaticDataCertificateProvider(const std::string& root_certificate) |
||||||
|
: StaticDataCertificateProvider(root_certificate, {}) {} |
||||||
|
|
||||||
|
StaticDataCertificateProvider( |
||||||
|
const std::vector<IdentityKeyCertPair>& identity_key_cert_pairs) |
||||||
|
: StaticDataCertificateProvider("", identity_key_cert_pairs) {} |
||||||
|
|
||||||
|
~StaticDataCertificateProvider(); |
||||||
|
|
||||||
|
grpc_tls_certificate_provider* c_provider() override { return c_provider_; } |
||||||
|
|
||||||
|
private: |
||||||
|
grpc_tls_certificate_provider* c_provider_ = nullptr; |
||||||
|
}; |
||||||
|
|
||||||
|
} // namespace experimental
|
||||||
|
} // namespace grpc
|
||||||
|
|
||||||
|
#endif // GRPCPP_SECURITY_TLS_CERTIFICATE_PROVIDER_H
|
@ -0,0 +1,78 @@ |
|||||||
|
//
|
||||||
|
// Copyright 2020 gRPC authors.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <grpc/support/port_platform.h> |
||||||
|
|
||||||
|
#include "src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.h" |
||||||
|
|
||||||
|
#include <grpc/support/alloc.h> |
||||||
|
#include <grpc/support/log.h> |
||||||
|
#include <grpc/support/string_util.h> |
||||||
|
|
||||||
|
#include "src/core/lib/surface/api_trace.h" |
||||||
|
|
||||||
|
namespace grpc_core { |
||||||
|
|
||||||
|
StaticDataCertificateProvider::StaticDataCertificateProvider( |
||||||
|
std::string root_certificate, |
||||||
|
grpc_core::PemKeyCertPairList pem_key_cert_pairs) |
||||||
|
: distributor_(MakeRefCounted<grpc_tls_certificate_distributor>()), |
||||||
|
root_certificate_(std::move(root_certificate)), |
||||||
|
pem_key_cert_pairs_(std::move(pem_key_cert_pairs)) { |
||||||
|
distributor_->SetWatchStatusCallback([this](std::string cert_name, |
||||||
|
bool root_being_watched, |
||||||
|
bool identity_being_watched) { |
||||||
|
if (!root_being_watched && !identity_being_watched) return; |
||||||
|
absl::optional<std::string> root_certificate; |
||||||
|
absl::optional<grpc_core::PemKeyCertPairList> pem_key_cert_pairs; |
||||||
|
if (root_being_watched) { |
||||||
|
root_certificate = root_certificate_; |
||||||
|
} |
||||||
|
if (identity_being_watched) { |
||||||
|
pem_key_cert_pairs = pem_key_cert_pairs_; |
||||||
|
} |
||||||
|
distributor_->SetKeyMaterials(cert_name, std::move(root_certificate), |
||||||
|
std::move(pem_key_cert_pairs)); |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
} // namespace grpc_core
|
||||||
|
|
||||||
|
/** -- Wrapper APIs declared in grpc_security.h -- **/ |
||||||
|
|
||||||
|
grpc_tls_certificate_provider* grpc_tls_certificate_provider_static_data_create( |
||||||
|
const char* root_certificate, grpc_tls_identity_pairs* pem_key_cert_pairs) { |
||||||
|
GPR_ASSERT(root_certificate != nullptr || pem_key_cert_pairs != nullptr); |
||||||
|
grpc_core::PemKeyCertPairList identity_pairs_core; |
||||||
|
if (pem_key_cert_pairs != nullptr) { |
||||||
|
identity_pairs_core = std::move(pem_key_cert_pairs->pem_key_cert_pairs); |
||||||
|
delete pem_key_cert_pairs; |
||||||
|
} |
||||||
|
std::string root_cert_core; |
||||||
|
if (root_certificate != nullptr) { |
||||||
|
root_cert_core = root_certificate; |
||||||
|
} |
||||||
|
return new grpc_core::StaticDataCertificateProvider( |
||||||
|
std::move(root_cert_core), std::move(identity_pairs_core)); |
||||||
|
} |
||||||
|
|
||||||
|
void grpc_tls_certificate_provider_release( |
||||||
|
grpc_tls_certificate_provider* provider) { |
||||||
|
GRPC_API_TRACE("grpc_tls_certificate_provider_release(provider=%p)", 1, |
||||||
|
(provider)); |
||||||
|
grpc_core::ExecCtx exec_ctx; |
||||||
|
if (provider != nullptr) provider->Unref(); |
||||||
|
} |
@ -0,0 +1,45 @@ |
|||||||
|
//
|
||||||
|
// Copyright 2020 gRPC authors.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <grpc/grpc_security.h> |
||||||
|
#include <grpc/support/alloc.h> |
||||||
|
#include <grpcpp/security/tls_certificate_provider.h> |
||||||
|
|
||||||
|
#include "absl/container/inlined_vector.h" |
||||||
|
|
||||||
|
namespace grpc { |
||||||
|
namespace experimental { |
||||||
|
|
||||||
|
StaticDataCertificateProvider::StaticDataCertificateProvider( |
||||||
|
const std::string& root_certificate, |
||||||
|
const std::vector<IdentityKeyCertPair>& identity_key_cert_pairs) { |
||||||
|
GPR_ASSERT(!root_certificate.empty() || !identity_key_cert_pairs.empty()); |
||||||
|
grpc_tls_identity_pairs* pairs_core = grpc_tls_identity_pairs_create(); |
||||||
|
for (const IdentityKeyCertPair& pair : identity_key_cert_pairs) { |
||||||
|
grpc_tls_identity_pairs_add_pair(pairs_core, pair.private_key.c_str(), |
||||||
|
pair.certificate_chain.c_str()); |
||||||
|
} |
||||||
|
c_provider_ = grpc_tls_certificate_provider_static_data_create( |
||||||
|
root_certificate.c_str(), pairs_core); |
||||||
|
GPR_ASSERT(c_provider_ != nullptr); |
||||||
|
}; |
||||||
|
|
||||||
|
StaticDataCertificateProvider::~StaticDataCertificateProvider() { |
||||||
|
grpc_tls_certificate_provider_release(c_provider_); |
||||||
|
}; |
||||||
|
|
||||||
|
} // namespace experimental
|
||||||
|
} // namespace grpc
|
@ -0,0 +1,98 @@ |
|||||||
|
//
|
||||||
|
// Copyright 2020 gRPC authors.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <gmock/gmock.h> |
||||||
|
#include <grpc/grpc.h> |
||||||
|
#include <grpc/grpc_security.h> |
||||||
|
#include <grpcpp/security/server_credentials.h> |
||||||
|
#include <grpcpp/security/tls_credentials_options.h> |
||||||
|
#include <gtest/gtest.h> |
||||||
|
|
||||||
|
#include <memory> |
||||||
|
|
||||||
|
#include "src/cpp/client/secure_credentials.h" |
||||||
|
#include "test/core/util/port.h" |
||||||
|
#include "test/core/util/test_config.h" |
||||||
|
|
||||||
|
namespace { |
||||||
|
|
||||||
|
constexpr const char* kRootCertName = "root_cert_name"; |
||||||
|
constexpr const char* kRootCertContents = "root_cert_contents"; |
||||||
|
constexpr const char* kIdentityCertName = "identity_cert_name"; |
||||||
|
constexpr const char* kIdentityCertPrivateKey = "identity_private_key"; |
||||||
|
constexpr const char* kIdentityCertContents = "identity_cert_contents"; |
||||||
|
|
||||||
|
using ::grpc::experimental::StaticDataCertificateProvider; |
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace grpc { |
||||||
|
namespace testing { |
||||||
|
namespace { |
||||||
|
|
||||||
|
TEST( |
||||||
|
CredentialsTest, |
||||||
|
TlsServerCredentialsWithStaticDataCertificateProviderLoadingRootAndIdentity) { |
||||||
|
experimental::IdentityKeyCertPair key_cert_pair; |
||||||
|
key_cert_pair.private_key = kIdentityCertPrivateKey; |
||||||
|
key_cert_pair.certificate_chain = kIdentityCertContents; |
||||||
|
std::vector<experimental::IdentityKeyCertPair> identity_key_cert_pairs; |
||||||
|
identity_key_cert_pairs.emplace_back(key_cert_pair); |
||||||
|
auto certificate_provider = std::make_shared<StaticDataCertificateProvider>( |
||||||
|
kRootCertContents, identity_key_cert_pairs); |
||||||
|
grpc::experimental::TlsServerCredentialsOptions options(certificate_provider); |
||||||
|
options.watch_root_certs(); |
||||||
|
options.set_root_cert_name(kRootCertName); |
||||||
|
options.watch_identity_key_cert_pairs(); |
||||||
|
options.set_identity_cert_name(kIdentityCertName); |
||||||
|
options.set_cert_request_type( |
||||||
|
GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY); |
||||||
|
auto server_credentials = grpc::experimental::TlsServerCredentials(options); |
||||||
|
GPR_ASSERT(server_credentials.get() != nullptr); |
||||||
|
} |
||||||
|
|
||||||
|
// ServerCredentials should always have identity credential presented.
|
||||||
|
// Otherwise gRPC stack will fail.
|
||||||
|
TEST(CredentialsTest, |
||||||
|
TlsServerCredentialsWithStaticDataCertificateProviderLoadingIdentityOnly) { |
||||||
|
experimental::IdentityKeyCertPair key_cert_pair; |
||||||
|
key_cert_pair.private_key = kIdentityCertPrivateKey; |
||||||
|
key_cert_pair.certificate_chain = kIdentityCertContents; |
||||||
|
std::vector<experimental::IdentityKeyCertPair> identity_key_cert_pairs; |
||||||
|
// Adding two key_cert_pair(s) should still work.
|
||||||
|
identity_key_cert_pairs.emplace_back(key_cert_pair); |
||||||
|
identity_key_cert_pairs.emplace_back(key_cert_pair); |
||||||
|
auto certificate_provider = |
||||||
|
std::make_shared<StaticDataCertificateProvider>(identity_key_cert_pairs); |
||||||
|
grpc::experimental::TlsServerCredentialsOptions options(certificate_provider); |
||||||
|
options.watch_identity_key_cert_pairs(); |
||||||
|
options.set_identity_cert_name(kIdentityCertName); |
||||||
|
options.set_cert_request_type( |
||||||
|
GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY); |
||||||
|
auto server_credentials = grpc::experimental::TlsServerCredentials(options); |
||||||
|
GPR_ASSERT(server_credentials.get() != nullptr); |
||||||
|
} |
||||||
|
|
||||||
|
} // namespace
|
||||||
|
} // namespace testing
|
||||||
|
} // namespace grpc
|
||||||
|
|
||||||
|
int main(int argc, char** argv) { |
||||||
|
::testing::InitGoogleTest(&argc, argv); |
||||||
|
grpc::testing::TestEnvironment env(argc, argv); |
||||||
|
int ret = RUN_ALL_TESTS(); |
||||||
|
return ret; |
||||||
|
} |
Loading…
Reference in new issue