| #ifndef THIRD_PARTY_MILOTIC_INTERNAL_CC_PROXY_REMOTE_CREDENTIALS_H_ |
| #define THIRD_PARTY_MILOTIC_INTERNAL_CC_PROXY_REMOTE_CREDENTIALS_H_ |
| |
| #include <memory> |
| #include <optional> |
| #include <string> |
| #include <utility> |
| #include <vector> |
| |
| #include "absl/base/thread_annotations.h" |
| #include "absl/functional/any_invocable.h" |
| #include "absl/status/status.h" |
| #include "absl/status/statusor.h" |
| #include "absl/strings/string_view.h" |
| #include "absl/synchronization/mutex.h" |
| #include "grpcpp/security/credentials.h" |
| #include "proxy_config.pb.h" |
| |
| namespace milotic { |
| struct RemoteCredentials { |
| std::optional<std::string> username; |
| // TODO : b/320747974 - Make password optional as well |
| std::string password; |
| }; |
| |
| using CredentialsFileReader = |
| absl::AnyInvocable<absl::StatusOr<RemoteCredentials>( |
| absl::string_view file_path, absl::string_view network_endpoint)>; |
| |
| using CredentialsFileWriter = absl::AnyInvocable<absl::Status( |
| absl::string_view new_path, absl::string_view old_path, |
| const RemoteCredentials& credentials, absl::string_view target_mac)>; |
| |
| using GrpcCredentialFetcher = absl::AnyInvocable< |
| absl::StatusOr<std::shared_ptr<grpc::ChannelCredentials>>( |
| const milotic_grpc_proxy::GrpcAuth& grpc_auth)>; |
| |
| using LoginFunction = absl::AnyInvocable<absl::Status( |
| absl::StatusOr<RemoteCredentials>& credentials)>; |
| |
| inline absl::StatusOr<std::shared_ptr<grpc::ChannelCredentials>> |
| UnimplementedGrpcCredentialFetcher( |
| const milotic_grpc_proxy::GrpcAuth& grpc_auth) { |
| return absl::UnimplementedError("Grpc credential fetcher not implemented"); |
| } |
| |
| inline absl::StatusOr<RemoteCredentials> UnimplementedCredentialsFileReader( |
| absl::string_view file_path, absl::string_view network_endpoint) { |
| return absl::UnimplementedError("Credential file reader not implemented"); |
| } |
| |
| inline absl::Status UnimplementedCredentialsFileWriter( |
| absl::string_view new_path, absl::string_view old_path, |
| const RemoteCredentials& credentials, absl::string_view target_mac) { |
| return absl::UnimplementedError("Credential file writer not implemented"); |
| } |
| |
| class CredentialsFileManager { |
| public: |
| explicit CredentialsFileManager(CredentialsFileReader& reader, |
| CredentialsFileWriter& writer) |
| : reader_(reader), writer_(writer) {} |
| |
| CredentialsFileManager(const CredentialsFileManager&) = delete; |
| CredentialsFileManager& operator=(const CredentialsFileManager&) = delete; |
| |
| bool HasSources() const { |
| return !source_files_.empty() || !private_cache_path_.empty(); |
| } |
| |
| // Adds file sources for credentials. These are tried in sequence until one |
| // works. Once credentials have been read *and* used successfully, a cached |
| // value will be used until login fails or the cache is cleared. |
| template <typename Iter> |
| void AddSourceFiles(Iter begin, Iter end) { |
| source_files_.insert(source_files_.end(), begin, end); |
| } |
| |
| // Sets the path to the private cache file. |
| // This file is updated by the CredentialsFileManager with the last working |
| // credentials. If a non-empty value is specified, this is the first source |
| // used. |
| void SetPrivateCachePath(std::string private_cache_path) { |
| private_cache_path_ = std::move(private_cache_path); |
| } |
| |
| // Tries to log on using the cached credentials, or using each credentials |
| // file if there is no cached value. If login succeeds, the value is cached |
| // and stored in the private cache file. |
| // |
| // network_endpoint is passed to the CredentialsFileReader as a key to lookup |
| // the credentials. |
| // |
| // login_func should attempt to use the provided credentials |
| // and return Ok if it was able to log in. This function will be called with |
| // an error value if none of the source files could be read or if no source |
| // files were configured. |
| absl::Status RunLogin(absl::string_view network_endpoint, |
| LoginFunction login_func); |
| |
| private: |
| absl::Status TryLogin(absl::string_view file_path, |
| absl::string_view network_endpoint, |
| LoginFunction& login_func) |
| ABSL_EXCLUSIVE_LOCKS_REQUIRED(credentials_mutex_); |
| |
| CredentialsFileReader& reader_; |
| CredentialsFileWriter& writer_; |
| std::vector<std::string> source_files_; |
| std::string private_cache_path_; |
| absl::Mutex credentials_mutex_; |
| absl::StatusOr<RemoteCredentials> last_tried_credentials_ |
| ABSL_GUARDED_BY(credentials_mutex_) = |
| absl::FailedPreconditionError("Credentials not loaded"); |
| absl::Status last_try_result_ ABSL_GUARDED_BY(credentials_mutex_) = |
| absl::NotFoundError("No working credentials found"); |
| }; |
| |
| } // namespace milotic |
| |
| #endif // THIRD_PARTY_MILOTIC_INTERNAL_CC_PROXY_REMOTE_CREDENTIALS_H_ |