| 1 | // |
| 2 | // Copyright 2020 gRPC authors. |
| 3 | // |
| 4 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | // you may not use this file except in compliance with the License. |
| 6 | // You may obtain a copy of the License at |
| 7 | // |
| 8 | // http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | // |
| 10 | // Unless required by applicable law or agreed to in writing, software |
| 11 | // distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | // See the License for the specific language governing permissions and |
| 14 | // limitations under the License. |
| 15 | // |
| 16 | |
| 17 | #ifndef GRPCPP_SECURITY_TLS_CERTIFICATE_PROVIDER_H |
| 18 | #define GRPCPP_SECURITY_TLS_CERTIFICATE_PROVIDER_H |
| 19 | |
| 20 | #include <memory> |
| 21 | #include <vector> |
| 22 | |
| 23 | #include <grpc/grpc_security.h> |
| 24 | #include <grpc/grpc_security_constants.h> |
| 25 | #include <grpc/status.h> |
| 26 | #include <grpc/support/log.h> |
| 27 | #include <grpcpp/impl/codegen/grpc_library.h> |
| 28 | #include <grpcpp/support/config.h> |
| 29 | |
| 30 | namespace grpc { |
| 31 | namespace experimental { |
| 32 | |
| 33 | // Interface for a class that handles the process to fetch credential data. |
| 34 | // Implementations should be a wrapper class of an internal provider |
| 35 | // implementation. |
| 36 | class CertificateProviderInterface { |
| 37 | public: |
| 38 | virtual ~CertificateProviderInterface() = default; |
| 39 | virtual grpc_tls_certificate_provider* c_provider() = 0; |
| 40 | }; |
| 41 | |
| 42 | // A struct that stores the credential data presented to the peer in handshake |
| 43 | // to show local identity. The private_key and certificate_chain should always |
| 44 | // match. |
| 45 | struct IdentityKeyCertPair { |
| 46 | std::string private_key; |
| 47 | std::string certificate_chain; |
| 48 | }; |
| 49 | |
| 50 | // A basic CertificateProviderInterface implementation that will load credential |
| 51 | // data from static string during initialization. This provider will always |
| 52 | // return the same cert data for all cert names, and reloading is not supported. |
| 53 | class StaticDataCertificateProvider : public CertificateProviderInterface { |
| 54 | public: |
| 55 | StaticDataCertificateProvider( |
| 56 | const std::string& root_certificate, |
| 57 | const std::vector<IdentityKeyCertPair>& identity_key_cert_pairs); |
| 58 | |
| 59 | explicit StaticDataCertificateProvider(const std::string& root_certificate) |
| 60 | : StaticDataCertificateProvider(root_certificate, {}) {} |
| 61 | |
| 62 | explicit StaticDataCertificateProvider( |
| 63 | const std::vector<IdentityKeyCertPair>& identity_key_cert_pairs) |
| 64 | : StaticDataCertificateProvider("" , identity_key_cert_pairs) {} |
| 65 | |
| 66 | ~StaticDataCertificateProvider() override; |
| 67 | |
| 68 | grpc_tls_certificate_provider* c_provider() override { return c_provider_; } |
| 69 | |
| 70 | private: |
| 71 | grpc_tls_certificate_provider* c_provider_ = nullptr; |
| 72 | }; |
| 73 | |
| 74 | // A CertificateProviderInterface implementation that will watch the credential |
| 75 | // changes on the file system. This provider will always return the up-to-date |
| 76 | // cert data for all the cert names callers set through |TlsCredentialsOptions|. |
| 77 | // Several things to note: |
| 78 | // 1. This API only supports one key-cert file and hence one set of identity |
| 79 | // key-cert pair, so SNI(Server Name Indication) is not supported. |
| 80 | // 2. The private key and identity certificate should always match. This API |
| 81 | // guarantees atomic read, and it is the callers' responsibility to do atomic |
| 82 | // updates. There are many ways to atomically update the key and certs in the |
| 83 | // file system. To name a few: |
| 84 | // 1) creating a new directory, renaming the old directory to a new name, and |
| 85 | // then renaming the new directory to the original name of the old directory. |
| 86 | // 2) using a symlink for the directory. When need to change, put new |
| 87 | // credential data in a new directory, and change symlink. |
| 88 | class FileWatcherCertificateProvider final |
| 89 | : public CertificateProviderInterface { |
| 90 | public: |
| 91 | // Constructor to get credential updates from root and identity file paths. |
| 92 | // |
| 93 | // @param private_key_path is the file path of the private key. |
| 94 | // @param identity_certificate_path is the file path of the identity |
| 95 | // certificate chain. |
| 96 | // @param root_cert_path is the file path to the root certificate bundle. |
| 97 | // @param refresh_interval_sec is the refreshing interval that we will check |
| 98 | // the files for updates. |
| 99 | FileWatcherCertificateProvider(const std::string& private_key_path, |
| 100 | const std::string& identity_certificate_path, |
| 101 | const std::string& root_cert_path, |
| 102 | unsigned int refresh_interval_sec); |
| 103 | // Constructor to get credential updates from identity file paths only. |
| 104 | FileWatcherCertificateProvider(const std::string& private_key_path, |
| 105 | const std::string& identity_certificate_path, |
| 106 | unsigned int refresh_interval_sec) |
| 107 | : FileWatcherCertificateProvider(private_key_path, |
| 108 | identity_certificate_path, "" , |
| 109 | refresh_interval_sec) {} |
| 110 | // Constructor to get credential updates from root file path only. |
| 111 | FileWatcherCertificateProvider(const std::string& root_cert_path, |
| 112 | unsigned int refresh_interval_sec) |
| 113 | : FileWatcherCertificateProvider("" , "" , root_cert_path, |
| 114 | refresh_interval_sec) {} |
| 115 | |
| 116 | ~FileWatcherCertificateProvider() override; |
| 117 | |
| 118 | grpc_tls_certificate_provider* c_provider() override { return c_provider_; } |
| 119 | |
| 120 | private: |
| 121 | grpc_tls_certificate_provider* c_provider_ = nullptr; |
| 122 | }; |
| 123 | |
| 124 | } // namespace experimental |
| 125 | } // namespace grpc |
| 126 | |
| 127 | #endif // GRPCPP_SECURITY_TLS_CERTIFICATE_PROVIDER_H |
| 128 | |