| #ifndef THIRD_PARTY_MILOTIC_EXTERNAL_CC_TLBMC_CREDENTIALS_CREDENTIAL_MANAGER_IMPL_H_ |
| #define THIRD_PARTY_MILOTIC_EXTERNAL_CC_TLBMC_CREDENTIALS_CREDENTIAL_MANAGER_IMPL_H_ |
| |
| #include <cstdint> |
| #include <memory> |
| #include <optional> |
| #include <string> |
| #include <string_view> |
| #include <tuple> |
| #include <vector> |
| |
| #include "owner_certificate/owner_verification_cert_configuration.pb.h" |
| #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 "absl/time/time.h" |
| #include "tlbmc/credentials/credential_manager.h" |
| #include "tlbmc/redfish/routes/action_managers/file_manager.h" |
| #include "resource.pb.h" |
| #include "tlbmc/utils/command_executor.h" |
| #include "zatar/g3_misc.h" |
| #include "openssl/evp.h" |
| |
| namespace milotic_tlbmc { |
| |
| constexpr int kServerRestartDelaySeconds = 3; |
| |
| // Add 1 second as buffer to make sure the restart is triggered after the delay |
| // but the grpc server is not restarted, so we allow retry to go through. |
| inline constexpr int kTrustBundleRetryDelaySeconds = |
| kServerRestartDelaySeconds + 1; |
| |
| constexpr std::string_view kRestartBmcWebCommand = |
| "/usr/bin/systemctl restart --no-block bmcweb"; |
| |
| constexpr std::string_view kTempTrustBundlePath = "/tmp/trust_bundle_XXXXXX"; |
| constexpr std::string_view kTempOsCertPath = "/tmp/os_cert_XXXXXX"; |
| constexpr std::string_view kTempSignaturePath = "/tmp/signature_XXXXXX"; |
| constexpr std::string_view kTempOutputFile = "/tmp/openssl_output_XXXXXX"; |
| constexpr std::string_view kTempTrustedUserCAKeysPath = |
| "/tmp/trusted_user_ca_keys_XXXXXX"; |
| |
| // The command to verify the trust bundle signature and verify the signer |
| // certificate with the CA file to make sure the signer is trusted. |
| constexpr std::string_view kTrustBundleVerifyWithCaCommand = |
| "openssl smime -verify -binary -inform PEM -in '%s' -content '%s' " |
| "-CAfile '%s' -purpose any"; |
| |
| constexpr std::string_view kOsCertVerifyCommand = |
| "openssl verify -CAfile '%s' -purpose any '%s'"; |
| |
| class CredentialManagerImpl : public CredentialManager { |
| public: |
| struct CredentialManagerParams { |
| std::string private_key_path; |
| std::string cert_path; |
| std::string owner_verification_cert_path; |
| std::string owner_verification_config_path; |
| std::string bmc_ssh_trusted_user_ca_keys_path; |
| std::string trust_bundle_path; |
| std::string trust_bundle_signature_path; |
| std::string os_verification_cert_path; |
| std::string os_verification_key_path; |
| std::string serial_console_trusted_user_ca_keys_path; |
| std::string serial_console_detatched_signature_path; |
| std::string serial_console_access_level_dir; |
| std::string syslog_client_conf_override_path; |
| std::string syslog_root_cert_path; |
| }; |
| |
| static absl::StatusOr<std::unique_ptr<CredentialManagerImpl>> Create( |
| const CredentialManagerParams& params); |
| |
| // Generates a CSR (Certificate Signing Request) for the private key. |
| // We will return the CSR string in PEM format and store the private key in |
| // memory. |
| // The old private key will be overwritten. |
| absl::StatusOr<std::string> GenerateCsr(const CsrParams& csr_params) override |
| ABSL_LOCKS_EXCLUDED(mutex_); |
| |
| absl::Status InstallServerCert(std::string_view certificate) override |
| ABSL_LOCKS_EXCLUDED(mutex_); |
| |
| virtual ~CredentialManagerImpl() = default; |
| |
| bssl::UniquePtr<EVP_PKEY> GetPrivateKey() const |
| ABSL_LOCKS_EXCLUDED(mutex_) override { |
| absl::MutexLock lock(mutex_); |
| if (private_key_ == nullptr) { |
| return nullptr; |
| } |
| EVP_PKEY_up_ref(private_key_.get()); |
| return bssl::UniquePtr<EVP_PKEY>(private_key_.get()); |
| } |
| |
| std::optional<std::string> GetOwnerVerificationCert() const override { |
| return owner_verification_cert_; |
| } |
| |
| absl::Status InstallTrustBundle(std::string_view trust_bundle, |
| std::string_view signature) override |
| ABSL_LOCKS_EXCLUDED(mutex_); |
| |
| absl::Status InstallOsVerificationCertificate( |
| std::string_view cert_string) override ABSL_LOCKS_EXCLUDED(mutex_); |
| |
| absl::Status InstallSerialConsoleTrustedUserCAKeys( |
| std::string_view trusted_user_ca_keys, |
| std::string_view signature) override ABSL_LOCKS_EXCLUDED(mutex_); |
| |
| absl::Status InstallSyslogCert(std::string_view cert_string, |
| std::string_view target_ip, |
| int64_t target_port, SyslogProtocol protocol, |
| SyslogTlsMode tls_mode) override |
| ABSL_LOCKS_EXCLUDED(mutex_); |
| |
| std::optional<owner_certificate::OwnerVerificationCertConfiguration> |
| GetOwnerVerificationCertConfiguration() const override { |
| return owner_verification_cert_configuration_; |
| } |
| |
| std::optional<std::string> GetBmcSshTrustedUserCAKeysSignature() |
| const override { |
| return bmc_ssh_trusted_user_ca_keys_signature_; |
| } |
| |
| std::optional<std::string> GetTrustBundle() const override { |
| return trust_bundle_; |
| } |
| |
| std::optional<std::string> GetTrustBundleSignature() const override { |
| return trust_bundle_signature_; |
| } |
| |
| std::optional<std::string> GetServerCert() const override { |
| return server_cert_; |
| } |
| |
| std::optional<std::string> GetOsVerificationCert() const override { |
| return os_verification_cert_; |
| } |
| |
| std::optional<std::string> GetSerialConsoleTrustedUserCAKeys() |
| const override { |
| return serial_console_trusted_user_ca_keys_; |
| } |
| |
| std::optional<std::string> GetSerialConsoleDetatchedSignature() |
| const override { |
| return serial_console_detatched_signature_; |
| } |
| |
| std::optional<SyslogTargetConfig> GetSyslogClientConf() const override |
| ABSL_LOCKS_EXCLUDED(mutex_) { |
| absl::ReaderMutexLock lock(mutex_); |
| return syslog_cert_config_; |
| } |
| |
| std::optional<std::string> GetSyslogRootCert() const override |
| ABSL_LOCKS_EXCLUDED(mutex_) { |
| absl::ReaderMutexLock lock(mutex_); |
| return syslog_root_cert_; |
| } |
| |
| bool IsFirmwareUpdateable() const override { |
| // If there is no owner verification config, then we should allow firmware |
| // updates by default. |
| if (!owner_verification_cert_configuration_.has_value()) { |
| return true; |
| } |
| return owner_verification_cert_configuration_->fw_update_enabled(); |
| } |
| |
| protected: |
| void ParseOwnerVerificationCert(); |
| void ParseOwnerVerificationConfiguration(); |
| void ParseBmcSshTrustedUserCaKeys(); |
| void ParseTrustBundleFiles(); |
| void ParseServerCert(); |
| void ParseOsVerificationCert(); |
| void ParseSerialConsoleTrustedUserCAKeys(); |
| void ParseSyslogTargetConfig(); |
| void ParseSyslogRootCert(); |
| |
| absl::Status VerifyOsVerificationCertificate(std::string_view cert_string) |
| ABSL_LOCKS_EXCLUDED(mutex_); |
| |
| CredentialManagerImpl() = default; |
| explicit CredentialManagerImpl(const CredentialManagerParams& params); |
| |
| void RestartBmcwebInASeparateThread(); |
| |
| absl::StatusOr<StagedTempFile> VerifyAndStageTrustBundle( |
| std::string_view trust_bundle, std::string_view signature) |
| ABSL_SHARED_LOCKS_REQUIRED(mutex_); |
| |
| absl::Status VerifyAndStageSerialConsoleTrustedUserCAKeys( |
| std::string_view trusted_user_ca_keys, std::string_view signature) |
| ABSL_SHARED_LOCKS_REQUIRED(mutex_); |
| |
| absl::Status VerifyAndStageCertificate(std::string_view cert_path, |
| std::string_view signature) |
| ABSL_SHARED_LOCKS_REQUIRED(mutex_); |
| |
| // All credential installation operations should be synchronized. |
| mutable absl::Mutex mutex_; |
| |
| // The in memory private key will be empty until GenerateCSR is called. |
| bssl::UniquePtr<EVP_PKEY> private_key_ ABSL_GUARDED_BY(mutex_); |
| |
| CredentialManagerParams params_; |
| |
| // trust bundle related properties |
| absl::Time last_install_time_ = absl::InfinitePast(); |
| |
| // This is the certificate that will be used to validate the trust bundle and |
| // os verification keys. |
| std::optional<std::string> owner_verification_cert_; |
| std::optional<owner_certificate::OwnerVerificationCertConfiguration> |
| owner_verification_cert_configuration_; |
| std::optional<std::string> bmc_ssh_trusted_user_ca_keys_signature_; |
| |
| std::optional<std::string> trust_bundle_; |
| std::optional<std::string> trust_bundle_signature_; |
| std::optional<std::string> server_cert_; |
| std::optional<std::string> os_verification_cert_; |
| std::optional<std::string> serial_console_trusted_user_ca_keys_; |
| std::optional<std::string> serial_console_detatched_signature_; |
| std::optional<SyslogTargetConfig> syslog_cert_config_; |
| std::optional<std::string> syslog_root_cert_; |
| |
| std::unique_ptr<CommandExecutor> command_executor_; |
| absl::AnyInvocable<void(absl::Status)> restart_bmcweb_callback_; |
| }; |
| |
| } // namespace milotic_tlbmc |
| |
| #endif // THIRD_PARTY_MILOTIC_EXTERNAL_CC_TLBMC_CREDENTIALS_CREDENTIAL_MANAGER_IMPL_H_ |