Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nonkube certs paths refactored #1781

Merged
merged 2 commits into from
Nov 18, 2024
Merged
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
50 changes: 23 additions & 27 deletions cmd/bootstrap/PROVIDED_CERTIFICATES.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,22 @@ 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
generate a server certificate that is valid for the provided `RouterAccess.spec.bindHost` and
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.
Expand All @@ -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
Expand All @@ -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,
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down
51 changes: 22 additions & 29 deletions internal/nonkube/bundle/install.sh.template
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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
Expand Down Expand Up @@ -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}')"
Expand All @@ -436,6 +428,7 @@ main() {
return
fi

handle_provided_issuers
handle_provided_certificates

if ${DUMP_TOKENS}; then
Expand Down
27 changes: 11 additions & 16 deletions pkg/nonkube/api/environment.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 3 additions & 3 deletions pkg/nonkube/api/site_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion pkg/nonkube/bundle/site_state_renderer.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"},
},
Expand Down
32 changes: 17 additions & 15 deletions pkg/nonkube/common/fs_config_renderer.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -37,9 +34,7 @@ var (
}
reloadDirectories = []api.InternalPath{
api.RouterConfigPath,
api.CertificatesClientPath,
api.CertificatesServerPath,
api.CertificatesLinkPath,
api.CertificatesPath,
api.RuntimeSiteStatePath,
api.RuntimeTokenPath,
api.ScriptsPath,
Expand All @@ -52,6 +47,7 @@ type InputPathType string
const (
InputPathResources InputPathType = "resources"
InputPathCerts InputPathType = "certs"
InputPathIssuers InputPathType = "issuers"
)

const (
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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) {
Expand All @@ -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 {
Expand Down
Loading