Skip to content
Closed

Certs #283

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
9 changes: 9 additions & 0 deletions input/kube-cli/site-linking.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,3 +125,12 @@ To link sites, you create a `link` resource YAML file on one site and apply that

There are many options to consider when linking sites using the CLI, see [CLI Reference][cli-ref], including *frequently used* options.

## Using custom certificates

For information about linking sites using custom certificates instead of the default Skupper-generated certificates, see [Linking sites using custom certificates][custom-certs-yaml].

**📌 NOTE**
The YAML approach is recommended for custom certificate workflows as it provides more control over certificate management and integration with existing PKI infrastructure.

[custom-certs-yaml]: ../kube-yaml/site-linking.html#kube-link-custom-certs-yaml

200 changes: 199 additions & 1 deletion input/kube-yaml/site-linking.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,4 +113,202 @@ 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
```
```

<a id="kube-link-custom-certs-yaml"></a>
## Linking sites using `Link` resources and custom certificates

By default, the Skupper V2 controller generates internal Certificate Authorities (CAs) and self-signed certificates.
For example, it creates certificates to authenticate incoming Skupper links from external Skupper sites.

The CA and server certificate used for this authentication are named `skupper-site-ca` (default signing `Certificate` resource for a Skupper Site) and `skupper-site-server`, respectively.

The server certificate (`skupper-site-server`) issued by the self-signed CA `skupper-site-ca` is issued for the public hostname or IP address associated with the `skupper-router` service. This depends on the ingress method used, for example an OpenShift Route or a Kubernetes LoadBalancer Service.

Although this behavior is automatic, you can override it by providing your own custom server certificate or even your own CA.

**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 using the kubectl method to generate the `Link` resource
* `skupper` CLI installed if using the CLI method 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
```

Make sure the certificate specified in `tls.crt` is valid for the hostname or IP address that will be referenced in your `Link` resource. In this example, consider the server certificate as being valid for the hostname: `skupper.public.host`.

2. Determine the hostname or IP address for the listening site.

In case your Skupper Site is already created, you can find the appropriate Hostname or IP by looking at the Endpoint element of a Site status:
```shell
kubectl get site <site-name> -o json | jq -r '.status.endpoints[0].host'
```
And you will see something like:
```
skupper.public.host
```

**_Note:_** Make sure you specify the appropriate namespace when running the commands from this example.

Again, if your Site has already been created, Skupper will recognize your custom secret. You can confirm this with the following command:
```shell
kubectl get certificate skupper-site-server -o json | jq -r '.status.conditions[].message'
```
You should see a message like:
```
Secret exists but is not controlled by skupper
```
This confirms that Skupper has detected your certificate but is not managing it.

3. On the listening site, create client credentials for the connecting site.

Once your Skupper site is configured to use your custom server certificate, you can create a `Link` resource and an associated client `Secret`. If the `skupper-site-ca` signing `Certificate` resource has been provided, you can create a Certificate resource and Skupper will generate the client Secret to be used, but it is only possible if the signing `Certificate` resource has been provided, otherwise, you have to provide the client Secret yourself.

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
```
You should see an output like:
```
certificate.skupper.io/skupper-link created
```
Then a Secret named `skupper-link` should be created and it can be used to compose your link file.

Save the generated secret to a local file for use in the next step:
```shell
kubectl get secret skupper-link -o yaml | yq eval -o=yaml '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.

Now, regardless of whether Skupper generated your client certificate Secret or if you generated it yourself, to define a Skupper Link, that can be shared with remote sites allowing them to initiate a secure outgoing link to your site, you will need to write a YAML file that contains both documents: a `Link`, and a Client `Secret`.

You can generate a Link using `kubectl` or manually (as long as retrieve the list of endpoints). Here are these two methods:

**Option A: Using kubectl with jq and yq**

The following command uses `kubectl`, `yq`, `jq` and `tee` to extract and compose the information needed to define a Link, storing the Link document into `skupper-link.yaml`:
```shell
endpoints=$(kubectl get site <site-name> -o json | jq -r '.status.endpoints')
cat << EOF | yq -y --argjson endpoints "${endpoints}" '.spec.endpoints = $endpoints' | tee skupper-link.yaml
apiVersion: skupper.io/v2alpha1
kind: Link
metadata:
name: skupper-link
spec:
cost: 1
tlsCredentials: skupper-link
EOF
```
Then you need to combine it in a YAML file that contains both the Link above and the client Secret. Suppose your client Secret is stored in a file named `client-secret.yaml`, you could run:
```shell
echo "---" >> skupper-link.yaml
cat client-secret.yaml >> skupper-link.yaml
```

**Option B: Manual generation**

You can retrieve the list of endpoints from the Site definition, using:
```shell
kubectl get site <site-name> -o yaml | yq -y .status.endpoints
```
The command above uses both `kubectl` and `yq`. And the output should be something like:
```yaml
- group: skupper-router
host: skupper.public.host
name: inter-router
port: '55671'
- group: skupper-router
host: skupper.public.host
name: edge
port: '45671'
```

Then you can create your Link file with:
```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 # The hostname or IP specified in your custom certificate
name: inter-router
port: '55671'
- group: skupper-router
host: skupper.public.host # The same hostname or IP
name: edge
port: '45671'
---
apiVersion: v1
kind: Secret
metadata:
name: skupper-link
data:
ca.crt: LS0tLS1C...redacted # The trusted CA certificate
tls.crt: LS0tLS1C...redacted # The client certificate
tls.key: LS0tLS1C...redacted # The corresponding private key
```

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 skupper-link.yaml
kubectl get link
NAME STATUS REMOTE SITE MESSAGE
skupper-link Ready my-site OK
```
18 changes: 18 additions & 0 deletions input/overview/security.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.