blob: e34b7f7ffb1689dcb9d6e8ce0f49ed8289375d4d [file]
#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_