1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
//
// 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 <memory>
#include <vector>
#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>
// 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 {
TString private_key;
TString 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 TString& root_certificate,
const std::vector<IdentityKeyCertPair>& identity_key_cert_pairs);
explicit StaticDataCertificateProvider(const TString& root_certificate)
: StaticDataCertificateProvider(root_certificate, {}) {}
explicit StaticDataCertificateProvider(
const std::vector<IdentityKeyCertPair>& identity_key_cert_pairs)
: StaticDataCertificateProvider("", identity_key_cert_pairs) {}
~StaticDataCertificateProvider() override;
grpc_tls_certificate_provider* c_provider() override { return c_provider_; }
private:
grpc_tls_certificate_provider* c_provider_ = nullptr;
};
// A CertificateProviderInterface implementation that will watch the credential
// changes on the file system. This provider will always return the up-to-date
// cert data for all the cert names callers set through |TlsCredentialsOptions|.
// Several things to note:
// 1. This API only supports one key-cert file and hence one set of identity
// key-cert pair, so SNI(Server Name Indication) is not supported.
// 2. The private key and identity certificate should always match. This API
// guarantees atomic read, and it is the callers' responsibility to do atomic
// updates. There are many ways to atomically update the key and certs in the
// file system. To name a few:
// 1) creating a new directory, renaming the old directory to a new name, and
// then renaming the new directory to the original name of the old directory.
// 2) using a symlink for the directory. When need to change, put new
// credential data in a new directory, and change symlink.
class FileWatcherCertificateProvider final
: public CertificateProviderInterface {
public:
// Constructor to get credential updates from root and identity file paths.
//
// @param private_key_path is the file path of the private key.
// @param identity_certificate_path is the file path of the identity
// certificate chain.
// @param root_cert_path is the file path to the root certificate bundle.
// @param refresh_interval_sec is the refreshing interval that we will check
// the files for updates.
FileWatcherCertificateProvider(const TString& private_key_path,
const TString& identity_certificate_path,
const TString& root_cert_path,
unsigned int refresh_interval_sec);
// Constructor to get credential updates from identity file paths only.
FileWatcherCertificateProvider(const TString& private_key_path,
const TString& identity_certificate_path,
unsigned int refresh_interval_sec)
: FileWatcherCertificateProvider(private_key_path,
identity_certificate_path, "",
refresh_interval_sec) {}
// Constructor to get credential updates from root file path only.
FileWatcherCertificateProvider(const TString& root_cert_path,
unsigned int refresh_interval_sec)
: FileWatcherCertificateProvider("", "", root_cert_path,
refresh_interval_sec) {}
~FileWatcherCertificateProvider() override;
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
|