Fix CredentialManager sharing and combined server certificate installation.

Google-Bug-Id:527528182
PiperOrigin-RevId: 974680731
Change-Id: I639d0fca51865f7e2b82c3a0b205fca6bba35a5e
diff --git a/g3/server.cc b/g3/server.cc
index f1fad79..2c3cf84 100644
--- a/g3/server.cc
+++ b/g3/server.cc
@@ -1491,31 +1491,35 @@
       config.periodic_deterministic_fru_scan_interval_ms;
   options.system_registry = config.system_registry;
   options.enable_hft_test_sensor = config.enable_hft_test_sensor;
-
-  milotic_tlbmc::CredentialManagerImpl::CredentialManagerParams cm_params{
-      .private_key_path = config.private_key_path,
-      .cert_path = config.own_cert_path,
-      .owner_verification_cert_path = config.owner_verification_cert_path,
-      .owner_verification_config_path = config.owner_verification_config_path,
-      .bmc_ssh_trusted_user_ca_keys_path =
-          config.bmc_ssh_trusted_user_ca_keys_path,
-      .trust_bundle_path = config.trust_bundle_path,
-      .trust_bundle_signature_path = config.trust_bundle_signature_path,
-      .os_verification_cert_path = config.os_verification_cert_path,
-      .os_verification_key_path = config.os_verification_key_path,
-      .serial_console_trusted_user_ca_keys_path =
-          config.serial_console_trusted_user_ca_keys_path,
-      .serial_console_detatched_signature_path =
-          config.serial_console_detatched_signature_path,
-      .serial_console_access_level_dir = config.serial_console_access_level_dir,
-      .syslog_client_conf_override_path =
-          config.syslog_client_conf_override_path,
-      .syslog_root_cert_path = config.syslog_root_cert_path,
-  };
-  if (absl::StatusOr<std::unique_ptr<milotic_tlbmc::CredentialManager>> cm =
-          milotic_tlbmc::CredentialManagerImpl::Create(cm_params);
-      cm.ok()) {
-    options.credential_manager = std::move(*cm);
+  if (config.credential_manager != nullptr) {
+    options.credential_manager = config.credential_manager;
+  } else {
+    milotic_tlbmc::CredentialManagerImpl::CredentialManagerParams cm_params{
+        .private_key_path = config.private_key_path,
+        .cert_path = config.own_cert_path,
+        .owner_verification_cert_path = config.owner_verification_cert_path,
+        .owner_verification_config_path = config.owner_verification_config_path,
+        .bmc_ssh_trusted_user_ca_keys_path =
+            config.bmc_ssh_trusted_user_ca_keys_path,
+        .trust_bundle_path = config.trust_bundle_path,
+        .trust_bundle_signature_path = config.trust_bundle_signature_path,
+        .os_verification_cert_path = config.os_verification_cert_path,
+        .os_verification_key_path = config.os_verification_key_path,
+        .serial_console_trusted_user_ca_keys_path =
+            config.serial_console_trusted_user_ca_keys_path,
+        .serial_console_detatched_signature_path =
+            config.serial_console_detatched_signature_path,
+        .serial_console_access_level_dir =
+            config.serial_console_access_level_dir,
+        .syslog_client_conf_override_path =
+            config.syslog_client_conf_override_path,
+        .syslog_root_cert_path = config.syslog_root_cert_path,
+    };
+    if (absl::StatusOr<std::unique_ptr<milotic_tlbmc::CredentialManager>> cm =
+            milotic_tlbmc::CredentialManagerImpl::Create(cm_params);
+        cm.ok()) {
+      options.credential_manager = std::move(*cm);
+    }
   }
 
   if (config.nic_accessor_factory != nullptr) {
diff --git a/g3/server.h b/g3/server.h
index 35840c0..2922529 100644
--- a/g3/server.h
+++ b/g3/server.h
@@ -28,6 +28,7 @@
 #include "app.hpp"
 #include "grpcpp/support/status.h"
 #include "tlbmc/service/fru_service.h"
+#include "tlbmc/credentials/credential_manager.h"
 #include "tlbmc/deterministic_bmc/offline_config_parser/proto_reader.h"
 #include "tlbmc/hal/nic_veeprom/interface.h"
 #include "veeprom.pb.h"
@@ -203,6 +204,9 @@
   // System Registry for HAL Calls.
   std::shared_ptr<::milotic_tlbmc::SystemRegistry> system_registry = nullptr;
 
+  std::shared_ptr<milotic_tlbmc::CredentialManager> credential_manager =
+      nullptr;
+
   std::shared_ptr<absl::AnyInvocable<
       std::unique_ptr<::milotic_tlbmc::nic_veeprom::Accessor>(
           ::milotic_tlbmc::nic_veeprom::NicTelemetryVersion version, int bus,
diff --git a/include/webserver_main_setup.hpp b/include/webserver_main_setup.hpp
index 4e29116..ade7c4e 100644
--- a/include/webserver_main_setup.hpp
+++ b/include/webserver_main_setup.hpp
@@ -236,6 +236,7 @@
   secure_service_config.system_registry = system_registry;
 
   credential_manager = createCredentialManagerImpl(secure_service_config);
+  secure_service_config.credential_manager = credential_manager;
 
   std::unique_ptr<milotic_tlbmc::RedfishApp> tlbmc_app =
       milotic::GrpcRedfishService::CreateTlbmcApp(secure_service_config);
@@ -518,6 +519,7 @@
           absl::GetFlag(FLAGS_enable_tlbmc_thermal_control),
       .tlbmc_defer_router_registration_and_validation = true,
       .system_registry = system_registry,
+      .credential_manager = credential_manager,
   };
   GrpcRedfishService insecure_grpc_service(
       &app, tlbmc_app.get(), io, io_worker_threads, insecure_config, nullptr);
diff --git a/tlbmc/credentials/credential_manager_impl.cc b/tlbmc/credentials/credential_manager_impl.cc
index be8f837..17d52d0 100644
--- a/tlbmc/credentials/credential_manager_impl.cc
+++ b/tlbmc/credentials/credential_manager_impl.cc
@@ -540,11 +540,20 @@
 
   // Write to a temp dir
   std::string temp_credential_dir = absl::StrCat(credential_dir, "-tmp");
-  ECCLESIA_RETURN_IF_ERROR(FileManager::WriteToFile(
-      certificate, absl::StrCat(temp_credential_dir, "/", cert_filename)));
-  ECCLESIA_RETURN_IF_ERROR(FileManager::WriteToFile(
-      private_key_pem,
-      absl::StrCat(temp_credential_dir, "/", private_key_filename)));
+  if (params_.cert_path == params_.private_key_path) {
+    // After RestartBmcwebInASeparateThread is called below that bmcweb instance
+    // will attempt to read the cert and key. Since the filepaths are the same,
+    // we must write both the cert and key to the same file.
+    ECCLESIA_RETURN_IF_ERROR(FileManager::WriteToFile(
+        absl::StrCat(certificate, "\n", private_key_pem),
+        absl::StrCat(temp_credential_dir, "/", cert_filename)));
+  } else {
+    ECCLESIA_RETURN_IF_ERROR(FileManager::WriteToFile(
+        certificate, absl::StrCat(temp_credential_dir, "/", cert_filename)));
+    ECCLESIA_RETURN_IF_ERROR(FileManager::WriteToFile(
+        private_key_pem,
+        absl::StrCat(temp_credential_dir, "/", private_key_filename)));
+  }
 
   // Atomically change both key and cert
   ECCLESIA_RETURN_IF_ERROR(