Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions cli/cmd/init_install_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ type InitInstallConfigOpts struct {
ACMEEABMacKey string
ACMEDNS01Provider string

ACMECustomDomainsEABKeyID string
ACMECustomDomainsEABMacKey string

CodesphereDomain string
CodespherePublicIP string
CodesphereWorkspaceHostingBaseDomain string
Expand Down Expand Up @@ -198,6 +201,8 @@ func AddInitInstallConfigCmd(init *cobra.Command, opts *util.GlobalOptions) {
c.cmd.Flags().StringVar(&c.Opts.ACMEServer, "acme-server", "https://acme-v02.api.letsencrypt.org/directory", "ACME server URL")
c.cmd.Flags().StringVar(&c.Opts.ACMEEABKeyID, "acme-eab-key-id", "", "External Account Binding key ID (required by some ACME providers)")
c.cmd.Flags().StringVar(&c.Opts.ACMEEABMacKey, "acme-eab-mac-key", "", "External Account Binding MAC key (required by some ACME providers)")
c.cmd.Flags().StringVar(&c.Opts.ACMECustomDomainsEABKeyID, "acme-custom-domains-eab-key-id", "", "External Account Binding key ID for custom-domain certificates (must differ from --acme-eab-key-id)")
Comment thread
OliverTrautvetter marked this conversation as resolved.
c.cmd.Flags().StringVar(&c.Opts.ACMECustomDomainsEABMacKey, "acme-custom-domains-eab-mac-key", "", "External Account Binding MAC key for custom-domain certificates")
c.cmd.Flags().StringVar(&c.Opts.ACMEDNS01Provider, "acme-dns01-provider", "", "DNS provider for DNS-01 solver (e.g., cloudflare)")

c.cmd.Flags().StringVar(&c.Opts.CodesphereDomain, "domain", "", "Main Codesphere domain")
Expand Down Expand Up @@ -512,6 +517,12 @@ func (c *InitInstallConfigCmd) updateConfigFromOpts(config *files.RootConfig, va
if c.Opts.ACMEEABMacKey != "" {
vault.SetSecret(files.SecretEntry{Name: files.SecretAcmeEabMacKey, Fields: &files.SecretFields{Password: c.Opts.ACMEEABMacKey}})
}
if c.Opts.ACMECustomDomainsEABKeyID != "" {
certIssuer.Acme.CustomDomainsEABKeyID = c.Opts.ACMECustomDomainsEABKeyID
}
if c.Opts.ACMECustomDomainsEABMacKey != "" {
vault.SetSecret(files.SecretEntry{Name: files.SecretAcmeCustomDomainsEabMacKey, Fields: &files.SecretFields{Password: c.Opts.ACMECustomDomainsEABMacKey}})
}

// Configure DNS-01 solver
if c.Opts.ACMEDNS01Provider != "" {
Expand Down
2 changes: 1 addition & 1 deletion cli/cmd/k0s/install_k0s.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ func AddInstallCmd(install *cobra.Command, opts *util.GlobalOptions) {
FileWriter: intutil.NewFilesystemWriter(),
}
k0s.cmd.Flags().StringVarP(&k0s.Opts.Version, "version", "v", installer.DefaultK0sVersion, "Version of k0s to install")
k0s.cmd.Flags().StringVar(&k0s.Opts.K0sctlVersion, "k0sctl-version", "", "Version of k0sctl to use")
k0s.cmd.Flags().StringVar(&k0s.Opts.K0sctlVersion, "k0sctl-version", installer.DefaultK0sctlVersion, "Version of k0sctl to use")
k0s.cmd.Flags().StringVarP(&k0s.Opts.Package, "package", "p", "", "Package file (e.g. codesphere-v1.2.3-installer-lite.tar.gz) to load k0s from")
k0s.cmd.Flags().StringVar(&k0s.Opts.InstallConfig, "install-config", "", "Path to Codesphere install-config file (required)")
k0s.cmd.Flags().StringVar(&k0s.Opts.SSHKeyPath, "ssh-key-path", "", "SSH private key path for remote installation")
Expand Down
23 changes: 23 additions & 0 deletions cli/cmd/update_install_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ type UpdateInstallConfigOpts struct {
ACMEEABMacKey string
ACMEDNS01Provider string

ACMECustomDomainsEABKeyID string
ACMECustomDomainsEABMacKey string

CodesphereDomain string
CodespherePublicIP string
CodesphereWorkspaceHostingBaseDomain string
Expand Down Expand Up @@ -151,6 +154,8 @@ func AddUpdateInstallConfigCmd(update *cobra.Command, opts *util.GlobalOptions)
c.cmd.Flags().StringVar(&c.Opts.ACMEServer, "acme-server", "", "ACME server URL")
c.cmd.Flags().StringVar(&c.Opts.ACMEEABKeyID, "acme-eab-key-id", "", "External Account Binding key ID (required by some ACME providers)")
c.cmd.Flags().StringVar(&c.Opts.ACMEEABMacKey, "acme-eab-mac-key", "", "External Account Binding MAC key (required by some ACME providers)")
c.cmd.Flags().StringVar(&c.Opts.ACMECustomDomainsEABKeyID, "acme-custom-domains-eab-key-id", "", "External Account Binding key ID for custom-domain certificates (must differ from --acme-eab-key-id)")
c.cmd.Flags().StringVar(&c.Opts.ACMECustomDomainsEABMacKey, "acme-custom-domains-eab-mac-key", "", "External Account Binding MAC key for custom-domain certificates")
c.cmd.Flags().StringVar(&c.Opts.ACMEDNS01Provider, "acme-dns01-provider", "", "DNS provider for DNS-01 solver")

// Codesphere update flags
Expand Down Expand Up @@ -383,6 +388,24 @@ func (c *UpdateInstallConfigCmd) applyACMEUpdates(config *files.RootConfig, vaul
}
}

if c.Opts.ACMECustomDomainsEABKeyID != "" && certIssuer.Acme.CustomDomainsEABKeyID != c.Opts.ACMECustomDomainsEABKeyID {
log.Printf("Updating ACME custom-domains EAB key ID: %s -> %s\n", certIssuer.Acme.CustomDomainsEABKeyID, c.Opts.ACMECustomDomainsEABKeyID)
certIssuer.Acme.CustomDomainsEABKeyID = c.Opts.ACMECustomDomainsEABKeyID
acmeChanged = true
}

if c.Opts.ACMECustomDomainsEABMacKey != "" {
currentKey := ""
if s := vault.GetSecret(files.SecretAcmeCustomDomainsEabMacKey); s != nil && s.Fields != nil {
currentKey = s.Fields.Password
}
if currentKey != c.Opts.ACMECustomDomainsEABMacKey {
log.Printf("Updating ACME custom-domains EAB MAC key\n")
vault.SetSecret(files.SecretEntry{Name: files.SecretAcmeCustomDomainsEabMacKey, Fields: &files.SecretFields{Password: c.Opts.ACMECustomDomainsEABMacKey}})
acmeChanged = true
}
}

// Update DNS-01 solver configuration
if c.Opts.ACMEDNS01Provider != "" {
if certIssuer.Acme.Solver.DNS01 == nil {
Expand Down
2 changes: 2 additions & 0 deletions docs/oms_init_install-config.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ $ oms init install-config --validate -c config.yaml --vault prod.vault.yaml
### Options

```
--acme-custom-domains-eab-key-id string External Account Binding key ID for custom-domain certificates (must differ from --acme-eab-key-id)
--acme-custom-domains-eab-mac-key string External Account Binding MAC key for custom-domain certificates
--acme-dns01-provider string DNS provider for DNS-01 solver (e.g., cloudflare)
--acme-eab-key-id string External Account Binding key ID (required by some ACME providers)
--acme-eab-mac-key string External Account Binding MAC key (required by some ACME providers)
Expand Down
2 changes: 1 addition & 1 deletion docs/oms_install_k0s.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ $ oms install k0s --no-download
-f, --force Force new download and installation
-h, --help help for k0s
--install-config string Path to Codesphere install-config file (required)
--k0sctl-version string Version of k0sctl to use
--k0sctl-version string Version of k0sctl to use (default "v0.31.1")
--no-download Skip downloading k0s binary
-p, --package string Package file (e.g. codesphere-v1.2.3-installer-lite.tar.gz) to load k0s from
--ssh-key-path string SSH private key path for remote installation
Expand Down
2 changes: 2 additions & 0 deletions docs/oms_update_install-config.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ $ oms update install-config --k8s-api-server 10.0.0.10 --config config.yaml --va
### Options

```
--acme-custom-domains-eab-key-id string External Account Binding key ID for custom-domain certificates (must differ from --acme-eab-key-id)
--acme-custom-domains-eab-mac-key string External Account Binding MAC key for custom-domain certificates
--acme-dns01-provider string DNS provider for DNS-01 solver
--acme-eab-key-id string External Account Binding key ID (required by some ACME providers)
--acme-eab-mac-key string External Account Binding MAC key (required by some ACME providers)
Expand Down
2 changes: 2 additions & 0 deletions internal/bootstrap/gcp/gce.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ func (b *GCPBootstrapper) EnsureComputeInstances() error {
b.Env.Jumpbox = &node.Node{
NodeClient: b.NodeClient,
FileIO: b.fw,
KeyPath: util.ExpandPath(b.Env.SSHPrivateKeyPath),
}
dcByID := map[int]*datacenter.DataCenter{}

Expand Down Expand Up @@ -555,6 +556,7 @@ func (b *GCPBootstrapper) GetNodeByName(name string) (*node.Node, error) {
existingNode := &node.Node{
NodeClient: b.NodeClient,
FileIO: b.fw,
KeyPath: util.ExpandPath(b.Env.SSHPrivateKeyPath),
}

internalIP, externalIP := ExtractInstanceIPs(existingInstance)
Expand Down
10 changes: 10 additions & 0 deletions internal/bootstrap/gcp/install_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -240,9 +240,19 @@ func (b *GCPBootstrapper) UpdateInstallConfig() error {
if err != nil {
return fmt.Errorf("failed to obtain Google Public CA EAB credentials: %w", err)
}

customDomainsKeyID, customDomainsB64MacKey, err := b.GCPClient.CreatePublicCAExternalAccountKey(b.Env.ProjectID)
if err != nil {
return fmt.Errorf("failed to obtain Google Public CA EAB credentials for custom domains: %w", err)
}
if customDomainsKeyID == keyID {
return fmt.Errorf("google Public CA returned the same EAB key ID for the default and custom-domains ACME accounts")
}
acmeConfig.Server = "https://dv.acme-v02.api.pki.goog/directory"
acmeConfig.EABKeyID = keyID
acmeConfig.CustomDomainsEABKeyID = customDomainsKeyID
b.icg.GetVault().SetSecret(files.SecretEntry{Name: files.SecretAcmeEabMacKey, Fields: &files.SecretFields{Password: b64MacKey}})
b.icg.GetVault().SetSecret(files.SecretEntry{Name: files.SecretAcmeCustomDomainsEabMacKey, Fields: &files.SecretFields{Password: customDomainsB64MacKey}})
}
b.Env.InstallConfig.Codesphere.CertIssuer = &files.CertIssuerConfig{
Type: "acme",
Expand Down
21 changes: 20 additions & 1 deletion internal/bootstrap/gcp/install_config_test.go
Comment thread
OliverTrautvetter marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -762,7 +762,8 @@ var _ = Describe("Installconfig & Secrets", func() {
csEnv.GoogleACMEIssuer = true
})
It("requests EAB credentials from Public CA and uses them in the ACME config", func() {
gc.EXPECT().CreatePublicCAExternalAccountKey(mock.Anything).Return("fake-eab-key-id", "fake-eab-mac-key", nil)
gc.EXPECT().CreatePublicCAExternalAccountKey(mock.Anything).Return("fake-eab-key-id", "fake-eab-mac-key", nil).Once()
gc.EXPECT().CreatePublicCAExternalAccountKey(mock.Anything).Return("fake-cd-eab-key-id", "fake-cd-eab-mac-key", nil).Once()
icg.EXPECT().GenerateSecrets().Return(nil)
icg.EXPECT().WriteInstallConfig("fake-config-file", true).Return(nil)
icg.EXPECT().WriteVault("fake-secret", true).Return(nil)
Expand All @@ -775,6 +776,8 @@ var _ = Describe("Installconfig & Secrets", func() {
Expect(bs.Env.InstallConfig.Codesphere.CertIssuer.Acme.Server).To(Equal("https://dv.acme-v02.api.pki.goog/directory"))
Expect(bs.Env.InstallConfig.Codesphere.CertIssuer.Acme.EABKeyID).To(Equal("fake-eab-key-id"))
Expect(vault.GetSecret(files.SecretAcmeEabMacKey).Fields.Password).To(Equal("fake-eab-mac-key"))
Expect(bs.Env.InstallConfig.Codesphere.CertIssuer.Acme.CustomDomainsEABKeyID).To(Equal("fake-cd-eab-key-id"))
Expect(vault.GetSecret(files.SecretAcmeCustomDomainsEabMacKey).Fields.Password).To(Equal("fake-cd-eab-mac-key"))

issuers := bs.Env.InstallConfig.Cluster.Certificates.Override["issuers"].(map[string]interface{})
httpIssuer := issuers["letsEncryptHttp"].(map[string]interface{})
Expand All @@ -787,6 +790,22 @@ var _ = Describe("Installconfig & Secrets", func() {
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("failed to obtain Google Public CA EAB credentials"))
})
It("returns an error when the second public API call for custom domains fails", func() {
gc.EXPECT().CreatePublicCAExternalAccountKey(mock.Anything).Return("fake-eab-key-id", "fake-eab-mac-key", nil).Once()
gc.EXPECT().CreatePublicCAExternalAccountKey(mock.Anything).Return("", "", fmt.Errorf("api boom")).Once()

err := bs.UpdateInstallConfig()
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("failed to obtain Google Public CA EAB credentials for custom domains"))
})
It("returns an error when both EAB key IDs are the same", func() {
gc.EXPECT().CreatePublicCAExternalAccountKey(mock.Anything).Return("same-eab-key-id", "fake-eab-mac-key", nil).Once()
gc.EXPECT().CreatePublicCAExternalAccountKey(mock.Anything).Return("same-eab-key-id", "fake-cd-eab-mac-key", nil).Once()

err := bs.UpdateInstallConfig()
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("google Public CA returned the same EAB key ID for the default and custom-domains ACME accounts"))
})
})

Context("When ACME staging is enabled", func() {
Expand Down
22 changes: 22 additions & 0 deletions internal/installer/config_generator_collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,28 @@ func (g *InstallConfig) collectACMEConfig(prompter prompt.Prompter) {
}
}

// External Account Binding (EAB) for custom domains
log.Println("\n--- Custom Domains External Account Binding (Optional) ---")
hasCustomDomainsEAB := prompter.Bool("Configure a separate External Account Binding for custom-domain certificates", certIssuer.Acme.CustomDomainsEABKeyID != "")

certIssuer.Acme.CustomDomainsEABKeyID = ""
if hasCustomDomainsEAB {
certIssuer.Acme.CustomDomainsEABKeyID = g.collectString(prompter, "Custom Domains EAB Key ID", certIssuer.Acme.CustomDomainsEABKeyID)
existingCustomDomainsEabKey := ""
if g.Vault != nil {
if s := g.Vault.GetSecret(files.SecretAcmeCustomDomainsEabMacKey); s != nil && s.Fields != nil {
existingCustomDomainsEabKey = s.Fields.Password
}
}
newCustomDomainsEabKey := g.collectString(prompter, "Custom Domains EAB MAC Key", existingCustomDomainsEabKey)
if newCustomDomainsEabKey != "" {
if g.Vault == nil {
g.Vault = &files.InstallVault{}
}
g.Vault.SetSecret(files.SecretEntry{Name: files.SecretAcmeCustomDomainsEabMacKey, Fields: &files.SecretFields{Password: newCustomDomainsEabKey}})
}
}

// DNS-01 Challenge Configuration
log.Println("\n--- DNS-01 Challenge Configuration (Optional) ---")
if certIssuer.Acme.Solver.DNS01 == nil {
Expand Down
7 changes: 7 additions & 0 deletions internal/installer/config_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,13 @@ func (g *InstallConfig) ValidateInstallConfig() []string {
}
}

if ci := g.Config.Codesphere.CertIssuer; ci != nil && ci.Acme != nil {
acme := ci.Acme
if acme.EABKeyID != "" && acme.CustomDomainsEABKeyID != "" && acme.EABKeyID == acme.CustomDomainsEABKeyID {
errors = append(errors, "ACME EAB key ID and custom-domains EAB key ID must be different")
}
}

errors = append(errors, validateOpenFga(g.Config.Codesphere.OpenFga)...)

return errors
Expand Down
29 changes: 29 additions & 0 deletions internal/installer/config_manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,35 @@ var _ = Describe("ConfigManager", func() {
})
})

Context("ACME validation", func() {
BeforeEach(func() {
configManager.Config.Codesphere.CertIssuer = &files.CertIssuerConfig{
Type: files.CertIssuerTypeACME,
Acme: &files.ACMEConfig{
Enabled: true,
EABKeyID: "eab-key-id",
},
}
})

It("should not error when only the primary EAB key ID is set", func() {
errors := configManager.ValidateInstallConfig()
Expect(errors).ToNot(ContainElement(ContainSubstring("EAB key ID")))
})

It("should not error when the EAB key IDs differ", func() {
configManager.Config.Codesphere.CertIssuer.Acme.CustomDomainsEABKeyID = "custom-domains-eab-key-id"
errors := configManager.ValidateInstallConfig()
Expect(errors).ToNot(ContainElement(ContainSubstring("EAB key ID")))
})

It("should error when the EAB key IDs are the same", func() {
configManager.Config.Codesphere.CertIssuer.Acme.CustomDomainsEABKeyID = "eab-key-id"
errors := configManager.ValidateInstallConfig()
Expect(errors).To(ContainElement(ContainSubstring("ACME EAB key ID and custom-domains EAB key ID must be different")))
})
})

Context("openfga backups validation", func() {
It("should require destinationPath and endpointURL when enabled", func() {
configManager.Config.Codesphere.OpenfgaBackups = &files.OpenfgaBackupsConfig{
Expand Down
3 changes: 2 additions & 1 deletion internal/installer/files/config_yaml.go
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,8 @@ type ACMEConfig struct {
PrivateKeySecretName string `yaml:"-"`
Solver ACMESolver `yaml:"-"`

EABKeyID string `yaml:"eabKeyId,omitempty"`
EABKeyID string `yaml:"eabKeyId,omitempty"`
CustomDomainsEABKeyID string `yaml:"customDomainsEabKeyId,omitempty"`
}

type ACMESolver struct {
Expand Down
3 changes: 2 additions & 1 deletion internal/installer/files/secret_names.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ const (
SecretRegistryPassword = "registryPassword"

// ACME
SecretAcmeEabMacKey = "acmeEabMacKey"
SecretAcmeEabMacKey = "acmeEabMacKey"
SecretAcmeCustomDomainsEabMacKey = "acmeCustomDomainsEabMacKey"

// OpenBao
SecretOpenBaoPassword = "openBaoPassword"
Expand Down
3 changes: 3 additions & 0 deletions internal/installer/k0sctl.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ import (
"github.com/codesphere-cloud/oms/internal/util"
)

// DefaultK0sctlVersion is the currently verified k0sctl version.
const DefaultK0sctlVersion = "v0.31.1"

//mockery:generate: true
type K0sctlManager interface {
GetLatestVersion() (string, error)
Expand Down
14 changes: 7 additions & 7 deletions internal/installer/node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ type Node struct {
// If connecting via the Jumpbox
Jumpbox *Node `json:"-"`
// Config
keyPath string `json:"-"`
KeyPath string `json:"-"`
Name string `json:"name"`
ExternalIP string `json:"external_ip"`
InternalIP string `json:"internal_ip"`
Expand Down Expand Up @@ -123,7 +123,7 @@ func (n *Node) CreateSubNode(name string, externalIP string, internalIP string)
// Inherited from jumpbox
FileIO: n.FileIO,
Jumpbox: n,
keyPath: util.ExpandPath(n.keyPath),
KeyPath: util.ExpandPath(n.KeyPath),
sshQuiet: n.sshQuiet,
NodeClient: n.NodeClient,

Expand Down Expand Up @@ -594,7 +594,7 @@ func (n *Node) getAuthMethods() ([]ssh.AuthMethod, error) {
}

// 2. Add Private Key (File) if needed
if n.keyPath != "" {
if n.KeyPath != "" {
shouldLoad := true

// Use cached signer if available
Expand All @@ -605,7 +605,7 @@ func (n *Node) getAuthMethods() ([]ssh.AuthMethod, error) {

// Check if key is already in agent (requires .pub file)
if shouldLoad && len(signers) > 0 {
if pubBytes, err := n.FileIO.ReadFile(n.keyPath + ".pub"); err == nil {
if pubBytes, err := n.FileIO.ReadFile(n.KeyPath + ".pub"); err == nil {
if targetPub, _, _, _, err := ssh.ParseAuthorizedKey(pubBytes); err == nil {
targetMarshaled := string(targetPub.Marshal())
for _, s := range signers {
Expand Down Expand Up @@ -638,9 +638,9 @@ func (n *Node) getAuthMethods() ([]ssh.AuthMethod, error) {

// loadPrivateKey reads and parses the private key, prompting for passphrase if needed.
func (n *Node) loadPrivateKey() (ssh.Signer, error) {
key, err := n.FileIO.ReadFile(n.keyPath)
key, err := n.FileIO.ReadFile(n.KeyPath)
if err != nil {
return nil, fmt.Errorf("failed to read private key file %s: %v", n.keyPath, err)
return nil, fmt.Errorf("failed to read private key file %s: %v", n.KeyPath, err)
}

signer, err := ssh.ParsePrivateKey(key)
Expand All @@ -653,7 +653,7 @@ func (n *Node) loadPrivateKey() (ssh.Signer, error) {
}

// Key is encrypted, prompt for passphrase
log.Printf("Enter passphrase for key '%s': ", n.keyPath)
log.Printf("Enter passphrase for key '%s': ", n.KeyPath)
passphrase, err := term.ReadPassword(int(syscall.Stdin))
log.Println()
if err != nil {
Expand Down
7 changes: 6 additions & 1 deletion internal/installer/secrets/datacenter.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ var DataCenterScopedSecretNames = []string{
files.SecretKubeConfig,
// ACME external account binding — paired with codesphere.certIssuer.acme.eabKeyId.
files.SecretAcmeEabMacKey,
// ACME external account binding for custom domains — paired with
// codesphere.certIssuer.acme.customDomainsEabKeyId.
files.SecretAcmeCustomDomainsEabMacKey,
// Only present in recovered vaults; keyed to a single cluster's nix cache.
files.SecretPrivNixSigningKey,
files.SecretPubNixSigningKey,
Expand Down Expand Up @@ -100,8 +103,10 @@ func clearDataCenterScopedConfig(config *files.RootConfig) {
config.Cluster.Certificates.CA.CertPem = ""
// Paired with cephSshPrivateKey, written by EnsureCephSSHKeys.
config.Ceph.CephAdmSSHKey.PublicKey = ""
// Paired with acmeEabMacKey, obtained per data center from the ACME CA.
// Paired with acmeEabMacKey / acmeCustomDomainsEabMacKey, obtained per data center from
// the ACME CA.
if config.Codesphere.CertIssuer != nil && config.Codesphere.CertIssuer.Acme != nil {
config.Codesphere.CertIssuer.Acme.EABKeyID = ""
config.Codesphere.CertIssuer.Acme.CustomDomainsEABKeyID = ""
}
}