Repository: skupperproject/skupper
Pull request #1781 (2024-11-11 20:32:58)

Nonkube certs paths refactored
This PR simplifies the directory trees used to store runtime certificates and by user provided certificates.
Certificate Authorities (issuers) are now stored under:

${HOME}/.local/share/skupper/namespaces/default/runtime/issuers/<ca-name>
${HOME}/.local/share/skupper/namespaces/default/input/issuers/<ca-name>

While client and server certificates are stored under (no more `client/`  or `server/` directory needed):

${HOME}/.local/share/skupper/namespaces/default/runtime/certs/<cert-name>
${HOME}/.local/share/skupper/namespaces/default/input/certs/<cert-name>

They need to be kept separate, as in case the namespace resources need to be reloaded, the CAs (issuers)
can be preserved, while the `runtime/certs` can be re-generated (or copied from `input/certs`).

It will also simplify the integration with #1761 .


Patch:
diff --git a/cmd/bootstrap/PROVIDED_CERTIFICATES.md b/cmd/bootstrap/PROVIDED_CERTIFICATES.md
index 60a0c35e..630d7eba 100644
--- a/cmd/bootstrap/PROVIDED_CERTIFICATES.md
+++ b/cmd/bootstrap/PROVIDED_CERTIFICATES.md
@@ -13,15 +13,14 @@ The certificates generated by Skupper are stored under the namespace home direct
 file system, using the following tree:
 
 ```shell
-runtime/certs/
-├── ca
-├── client
-└── server
+runtime/
+├── certs
+└── issuers
 ```
 
