diff --git a/input/kube-yaml/site-linking.md b/input/kube-yaml/site-linking.md index 698abe0..748b356 100644 --- a/input/kube-yaml/site-linking.md +++ b/input/kube-yaml/site-linking.md @@ -113,4 +113,160 @@ A connecting site redeems this token for a `Link` resource to establish a link t kubectl get link NAME STATUS REMOTE SITE MESSAGE token-to-west Ready my-site OK - ``` \ No newline at end of file + ``` + + +## Linking sites using `Link` resources and custom certificates + +By default, the site CA `skupper-site-ca` issues the `skupper-site-server` certificate that authenticates incoming links. +If you need to use your own server certificate, you can provide custom TLS credentials and then create a `Link` resource for remote sites. + +**Prerequisites** + +* Two sites +* The listening site must have `link-access` enabled +* A server certificate and key for the listening site +* `jq` and `yq` installed if you want to use the command examples to generate the `Link` resource + +To link sites using custom certificates, you provide a custom server certificate on the listening site and create a `Link` resource on the connecting site that references matching client credentials. + +**Procedure** + +1. On the listening site, create a secret named `skupper-site-server`, for example: + ```yaml + apiVersion: v1 + kind: Secret + metadata: + name: skupper-site-server + data: + ca.crt: LS0tLS1C...redacted + tls.crt: LS0tLS1C...redacted + tls.key: LS0tLS1C...redacted + ``` + Apply the secret: + ```shell + kubectl apply -f skupper-site-server.yaml + ``` + The certificate specified in `tls.crt` must be valid for the hostname or IP address that connecting sites use to connect to this site. + +2. Determine the hostname or IP address for the listening site: + ```shell + kubectl get site -o json | jq -r '.status.endpoints[0].host' + ``` + For example, the output might be: + ``` + skupper.public.host + ``` + If the site is already running, you can confirm that Skupper detected the custom server certificate: + ```shell + kubectl get certificate skupper-site-server -o json | jq -r '.status.conditions[].message' + ``` + The output includes a message similar to: + ``` + Secret exists but is not controlled by skupper + ``` + +3. On the listening site, create client credentials for the connecting site. + + If the listening site provides the `skupper-site-ca` issuer, create a `Certificate` resource so that Skupper generates a client secret named `skupper-link`: + ```yaml + apiVersion: skupper.io/v2alpha1 + kind: Certificate + metadata: + name: skupper-link + spec: + ca: skupper-site-ca + client: true + subject: skupper.public.host + ``` + Apply the resource: + ```shell + kubectl apply -f skupper-link-certificate.yaml + ``` + Save the generated secret to a local file for use in the next step: + ```shell + kubectl get secret skupper-link -o yaml | yq -y 'del(.metadata.namespace, .metadata.creationTimestamp, .metadata.resourceVersion, .metadata.uid, .metadata.managedFields)' > client-secret.yaml + ``` + + If you are providing the client certificate yourself, create a secret named `skupper-link`, for example: + ```yaml + apiVersion: v1 + kind: Secret + metadata: + name: skupper-link + data: + ca.crt: LS0tLS1C...redacted + tls.crt: LS0tLS1C...redacted + tls.key: LS0tLS1C...redacted + ``` + Save this resource locally as `client-secret.yaml` if you want to combine it with a `Link` resource in a single file. + +4. On the listening site, create a `Link` resource YAML file. + + To generate the `Link` resource using `kubectl`, `jq`, and `yq`, retrieve the site endpoints and write the YAML file: + ```shell + endpoints="$(kubectl get site -o json | jq -c '.status.endpoints')" + cat < west-link.yaml + apiVersion: skupper.io/v2alpha1 + kind: Link + metadata: + name: skupper-link + spec: + cost: 1 + tlsCredentials: skupper-link + EOF + ``` + If you created a local client secret file, combine it with the `Link` resource: + ```shell + printf '%s\n' '---' >> west-link.yaml + cat client-secret.yaml >> west-link.yaml + ``` + + To create the YAML manually, first inspect the endpoints: + ```shell + kubectl get site -o yaml | yq -y '.status.endpoints' + ``` + Then create a file that contains both the `Link` resource and the client `Secret`, for example: + ```yaml + --- + apiVersion: skupper.io/v2alpha1 + kind: Link + metadata: + name: skupper-link + spec: + cost: 1 + tlsCredentials: skupper-link + endpoints: + - group: skupper-router + host: skupper.public.host + name: inter-router + port: "55671" + - group: skupper-router + host: skupper.public.host + name: edge + port: "45671" + --- + apiVersion: v1 + kind: Secret + metadata: + name: skupper-link + data: + ca.crt: LS0tLS1C...redacted + tls.crt: LS0tLS1C...redacted + tls.key: LS0tLS1C...redacted + ``` + +5. Securely transfer the `Link` resource YAML file to the context of the connecting site. + If you have both sites available from your terminal session, this step is not required. + + **📌 NOTE** + Access to this file provides access to the application network. + Protect it appropriately. + +6. On the connecting site, apply the YAML file and check status: + ```shell + kubectl apply -f west-link.yaml + kubectl get link + NAME STATUS REMOTE SITE MESSAGE + skupper-link Ready my-site OK + ``` diff --git a/input/overview/security.md b/input/overview/security.md index 740e793..737af5f 100644 --- a/input/overview/security.md +++ b/input/overview/security.md @@ -22,3 +22,21 @@ Each router is uniquely identified by its own certificate. This means that the Skupper network is isolated from external access, preventing security risks such as lateral attacks, malware infestations, and data exfiltration. +**Certificates and trust between sites** + +On Kubernetes, each site has its own certificate authority for inter-site communication. +By default, Skupper generates the certificates needed to identify the router and to authenticate incoming and outgoing links. + +When two sites are linked, each router verifies the certificate presented by the remote router and checks that it is signed by a trusted CA. +This mutual TLS exchange ensures that only sites with valid credentials can join the application network. + +If your environment requires certificates issued by your own PKI, you can replace the default server certificate that a site uses for incoming links and provide matching client credentials for connecting sites. +This allows you to keep Skupper's mutual TLS model while aligning certificate management with your organization's security requirements. + +**Service level TLS** + +Skupper always encrypts traffic between sites. +This protects traffic carried across the application network, even when workloads run in different clusters or clouds. + +This inter-site encryption is separate from any TLS configuration used by your application services. +If a backend service also requires TLS, you can configure listener and connector resources with appropriate credentials for the application side of the connection.