Skip to content
Closed
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
7 changes: 6 additions & 1 deletion config/_default/hugo.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,12 @@ menu:
pre: <i class='fas fa-briefcase'></i>
weight: 16

- name: Resources
url: /project/resources/
pre: <i class="fa-solid fa-circle-info"></i>
weight: 17

- name: Project
url: /project/
pre: <i class='fas fa-flask'></i>
weight: 17
weight: 18
108 changes: 108 additions & 0 deletions content/en/docs/operating/admission-policies.md
Original file line number Diff line number Diff line change
Expand Up @@ -747,6 +747,114 @@ You may consider the upstream policies, depending on your needs:
* [QoS Guaranteed](https://kyverno.io/policies/other/require-qos-guaranteed/require-qos-guaranteed/)


## Certificates

### Deny ClusterIssuer in Certificates

Often when working in multi-tenant environments, you want to ensure that tenants are not using `ClusterIssuers` to issue certificates, but rather use namespaced `Issuers` within their own namespace. This policy enforces that `cert-manager.io/v1/Certificate` resources do not reference `ClusterIssuers` and that the `Issuer` referenced is in the same namespace as the `Certificate`.

{{% tabpane lang="yaml" %}}
{{% tab header="**Engines**:" disabled=true /%}}
{{< tab header="Kyverno" >}}
---
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: certificates-only-local-issuer
spec:
validationFailureAction: Enforce
background: true
rules:
- name: deny-clusterissuer-in-certificates
match:
any:
- resources:
kinds:
- cert-manager.io/v1/Certificate
namespaceSelector:
matchExpressions:
- key: capsule.clastix.io/tenant
operator: Exists
validate:
message: "Certificates must not reference ClusterIssuers; use a namespaced Issuer in the same namespace."
deny:
conditions:
any:
- key: "{{ request.object.spec.issuerRef.kind || 'Issuer' }}"
operator: Equals
value: "ClusterIssuer"

- name: deny-cross-namespace-issuerref-in-certificates
match:
any:
- resources:
kinds:
- cert-manager.io/v1/Certificate
validate:
message: "Certificates must reference an Issuer in the same namespace (spec.issuerRef.namespace must be empty or equal to the Certificate namespace)."
deny:
conditions:
any:
# If issuerRef.namespace is set and differs from the Certificate namespace -> deny
- key: "{{request.object.spec.issuerRef.namespace || '' }}"
operator: NotEquals
value: ""
# AND also not equal to request namespace
- key: "{{ request.object.spec.issuerRef.namespace || request.namespace }}"
operator: NotEquals
value: "{{ request.namespace }}"{{< /tab >}}
{{% /tabpane %}}

### Deny ClusterIssuer in Gateways

Deny to usage of ClusterIssuers in Gateways by checking for the `cert-manager.io/cluster-issuer` annotation. This ensures that tenants use namespaced issuer mechanisms instead.

This requires extra permissions to allow Kyverno to read Gateway resources:

```yaml
admissionController:
rbac:
clusterRole:
extraResources:
- apiGroups: ["gateway.networking.k8s.io"]
resources: ["*"]
verbs: ["get", "list", "watch"]
```

{{% tabpane lang="yaml" %}}
{{% tab header="**Engines**:" disabled=true /%}}
{{< tab header="Kyverno" >}}
---
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: gateways-deny-cluster-issuer-annotation
spec:
validationFailureAction: Enforce
background: false
rules:
- name: deny-cert-manager-cluster-issuer-annotation
match:
any:
- resources:
kinds:
- gateway.networking.k8s.io/v1/Gateway
namespaceSelector:
matchExpressions:
- key: capsule.clastix.io/tenant
operator: Exists
validate:
message: "Gateways must not use cert-manager.io/cluster-issuer; use namespaced issuer mechanisms instead."
deny:
conditions:
any:
- key: "{{ request.object.metadata.annotations.\"cert-manager.io/cluster-issuer\" || '' }}"
operator: NotEquals
value: ""{{< /tab >}}
{{% /tabpane %}}



## Images

### Allowed Registries
Expand Down
34 changes: 28 additions & 6 deletions content/en/docs/operating/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,32 +30,56 @@ In Capsule, we introduce a new persona called the `Tenant Owner`. The goal is to

### Capsule Administrators

[Configure Capsule Administrators](/docs/operating/setup/configuration/#administrators). The ClusterRoles assigned to Administrators can be configured in the [CapsuleConfiguration](/docs/operating/setup/configuration/#rbac) as well.

They are promoted to [Tenant-Owners](#tenant-owners) for all available tenants. Effectively granting them the ability to manage all namespaces within the cluster, across all tenants.

**Note**: Granting Capsule Administrator rights should be done with caution, as it provides extensive control over the cluster's multi-tenant environment. **When granting Capsule Administrator rights, the entity gets the privileges to create any namespace (also not part of capsule tenants) and the privileges to delete any tenant namespaces.**

Capsule Administrators can:

- Create and manage [namespaces via labels in any tenant](/docs/tenants/namespaces/#label).
- Create namespaces outside of tenants.
- Delete namespaces in any tenant.

Administrators come in handy in bootstrap scenarios or GitOps scenarios where certain users/serviceaccounts need to be able to manage namespaces for all tenants.

[Configure Capsule Administrators](/docs/operating/setup/configuration/#administrators)

### Capsule Users

[Configure Capsule Users](/docs/operating/setup/configuration/#users)

Any entity which needs to interact with tenants and their namespaces must be defined as a **Capsule User**. This is where the flexibility of Capsule comes into play. You can define users or groups as Capsule Users, allowing them to create and manage namespaces within any tenant they have access to. If they are not defined as Capsule Users, any interactions will be ignored by Capsule. Often a best practice is to define a single group which identifies all your tenant users. This way you can have one generic group for all your users and then use additional groups to separate responsibilities (e.g. administrators vs normal users).

**Only one entry is needed to identify a Capsule User. This is only important for Namespace Admission.**.

![Capsule Users Admission](/images/content/capsule-users-admission.drawio.png)

[Configure Capsule Users](/docs/operating/setup/configuration/#users)
You can always verify the effective Capsule Users by checking the Configuration Status. As this is variable with [Tenant Owners](#tenant-owners), the status will always show the effective users:

```bash
kubectl get capsuleconfiguration default -o jsonpath='{.status.users}' | jq

[
{
"kind": "Group",
"name": "oidc:kubernetes:admin"
},
{
"kind": "Group",
"name": "projectcapsule.dev"
},
{
"kind": "User",
"name": "test-user"
}
]
```

### Tenant Owners

**Every Tenant Owner must be a [Capsule User](#capsule-users)**
[Configure Tenant Owners](/docs/tenants/permissions/#ownership)

**Every Tenant Owner must be a [Capsule User](#capsule-users). By using the [TenantOwner CRD](/docs/tenants/permissions/#tenant-owners) this is automatically handeled.**


They manage the namespaces within their tenants and perform administrative tasks confined to their tenant boundaries. This delegation allows teams to operate more autonomously while still adhering to organizational policies. Tenant Owners can be used to shift reposnsability of one tenant towards this user group. promoting them to the SPOC of all namespaces within the tenant.
Expand All @@ -67,8 +91,6 @@ Tenant Owners can:

Capsule provides robust tools to strictly enforce tenant boundaries, ensuring that each tenant operates within its defined limits. This separation of duties promotes both security and efficient resource management.

[Configure Tenant Owners](/docs/tenants/permissions/#ownership)

## Layouts

Let's dicuss different Tenant Layouts which could be used . These are just approaches we have seen, however you might also find a combination of these which fits your use-case.
Expand Down
4 changes: 2 additions & 2 deletions content/en/docs/operating/best-practices/_index.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: Best Practices
weight: 2
description: Best Practices when running Capsule in production
description: Best Practices when running Capsule in production
---


Expand Down Expand Up @@ -30,7 +30,7 @@ Instead, a centralized secrets management system should be established — such
To integrate these external secret stores with Kubernetes, the [External Secrets Operator (ESO)](https://external-secrets.io/latest/) is a recommended solution. It automatically syncs defined secrets from external sources as Kubernetes secrets, and supports dynamic rotation, access control, and auditing.

If no external secret store is available, there should at least be a secure way to store sensitive data in Git.
In our ecosystem, we provide a solution based on SOPS (Secrets OPerationS) for this use case.
In our ecosystem, we provide a solution based on SOPS (Secrets OPerationS) for this use case; called the [sops-operator](https://github.com/peak-scale/sops-operator).

[👉 Demonstration](https://killercoda.com/peakscale/course/playgrounds/sops-secrets)

Loading
Loading