-As the CA `skupper-site-ca` is generated, it will be stored under the `runtime/certs/ca` path
-as a directory named `skupper-site-ca`. Inside a certificate folder, the following files are
-expected: `tls.key`, `tls.crt` and `ca.crt` (when dealing with a CA, `ca.crt` and `tls.crt`
+As the CA `skupper-site-ca` is generated, it will be stored under the `runtime/issuers` path
+as a directory named `skupper-site-ca`. Inside the issuers or certs folder, the following files are
+expected: `tls.key`, `tls.crt` and `ca.crt` (when dealing with a CA or issuer, `ca.crt` and `tls.crt`
 have the same content).
 
 If a `RouterAccess` is defined as part of the non kube site definition, Skupper will also
@@ -29,7 +28,7 @@ generate a server certificate that is valid for the provided `RouterAccess.spec.
 for each entry in the `RouterAccess.spec.subjectAlternativeName` list. The respective certificate
 is signed by the CA mentioned earlier (skupper-site-ca) and it will be named according to the
 provided `spec.tlsCredentials` field, or when it is omitted, the certificate will be named as the
-RouterAccess and stored as a directory under `runtime/certs/server`.
+RouterAccess and stored as a directory under `runtime/certs`.
 
 A set of static links are also created for the provided `RouterAccess.spec.bindHost` and for each
 entry in the `RouterAccess.spec.subjectAlternativeName` list as separate YAML files.
@@ -38,7 +37,7 @@ These static links are composed by a `Link` and a `Secret`, which is basically t
 signed by `skupper-site-ca`, that will be used by other sites to establish Skupper links. The client
 certificate is also named based on the RouterAccess `spec.tlsCredentials` field or, when it is omitted,
 the certificate will be named as the RouterAccess, prefixed with `client-` and stored under
-`runtime/certs/client`.
+`runtime/certs`.
 
 After a site bundle has been produced, it contains the whole site definition that can be installed
 at a remote location. Thus, all certificates and static links are already part of the bundle and no
@@ -49,9 +48,9 @@ new certificate is signed at the moment a bundle is installed.
 You can provide your own certificates to be used by Skupper for site linking.
 
 The provided certificates must be placed in a similar directory tree, as shown before,
-but its path under the namespace home is located at `input/certs` instead.
+but its path under the namespace home is located at `input/issuers` and `input/certs` instead.
 
-Certificates placed under this path will be used by Skupper primarily and
+Certificates placed under these paths will be used by Skupper primarily and
 all the other certificates expected by Skupper, will be generated when not provided. 
 
 Depending on your goals, some certificates should be supplied at certain phases,
@@ -108,12 +107,11 @@ certificates used for site linking, you can simply create the following structur
 the namespace home of your choice, for example:
 
 ```shell
-${HOME}/.local/share/skupper/namespaces/default/input/certs/
-└── ca
-    └── skupper-site-ca
-        ├── ca.crt
-        ├── tls.crt
-        └── tls.key
+${HOME}/.local/share/skupper/namespaces/default/input/issuers/
+└── skupper-site-ca
+    ├── ca.crt
+    ├── tls.crt
+    └── tls.key
 ```
 
 With that, if you bootstrap a site to run in the default namespace, the CA certificates above will be
@@ -138,16 +136,14 @@ must be provided under the namespace home of your choice, for example:
 
 ```shell
 ${HOME}/.local/share/skupper/namespaces/default/input/certs/
-├── client
-│   └── client-my-router-access
-│       ├── ca.crt
-│       ├── tls.crt
-│       └── tls.key
-└── server
-    └── my-router-access
-        ├── ca.crt
-        ├── tls.crt
-        └── tls.key
+├── client-my-router-access
+│   ├── ca.crt
+│   ├── tls.crt
+│   └── tls.key
+└── my-router-access
+    ├── ca.crt
+    ├── tls.crt
+    └── tls.key
 ```
 
 At bootstrap or bundle installation times, you should see a message saying that the
diff --git a/cmd/network-console-collector/internal/server/query.go b/cmd/network-console-collector/internal/server/query.go
index 8ae7f309..ea352b8a 100644
--- a/cmd/network-console-collector/internal/server/query.go
+++ b/cmd/network-console-collector/internal/server/query.go
@@ -181,6 +181,16 @@ func (m fieldIndex[T]) Compare(x, y T) int {
 	case reflect.Int64:
 		xx, yy := vx.Int(), vy.Int()
 		return int(xx - yy)
+	case reflect.Bool:
+		xx, yy := vx.Bool(), vy.Bool()
+		switch {
+		case xx == yy:
+			return 0
+		case xx && !yy:
+			return 1
+		default:
+			return -1
+		}
 	}
 	return 0
 }
diff --git a/internal/nonkube/bundle/install.sh.template b/internal/nonkube/bundle/install.sh.template
index f3f12cc1..ca36e1de 100644
--- a/internal/nonkube/bundle/install.sh.template
+++ b/internal/nonkube/bundle/install.sh.template
@@ -313,41 +313,33 @@ list_valid_certificates() {
     done
 }
 
-handle_provided_certificates() {
-    export USER_CERTIFICATES_PATH="${NAMESPACES_PATH}/${NAMESPACE}/input/certs"
-    [ ! -d "${USER_CERTIFICATES_PATH}" ] && return
-    cas=""
-    clients=""
-    servers=""
-    if [ -d "${USER_CERTIFICATES_PATH}/ca" ]; then
-        cas=$(list_valid_certificates "${USER_CERTIFICATES_PATH}/ca")
-    fi
-    if [ -d "${USER_CERTIFICATES_PATH}/client" ]; then
-        clients=$(list_valid_certificates "${USER_CERTIFICATES_PATH}/client")
-    fi
-    if [ -d "${USER_CERTIFICATES_PATH}/server" ]; then
-        servers=$(list_valid_certificates "${USER_CERTIFICATES_PATH}/server")
-    fi
-    if [ -z "${cas}" ] && [ -z "${clients}" ] && [ -z "${servers}" ]; then
+handle_provided_issuers() {
+    export USER_ISSUERS_PATH="${NAMESPACES_PATH}/${NAMESPACE}/input/issuers"
+    [ ! -d "${USER_ISSUERS_PATH}" ] && return
+    cas=$(list_valid_certificates "${USER_ISSUERS_PATH}")
+    if [ -z "${cas}" ]; then
         return
     fi
-    echo "User provided certificates found:"
+    echo "User provided issuers found:"
     if [ -n "${cas}" ]; then
-        echo "- CA certificates:"
         for ca in ${cas}; do
             echo "  - ${ca}"
         done
     fi
-    if [ -n "${clients}" ]; then
-        echo "- Client certificates:"
-        for client in ${clients}; do
-            echo "  - ${client}"
-        done
+    cp -r "${USER_ISSUERS_PATH}"/* "./${SOURCE_NAMESPACE}/runtime/issuers"
+}
+
+handle_provided_certificates() {
+    export USER_CERTIFICATES_PATH="${NAMESPACES_PATH}/${NAMESPACE}/input/certs"
+    [ ! -d "${USER_CERTIFICATES_PATH}" ] && return
+    certs=$(list_valid_certificates "${USER_CERTIFICATES_PATH}")
+    if [ -z "${certs}" ]; then
+        return
     fi
-    if [ -n "${servers}" ]; then
-        echo "- Server certificates:"
-        for server in ${servers}; do
-            echo "  - ${server}"
+    echo "User provided certificates found:"
+    if [ -n "${certs}" ]; then
+        for cert in ${certs}; do
+            echo "  - ${cert}"
         done
     fi
     cp -r "${USER_CERTIFICATES_PATH}"/* "./${SOURCE_NAMESPACE}/runtime/certs"
@@ -364,7 +356,7 @@ update_static_links() {
         ra_name=$(grep name: "${ra}" | grep -v '\- name:' | awk '{print $NF}' | sed 's/"//g')
         tls_credential=$(grep tlsCredentials: "${ra}" | awk '{print $NF}' | sed 's/"//g')
         bind_host=$(grep bindHost: "${ra}" | awk '{print $NF}' | sed 's/"//g')
-        client_cert_path="${USER_CERTIFICATES_PATH}/client/client-${tls_credential:-${ra_name}}"
+        client_cert_path="${USER_CERTIFICATES_PATH}/client-${tls_credential:-${ra_name}}"
 
         # no client certificate provided, skip
         [ ! -d "${client_cert_path}" ] && continue
@@ -409,7 +401,7 @@ generate_static_links_for_sans() {
         bind_host=$(grep bindHost: "${ra}" | awk '{print $NF}' | sed 's/"//g')
 
         # discovering SANS
-        server_cert="${DIR}/runtime/certs/server/${tls_credential:-${ra_name}}/tls.crt"
+        server_cert="${DIR}/runtime/certs/${tls_credential:-${ra_name}}/tls.crt"
         [ ! -f "${server_cert}" ] && continue
         subjects="$(openssl x509 -noout -ext subjectAltName -in "${server_cert}" |grep -v 'Subject Alternative Name:' | \
                     sed 's/ //g;s/,/\n/g' |  awk -F: '{if ($1 == "DNS" || $1 == "IPAddress") print $2}')"
@@ -436,6 +428,7 @@ main() {
         return
     fi
 
+    handle_provided_issuers
     handle_provided_certificates
 
     if ${DUMP_TOKENS}; then
diff --git a/pkg/nonkube/api/environment.go b/pkg/nonkube/api/environment.go
index 66951036..0b1fa705 100644
--- a/pkg/nonkube/api/environment.go
+++ b/pkg/nonkube/api/environment.go
@@ -12,22 +12,17 @@ type InternalPath string
 type InternalPathProvider func(namespace string, internalPath InternalPath) string
 
 const (
-	InputCertificatesBasePath   InternalPath = "input/certs"
-	InputCertificatesCaPath     InternalPath = "input/certs/ca"
-	InputCertificatesClientPath InternalPath = "input/certs/client"
-	InputCertificatesServerPath InternalPath = "input/certs/server"
-	InputSiteStatePath          InternalPath = "input/resources"
-	RouterConfigPath            InternalPath = "runtime/router"
-	CertificatesBasePath        InternalPath = "runtime/certs"
-	CertificatesCaPath          InternalPath = "runtime/certs/ca"
-	CertificatesClientPath      InternalPath = "runtime/certs/client"
-	CertificatesServerPath      InternalPath = "runtime/certs/server"
-	CertificatesLinkPath        InternalPath = "runtime/certs/link"
-	RuntimePath                 InternalPath = "runtime"
-	RuntimeSiteStatePath        InternalPath = "runtime/resources"
-	RuntimeTokenPath            InternalPath = "runtime/links"
-	LoadedSiteStatePath         InternalPath = "internal/snapshot"
-	ScriptsPath                 InternalPath = "internal/scripts"
+	InputIssuersPath      InternalPath = "input/issuers"
+	InputCertificatesPath InternalPath = "input/certs"
+	InputSiteStatePath    InternalPath = "input/resources"
+	RouterConfigPath      InternalPath = "runtime/router"
+	CertificatesPath      InternalPath = "runtime/certs"
+	IssuersPath           InternalPath = "runtime/issuers"
+	RuntimePath           InternalPath = "runtime"
+	RuntimeSiteStatePath  InternalPath = "runtime/resources"
+	RuntimeTokenPath      InternalPath = "runtime/links"
+	LoadedSiteStatePath   InternalPath = "internal/snapshot"
+	ScriptsPath           InternalPath = "internal/scripts"
 )
 
 type IdGetter func() int
diff --git a/pkg/nonkube/api/site_state.go b/pkg/nonkube/api/site_state.go
index 4d26b847..8a6522ce 100644
--- a/pkg/nonkube/api/site_state.go
+++ b/pkg/nonkube/api/site_state.go
@@ -239,7 +239,7 @@ func (s *SiteState) linkAccessMap() site.RouterAccessMap {
 func (s *SiteState) linkMap(sslProfileBasePath string) site.LinkMap {
 	linkMap := site.LinkMap{}
 	for name, link := range s.Links {
-		siteLink := site.NewLink(name, path.Join(sslProfileBasePath, string(CertificatesLinkPath)))
+		siteLink := site.NewLink(name, path.Join(sslProfileBasePath, string(CertificatesPath)))
 		link.SetConfigured(nil)
 		siteLink.Update(link)
 		linkMap[name] = siteLink
@@ -248,7 +248,7 @@ func (s *SiteState) linkMap(sslProfileBasePath string) site.LinkMap {
 }
 
 func (s *SiteState) bindings(sslProfileBasePath string) *site.Bindings {
-	b := site.NewBindings(path.Join(sslProfileBasePath, "certificates/bindings"))
+	b := site.NewBindings(path.Join(sslProfileBasePath, string(CertificatesPath)))
 	for name, connector := range s.Connectors {
 		connector.SetConfigured(nil)
 		_ = b.UpdateConnector(name, connector)
@@ -289,7 +289,7 @@ func (s *SiteState) ToRouterConfig(sslProfileBasePath string, platform string) q
 		routerConfig.SiteConfig.Platform = "{{.Platform}}"
 	}
 	// LinkAccess
-	s.linkAccessMap().DesiredConfig(nil, path.Join(sslProfileBasePath, string(CertificatesServerPath))).Apply(&routerConfig)
+	s.linkAccessMap().DesiredConfig(nil, path.Join(sslProfileBasePath, string(CertificatesPath))).Apply(&routerConfig)
 	// Link
 	s.linkMap(sslProfileBasePath).Apply(&routerConfig)
 	// Bindings
diff --git a/pkg/nonkube/bundle/site_state_renderer.go b/pkg/nonkube/bundle/site_state_renderer.go
index 37efe815..c3f8e728 100644
--- a/pkg/nonkube/bundle/site_state_renderer.go
+++ b/pkg/nonkube/bundle/site_state_renderer.go
@@ -117,7 +117,7 @@ func (s *SiteStateRenderer) prepareContainers() error {
 				Options:     []string{"z"},
 			},
 			{
-				Source:      path.Join("{{.NamespacesPath}}", "{{.Namespace}}", string(api.CertificatesBasePath)),
+				Source:      path.Join("{{.NamespacesPath}}", "{{.Namespace}}", string(api.CertificatesPath)),
 				Destination: "/etc/skupper-router/runtime/certs",
 				Options:     []string{"z"},
 			},
diff --git a/pkg/nonkube/common/fs_config_renderer.go b/pkg/nonkube/common/fs_config_renderer.go
index d0745792..2163ae62 100644
--- a/pkg/nonkube/common/fs_config_renderer.go
+++ b/pkg/nonkube/common/fs_config_renderer.go
@@ -22,13 +22,10 @@ import (
 var (
 	configurationDirectories = []api.InternalPath{
 		api.RouterConfigPath,
-		api.CertificatesCaPath,
-		api.CertificatesClientPath,
-		api.CertificatesServerPath,
-		api.CertificatesLinkPath,
-		api.InputCertificatesCaPath,
-		api.InputCertificatesClientPath,
-		api.InputCertificatesServerPath,
+		api.IssuersPath,
+		api.CertificatesPath,
+		api.InputIssuersPath,
+		api.InputCertificatesPath,
 		api.InputSiteStatePath,
 		api.LoadedSiteStatePath,
 		api.RuntimeSiteStatePath,
@@ -37,9 +34,7 @@ var (
 	}
 	reloadDirectories = []api.InternalPath{
 		api.RouterConfigPath,
-		api.CertificatesClientPath,
-		api.CertificatesServerPath,
-		api.CertificatesLinkPath,
+		api.CertificatesPath,
 		api.RuntimeSiteStatePath,
 		api.RuntimeTokenPath,
 		api.ScriptsPath,
@@ -52,6 +47,7 @@ type InputPathType string
 const (
 	InputPathResources InputPathType = "resources"
 	InputPathCerts     InputPathType = "certs"
+	InputPathIssuers   InputPathType = "issuers"
 )
 
 const (
@@ -384,7 +380,7 @@ func (c *FileSystemConfigurationRenderer) createTlsCertificates(siteState *api.S
 			secret = *userCaSecret
 			fmt.Printf("-> User provided CA found: %s\n", name)
 		}
-		caPath := path.Join(outputPath, string(api.CertificatesCaPath), name)
+		caPath := path.Join(outputPath, string(api.IssuersPath), name)
 		err = writeSecretFilesIgnore(caPath, &secret, ignoreExisting)
 		if err != nil {
 			return err
@@ -420,7 +416,7 @@ func (c *FileSystemConfigurationRenderer) createTlsCertificates(siteState *api.S
 			secret = *userSecret
 			fmt.Printf("-> User provided %s certificate found: %s\n", purpose, name)
 		}
-		certPath := path.Join(outputPath, string(api.CertificatesBasePath), purpose, name)
+		certPath := path.Join(outputPath, string(api.CertificatesPath), name)
 		err = writeSecretFiles(certPath, &secret)
 		if err != nil {
 			return err
@@ -433,7 +429,7 @@ func (c *FileSystemConfigurationRenderer) createTlsCertificates(siteState *api.S
 		if !ok {
 			return fmt.Errorf("secret %s not found", secretName)
 		}
-		certPath := path.Join(outputPath, string(api.CertificatesLinkPath), secretName+"-profile")
+		certPath := path.Join(outputPath, string(api.CertificatesPath), secretName+"-profile")
 		err = writeSecretFiles(certPath, secret)
 		if err != nil {
 			return err
@@ -484,12 +480,18 @@ func (c *FileSystemConfigurationRenderer) loadClientSecret(siteState *api.SiteSt
 }
 
 func (c *FileSystemConfigurationRenderer) loadCertAsSecret(siteState *api.SiteState, purpose, name string) (*corev1.Secret, error) {
-	outputPath := path.Join(c.GetOutputPath(siteState), string(api.CertificatesBasePath))
+	outputPath := path.Join(c.GetOutputPath(siteState), string(api.CertificatesPath))
+	if purpose == "ca" {
+		outputPath = path.Join(c.GetOutputPath(siteState), string(api.IssuersPath))
+	}
 	return c.loadCertAsSecretFrom(outputPath, siteState, purpose, name)
 }
 
 func (c *FileSystemConfigurationRenderer) loadUserCertAsSecret(siteState *api.SiteState, purpose, name string) (*corev1.Secret, error) {
 	userInputPath := path.Join(c.GetInputPath(siteState, InputPathCerts))
+	if purpose == "ca" {
+		userInputPath = path.Join(c.GetInputPath(siteState, InputPathIssuers))
+	}
 	secret, err := c.loadCertAsSecretFrom(userInputPath, siteState, purpose, name)
 	if err != nil {
 		if os.IsNotExist(err) {
@@ -514,7 +516,7 @@ func (c *FileSystemConfigurationRenderer) loadUserCertAsSecret(siteState *api.Si
 }
 
 func (c *FileSystemConfigurationRenderer) loadCertAsSecretFrom(basePath string, siteState *api.SiteState, purpose, name string) (*corev1.Secret, error) {
-	certPath := path.Join(basePath, purpose, name)
+	certPath := path.Join(basePath, name)
 	var secret *corev1.Secret
 	certDir, err := os.Open(certPath)
 	if err != nil {
diff --git a/pkg/nonkube/compat/site_state_renderer.go b/pkg/nonkube/compat/site_state_renderer.go
index cab9b754..f15bc349 100644
--- a/pkg/nonkube/compat/site_state_renderer.go
+++ b/pkg/nonkube/compat/site_state_renderer.go
@@ -217,7 +217,7 @@ func (s *SiteStateRenderer) prepareContainers() error {
 				Options:     []string{"z"},
 			},
 			{
-				Source:      path.Join(siteConfigPath, string(api.CertificatesBasePath)),
+				Source:      path.Join(siteConfigPath, string(api.CertificatesPath)),
 				Destination: "/etc/skupper-router/runtime/certs",
 				Options:     []string{"z"},
 			},


Test patch:
diff --git a/cmd/network-console-collector/internal/server/address_test.go b/cmd/network-console-collector/internal/server/address_test.go
index a4ae775d..19fe2804 100644
--- a/cmd/network-console-collector/internal/server/address_test.go
+++ b/cmd/network-console-collector/internal/server/address_test.go
@@ -23,6 +23,7 @@ func TestAddresses(t *testing.T) {
 	begin := time.Now()
 	testcases := []struct {
 		Records              []store.Entry
+		Parameters           map[string][]string
 		ExpectOK             bool
 		ExpectCount          int
 		ExpectTimeRangeCount int
@@ -62,6 +63,42 @@ func TestAddresses(t *testing.T) {
 				t.Error("expected to find address record for addr-1")
 			},
 		},
+		{
+			Records: wrapRecords(
+				collector.AddressRecord{ID: "addr-1", Name: "pizza", Protocol: "tcp", Start: begin},
+				collector.AddressRecord{ID: "addr-2", Name: "icecream", Protocol: "tcp", Start: begin},
+				collector.AddressRecord{ID: "addr-3", Name: "waffles", Protocol: "tcp", Start: begin},
+				vanflow.ConnectorRecord{BaseRecord: vanflow.NewBase("c1"), Address: ptrTo("pizza"), Protocol: ptrTo("tcp")},
+				vanflow.ListenerRecord{BaseRecord: vanflow.NewBase("l1"), Address: ptrTo("pizza"), Protocol: ptrTo("tcp")},
+			),
+			Parameters: map[string][]string{
+				"sortBy": {"isBound.asc"},
+			},
+			ExpectOK:    true,
+			ExpectCount: 3,
+			ExpectResults: func(t *testing.T, results []api.AddressRecord) {
+				assert.Equal(t, results[2].Identity, "addr-1", "Expected addr-1 to be last with sortBy isBound.asc")
+				assert.Equal(t, results[2].IsBound, true, "Expected addr-1 to be bound")
+			},
+		},
+		{
+			Records: wrapRecords(
+				collector.AddressRecord{ID: "addr-1", Name: "pizza", Protocol: "tcp", Start: begin},
+				collector.AddressRecord{ID: "addr-2", Name: "icecream", Protocol: "tcp", Start: begin},
+				collector.AddressRecord{ID: "addr-3", Name: "waffles", Protocol: "tcp", Start: begin},
+				vanflow.ConnectorRecord{BaseRecord: vanflow.NewBase("c1"), Address: ptrTo("pizza"), Protocol: ptrTo("tcp")},
+				vanflow.ListenerRecord{BaseRecord: vanflow.NewBase("l1"), Address: ptrTo("pizza"), Protocol: ptrTo("tcp")},
+			),
+			Parameters: map[string][]string{
+				"sortBy": {"isBound.desc"},
+			},
+			ExpectOK:    true,
+			ExpectCount: 3,
+			ExpectResults: func(t *testing.T, results []api.AddressRecord) {
+				assert.Equal(t, results[0].Identity, "addr-1", "Expected addr-1 to be first with sortBy isBound.asc")
+				assert.Equal(t, results[0].IsBound, true, "Expected addr-1 to be bound")
+			},
+		},
 	}
 
 	for _, tc := range testcases {
@@ -71,7 +108,7 @@ func TestAddresses(t *testing.T) {
 			for _, r := range tc.Records {
 				graph.(reset).Reindex(r.Record)
 			}
-			resp, err := c.AddressesWithResponse(context.TODO())
+			resp, err := c.AddressesWithResponse(context.TODO(), WithParameters(tc.Parameters))
 			assert.Check(t, err)
 			if tc.ExpectOK {
 				assert.Equal(t, resp.StatusCode(), 200)
diff --git a/pkg/nonkube/common/fs_config_renderer_test.go b/pkg/nonkube/common/fs_config_renderer_test.go
index 519d3ae4..e34d6c77 100644
--- a/pkg/nonkube/common/fs_config_renderer_test.go
+++ b/pkg/nonkube/common/fs_config_renderer_test.go
@@ -51,28 +51,28 @@ func testFileSystemConfigurationRendererRender(t *testing.T, addInputCertificate
 	}
 	expectedFiles := []string{
 		string(api.RouterConfigPath) + "/skrouterd.json",
-		string(api.CertificatesCaPath) + "/skupper-site-ca/tls.crt",
-		string(api.CertificatesCaPath) + "/skupper-site-ca/tls.key",
-		string(api.CertificatesCaPath) + "/skupper-service-ca/tls.crt",
-		string(api.CertificatesCaPath) + "/skupper-service-ca/tls.key",
-		string(api.CertificatesClientPath) + "/client-link-access-one/tls.crt",
-		string(api.CertificatesClientPath) + "/client-link-access-one/tls.key",
-		string(api.CertificatesClientPath) + "/client-link-access-one/ca.crt",
-		string(api.CertificatesServerPath) + "/link-access-one/tls.crt",
-		string(api.CertificatesServerPath) + "/link-access-one/tls.key",
-		string(api.CertificatesServerPath) + "/link-access-one/ca.crt",
-		string(api.CertificatesServerPath) + "/listener-one-credentials/tls.crt",
-		string(api.CertificatesServerPath) + "/listener-one-credentials/tls.key",
-		string(api.CertificatesServerPath) + "/listener-one-credentials/ca.crt",
-		string(api.CertificatesServerPath) + "/listener-two-credentials/tls.crt",
-		string(api.CertificatesServerPath) + "/listener-two-credentials/tls.key",
-		string(api.CertificatesServerPath) + "/listener-two-credentials/ca.crt",
-		string(api.CertificatesServerPath) + "/connector-one-credentials/tls.key",
-		string(api.CertificatesServerPath) + "/connector-one-credentials/ca.crt",
-		string(api.CertificatesServerPath) + "/connector-one-credentials/tls.crt",
-		string(api.CertificatesLinkPath) + "/link-one-profile/ca.crt",
-		string(api.CertificatesLinkPath) + "/link-one-profile/tls.crt",
-		string(api.CertificatesLinkPath) + "/link-one-profile/tls.key",
+		string(api.IssuersPath) + "/skupper-site-ca/tls.crt",
+		string(api.IssuersPath) + "/skupper-site-ca/tls.key",
+		string(api.IssuersPath) + "/skupper-service-ca/tls.crt",
+		string(api.IssuersPath) + "/skupper-service-ca/tls.key",
+		string(api.CertificatesPath) + "/client-link-access-one/tls.crt",
+		string(api.CertificatesPath) + "/client-link-access-one/tls.key",
+		string(api.CertificatesPath) + "/client-link-access-one/ca.crt",
+		string(api.CertificatesPath) + "/link-access-one/tls.crt",
+		string(api.CertificatesPath) + "/link-access-one/tls.key",
+		string(api.CertificatesPath) + "/link-access-one/ca.crt",
+		string(api.CertificatesPath) + "/listener-one-credentials/tls.crt",
+		string(api.CertificatesPath) + "/listener-one-credentials/tls.key",
+		string(api.CertificatesPath) + "/listener-one-credentials/ca.crt",
+		string(api.CertificatesPath) + "/listener-two-credentials/tls.crt",
+		string(api.CertificatesPath) + "/listener-two-credentials/tls.key",
+		string(api.CertificatesPath) + "/listener-two-credentials/ca.crt",
+		string(api.CertificatesPath) + "/connector-one-credentials/tls.key",
+		string(api.CertificatesPath) + "/connector-one-credentials/ca.crt",
+		string(api.CertificatesPath) + "/connector-one-credentials/tls.crt",
+		string(api.CertificatesPath) + "/link-one-profile/ca.crt",
+		string(api.CertificatesPath) + "/link-one-profile/tls.crt",
+		string(api.CertificatesPath) + "/link-one-profile/tls.key",
 		string(api.RuntimePath) + "/platform.yaml",
 		string(api.RuntimeTokenPath) + "/link-link-access-one-127.0.0.1.yaml",
 	}
@@ -95,12 +95,12 @@ func testFileSystemConfigurationRendererRender(t *testing.T, addInputCertificate
 }
 
 func compareCertificates(t *testing.T, customOutputPath string) {
-	caPath := path.Join(customOutputPath, string(api.CertificatesCaPath), "skupper-site-ca")
-	serverPath := path.Join(customOutputPath, string(api.CertificatesServerPath), "link-access-one")
-	clientPath := path.Join(customOutputPath, string(api.CertificatesClientPath), "client-link-access-one")
-	inputCaPath := path.Join(customOutputPath, string(api.InputCertificatesCaPath), "skupper-site-ca")
-	inputServerPath := path.Join(customOutputPath, string(api.InputCertificatesServerPath), "link-access-one")
-	inputClientPath := path.Join(customOutputPath, string(api.InputCertificatesClientPath), "client-link-access-one")
+	caPath := path.Join(customOutputPath, string(api.IssuersPath), "skupper-site-ca")
+	serverPath := path.Join(customOutputPath, string(api.CertificatesPath), "link-access-one")
+	clientPath := path.Join(customOutputPath, string(api.CertificatesPath), "client-link-access-one")
+	inputCaPath := path.Join(customOutputPath, string(api.InputIssuersPath), "skupper-site-ca")
+	inputServerPath := path.Join(customOutputPath, string(api.InputCertificatesPath), "link-access-one")
+	inputClientPath := path.Join(customOutputPath, string(api.InputCertificatesPath), "client-link-access-one")
 	pathsToCompare := map[string]string{
 		caPath:     inputCaPath,
 		serverPath: inputServerPath,
@@ -128,9 +128,9 @@ func createInputCertificates(t *testing.T, customOutputPath string) {
 	client := certs.GenerateSecret("fake-client-cert", "fake-client-cert", "", &ca)
 
 	// paths for each provided certificate
-	caPath := path.Join(customOutputPath, "namespaces/default", string(api.InputCertificatesCaPath), "skupper-site-ca")
-	serverPath := path.Join(customOutputPath, "namespaces/default", string(api.InputCertificatesServerPath), "link-access-one")
-	clientPath := path.Join(customOutputPath, "namespaces/default", string(api.InputCertificatesClientPath), "client-link-access-one")
+	caPath := path.Join(customOutputPath, "namespaces/default", string(api.InputIssuersPath), "skupper-site-ca")
+	serverPath := path.Join(customOutputPath, "namespaces/default", string(api.InputCertificatesPath), "link-access-one")
+	clientPath := path.Join(customOutputPath, "namespaces/default", string(api.InputCertificatesPath), "client-link-access-one")
 	certsMap := map[string]corev1.Secret{
 		caPath:     ca,
 		serverPath: server,