This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

Getting started

Find out how Greenhouse can help your organization and how to get started

1 - Core Concepts

Overview of some core concepts of Greenhouse
FeatureDescriptionAPIUIComments
OrganizationsOrganizations are the top-level entities in Greenhouse.🟢🟢
TeamsTeams are used to manage access and ownership of resources in Greenhouse.🟢🟡Read-only access to Teams via the UI
ClustersClusters represent a Kubernetes cluster that is managed by Greenhouse.🟡🟡Limited modification of Clusters via UI, CLI for KubeConfig registry planned.
Plugin Definitions & PluginsPlugins are software components that extend and integrate with Greenhouse .🟡🟡Read-only access via UI, a native Plugin Catalog is planned.

1.1 - Organizations

What are Organizations?

Organizations are the top-level entities in Greenhouse. Each Organization gets a dedicated Namespace, that contains all resources bound to the Organization. Greenhouse expects an Organization to provide its own Identity Provider and currently supports OIDC Identity Providers. Greenhouse also supports SCIM for syncing users and groups from an Identity Provider.

See Creating an Organization for more details.

Organization Namespace and Permissions

The Organization’s Namespace in the Greenhouse cluster contains all resources bound to the Organization. This Namespace is automatically provisioned when a new Organization is created and shares the Organization’s name. Once the Namespace is created, Greenhouse will automatically seed RBAC Roles and ClusterRoles for the Organization. These are used to grant permissions for the Organization’s resources to Teams.

  • The Administrators of an Organization are specified via a identity provider (IDP) group during the creation of the Organization. Greenhouse automatically creates a Team called <org-name>-admin. This Team is also a support group and all alerts created by the Greenhouse controller are routed to this admin Team, if no other ownership is provided. See operational processes and ownership for details.
  • The Administrators for Plugins and Clusters need to be defined by the Organization Admins via RoleBindings for the seeded Roles role:<org-name>:cluster-admin and role:<org-name>:plugin-admin.
  • All authenticated users are considered members of the Organization and are granted the organization:<org-name> Role.

See Working with Organizations for details on the seeded Roles and ClusterRoles.

OIDC

Each Organization must specify the OIDC configuration for the Organization’s IDP. This configuration is used together with DEXIDP to authenticate users in the Organization.

SCIM

Each Organization can specify SCIM credentials which are used to syncronize users and groups from an Identity Provider. This makes it possible to view the members of a Team in the Greenhouse dashboard.

Next Steps

1.2 - Teams

What are Teams?

Teams in a Greenhouse Organization are used to group users by group claims on the token provided by the upstream identity provider (IdP).

This can be used, for example, for

The Greenhouse UI is showing the members of a Team.

Team RBAC

TeamRoles and TeamRoleBindings provide a mechanism to control the permissions of Teams to onboarded Clusters of an Organization.

Team role-based access control (RBAC) wraps the concept of Kubernetes RBAC in TeamRoles and TeamRoleBindings . TeamRoles are used to define a set of RBAC permissions. These permissions can be granted to Teams with TeamRoleBindings . A TeamRoleBinding refers to a Team, a TeamRole , Cluster(s) and optional Namespaces. Depending on the latter, Greenhouse will create the appropriate rbacv1 resources on the targeted cluster(s) in either Cluster or Namespace scope. More information about how this can be configured is mentioned in this user guide.

Example of a TeamRoleBinding for a observability-admin which grants the cluster-admin TeamRole on the observability Cluster in the logs and metrics Namespaces. The TeamRoleBinding contains a list of Namespaces and a ClusterSelector to select the cluster(s) to target. Setting the .spec.namespaces field decides whether the created RBAC resources will be namespace-scoped or cluster-scoped.

apiVersion: greenhouse.sap/v1alpha2
kind: TeamRoleBinding
metadata:
  name: observability-admin
spec:
  teamRoleRef: cluster-admin
  teamRefs:
    - observability
  clusterSelector:
    clusterName: observability
  namespaces:
    - logs
    - metrics
flowchart TB subgraph "Greenhouse" subgraph "Organization" team[Team 'observability'] teamRole[TeamRole 'cluster-admin'] clusterA[Cluster 'observability'] trb[TeamRoleBinding 'observability-admin'] end end subgraph "Cluster 'observability'" subgraph "logs" clusterARoleBinding1[RoleBinding 'greenhouse:observability-admin'] end subgraph "metrics" clusterARoleBinding2[RoleBinding 'greenhouse:observability-admin'] end clusterAClusterRole[ClusterRole 'greenhouse:cluster-admin'] end team -.- trb teamRole -.- trb clusterA -."select by label".- trb trb --"creates"--> clusterARoleBinding1 trb --"creates"--> clusterARoleBinding2 trb --"creates"--> clusterAClusterRole clusterARoleBinding1 -.-> clusterAClusterRole clusterARoleBinding2 -.-> clusterAClusterRole

Support Groups

Support Groups in Greenhouse are a subset of Teams in an Organization. These Teams are used to identify response groups for operational tasks and to prefilter UI content.

Since a user can be part of many Teams the expectation is that they are only part of one Support Group.

To identify a Team as a Support Group in Greenhouse it needs to be labeled with greenhouse.sap/support-group: "true".

Support Groups are also used by the Authorization Webhook to add support-group-scoped access checks. When the webhook is consulted, it verifies access to Greenhouse resources based on the greenhouse.sap/owned-by label on resources, but RBAC may still allow cross-team access.

For a step-by-step guide on labelling resources and using the team ServiceAccount for automation, see Managing resources as a Team.

1.3 - Clusters

What are Clusters?

In the context of Greenhouse a Cluster represents a Kubernetes cluster that is onboarded to Greenhouse. Onboarded in this context means that Greenhouse can handle the management of role-based access control (RBAC) and the provisioning of operating tools (e.g. logging, monitoring, ingress etc.). The Greenhouse dashboard provides an overview of all onboarded clusters. Throughout Greenhouse the reference to a Cluster is used to target it for configuration and deployments.

Cluster access

During the initial onboarding of a cluster, Greenhouse will create a dedicated ServiceAccount inside the onboarded cluster. This ServiceAccount’s token is rotated automatically by Greenhouse.

Cluster registry (coming soon)

Once a Cluster is onboarded to Greenhouse a ClusterKubeConfig is generated for the Cluster based on the OIDC configuration of the Organization. This enables members of an Organization to access the fleet of onboarded Clusters via the common Identity Provider. on the respective Clusters can be managed via Greenhouse Team RBAC.

In order to make it convenient to use these ClusterKubeConfigs and to easily switch between multiple context locally there will be a CLI provided by Greenhouse.

1.4 - PluginDefinitions, Plugins and PluginPresets

What are PluginDefinitions and Plugins?

PluginDefinitons and Plugins are the Greenhouse way to extend the core functionality with domain specific features. PluginDefinitions, as the name suggests, are the definition of a Plugin, whereas a Plugin is a concrete instance of a PluginDefinition that is deployed to a Cluster.

The PluginDefinitions are shared between all Organizations in Greenhouse. A PluginDefinition can include a frontend, that is displayed in the Greenhouse dashboard and/or a backend component. The frontend is expected to be a standalone microfrontend created with the Juno framework. The backend components of a PluginDefinition are packaged as a Helm Chart and provide sane and opinionated default values. This allows Greenhouse to package and distribute tools such as Prometheus with a sensible default configuration, as well as giving the user a list of configurable values.

A Plugin is used to deploy the Helm Chart referenced in a PluginDefinition to a Cluster. The Plugin can be considered as an instance of a PluginDefinition, this instance specifies the PluginDefinition, the desired Cluster and additional values to set. Depending on the PluginDefinition, it may be necessary to specify required values (e.g. credentials, endpoints, etc.), but in general the PluginDefinition provides well-established default values.

[!NOTE] In this example the Plugin ‘openTelemetry-cluster-a’ is used to deploy the PluginDefinition ‘openTelemetry’ to the cluster ‘cluster-a’.

flowchart TB subgraph "Greenhouse" pluginDefinition[PluginDefinition 'openTelemetry'] subgraph "Namespace <org-name>" clusterA[Cluster 'cluster-a'] plugin1[Plugin 'openTelemetry-cluster-a'] end end subgraph "cluster-a" subgraph "observability" plugin1HelmRelease[HelmRelease 'openTelemetry-cluster-a'] end end plugin1 -.- clusterA plugin1 -.- pluginDefinition plugin1 --"deploys"--> plugin1HelmRelease

PluginPresets

PluginPresets are a mechanism to configure Plugins for multiple clusters at once. They are used to define a common configuration for a PluginDefinition that can be applied to multiple clusters, while allowing to override the configuration for individual clusters.

[!NOTE] In this example the PluginPreset ’example-obs’ references the PluginDefinition ’example’ and contains a clusterSelector that matches the clusters ‘cluster-a’ and ‘cluster-b’. The PluginPreset creates two Plugins ’example-obs-cluster-a’ and ’example-obs-cluster-b’ for the respective clusters.

flowchart TB subgraph "Greenhouse" pluginDefinition[PluginDefinition 'example'] subgraph "Namespace <org-name>" pluginPreset[PluginPreset 'example-obs'] clusterA[Cluster 'cluster-a'] clusterB[Cluster 'cluster-b'] plugin1[Plugin 'example-obs-cluster-a'] plugin2[Plugin 'example-obs-cluster-b'] end end pluginPreset -.- clusterA pluginPreset -.- clusterB pluginPreset -.- pluginDefinition pluginPreset --"creates"--> plugin1 pluginPreset --"creates"--> plugin2

Next Steps

2 - Overview

What is Greenhouse?

Greenhouse is a cloud operations platform designed to streamline and simplify the management of a large-scale, distributed infrastructure.

It offers a unified interface for organizations to manage various operational aspects efficiently and transparently and operate their cloud infrastructure in compliance with industry standards.
The platform addresses common challenges such as the fragmentation of tools, visibility of application-specific permission concepts and the management of organizational groups. It also emphasizes the harmonization and standardization of authorization concepts to enhance security and scalability. With its operator-friendly dashboard, features and extensive automation capabilities, Greenhouse empowers organizations to optimize their cloud operations, reduce manual efforts, and achieve greater operational efficiency.

Value Propositions

  1. Holistic dashboard Unified dashboard for infrastructure, alert, security, compliance, and organizational management. (Juno)
  2. Organization management Greenhouse allows to manage organizational groups as Teams. Teams can be provided with fine-grained access control to resources and tools. (e.g. Github Repositories, Kubernetes RBAC, etc.)
  3. Automation Greenhouse allows to configure tools and access control in a declarative way, that is auto-deployed across a fleet of Kubernetes clusters.
  4. Security & Compliance With Heureka, Greenhouse integrates a Security Posture Management tool that focuses on remediation of security issues (vulnerabilities, security events, policy violations), while ensuring compliance and auditability.
  5. Extensibility Greenhouse provides a plugin system that provides a curated catalog of plugins with sane defaults. Furthermore, it is possible to extend the platform with self-developed plugins.

Roadmap

The Roadmap Kanban board provides an overview of ongoing and planned efforts.

Architecture & Design

The Greenhouse design and architecture document describes the various use-cases and user stories.

3 - Installation

This section provides a step-by-step guide to install Greenhouse on a Gardener shoot cluster.

Prerequisites

Before you start the installation, make sure you have the following prerequisites:

  • Helm & Kubernetes CLI
  • OAuth2/OpenID provider (see Authentik)
  • Gardener Shoot Cluster configured to use the OIDC provider
  • nginx-ingress deployed in the cluster

Installation

To install Greenhouse on your Gardener shoot cluster, follow these steps:

  1. Create a values file called values.yaml with the following content:

      global:
        dnsDomain: tld.domain # Shoot.spec.dns.domain
        kubeAPISubDomain: myapi # api is already used by Gardener
        oidc:
          enabled: true
          issuer: <issuer-url>
          clientID: <client-ID>
          clientSecret: <top-secret>
        dex:   # DEX configuration for Greenhouse.
          backend: kubernetes
    
      postgresqlng:
        enabled: false # disable, because the dex backend is kubernetes
    
      organization:
        enabled: false # disable, because the greenhouse webhook is not running yet
    
      teams:
        admin:
          mappedIdPGroup: greenhouse-admins
    
      # gardener specifics
      dashboard:
        ingress:
          annotations:
            dns.gardener.cloud/dnsnames: "*"
            dns.gardener.cloud/ttl: "600"
            dns.gardener.cloud/class: garden
            cert.gardener.cloud/purpose: managed
    
      idproxy:
        enabled: false # disable because no organization is created yet
        ingress:
          annotations:
            dns.gardener.cloud/dnsnames: "*"
            dns.gardener.cloud/ttl: "600"
            dns.gardener.cloud/class: garden
            cert.gardener.cloud/purpose: managed
    
      cors-proxy:
        ingress:
          annotations:
            dns.gardener.cloud/dnsnames: "*"
            dns.gardener.cloud/ttl: "600"
            dns.gardener.cloud/class: garden
            cert.gardener.cloud/purpose: managed
    
      # disable Plugins for the greenhouse organization, PluginDefinitions are missing
      plugins:
        enabled: false
    
      # disable, Prometheus CRDs are missing
      manager:
        alerts:
          enabled: false
    
  2. Install the Greenhouse Helm chart:

    helm install greenhouse oci://ghcr.io/cloudoperators/greenhouse/charts/greenhouse --version <greenhouse-release-version> -f values.yaml
    
  3. Enable Greenhouse OIDC

    Now set organization.enabled and idproxy.enabled to true in the values.yaml file and upgrade the Helm release:

    helm upgrade greenhouse oci://ghcr.io/cloudoperators/greenhouse/charts/greenhouse --version <greenhouse-release-version> -f values.yaml
    

    This will create the initial Greenhouse Organization and the Greenhouse Admin Team. This Organization will receive the greenhouse namespace, which is used to manage the Greenhouse installation and allows to administer other organizations. Enabling the idproxy will deploy the idproxy service which handles the OIDC authentication.

4 - Operational Processes

Operational Processes in Greenhouse

Greenhouse provides a couple of predefined operational processes.

Operational processes facilitated via Greenhouse heavily rely on the Ownership principle. It is used to route operational tasks to Support Groups.

Examples for these operational tasks are:

  • Alert routing based on metrics
  • Lifecycle management of k8s Clusters
  • Security posture and vulnerability patch management
  • Secret rotation and management

Labels Used

Greenhouse focuses on labels in three different places:

  • On resources (e.g. PluginPresets, Clusters but also k8s Deployments, Pods, etc.)
  • On metrics exposed by those resources
  • On Prometheus alerts based on metrics

The following labels are used by Greenhouse automation:

labeldescriptionused onused by
greenhouse.sap/owned-byIdentifies the owning team of a resourceResources, metricsSecurity management, lifecycle management, secret rotation
support_groupSpecifies the support group responsible for the alertAlertsAlert routing
serviceGroups resources belonging to a serviceResources, metrics, alertsSecurity management, alert routing
regionIndicates the region an alert is firing inMetrics, alertsAlert routing
severityIndicates the importance or urgency of an alertAlertsAlert routing
ClusterSpecifies the cluster a metric is exposed onMetrics, alertsAlert routing

Alert Routing

Monitoring and alert routing is achieved through a combination of Plugins running on the remote Clusters and the Greenhouse central cluster.

All alerts processed with Greenhouse need the support_group label that can be extracted from the greenhouse.sap/owned-by.

With the Alerts Plugin a holistic alerts dashboard is integrated to the Greenhouse UI. This dashboard is prefiltered on the support group a user is member of. It directly displays alerts by region and severity. Also service is prominently displayed.

It is good practice to also route alerts by support_group and/or severity to specific Alertmanager receivers (e.g. Slack channels).

Lifecycle management of k8s Clusters

All Cluster related alerts, including version expiration and other maintenance tasks are routed to the owning support_group of the Cluster.

Security Management

Security posture and vulnerability management is achieved through the heureka Plugin. It scans for security violations in running k8s containers and displays these by support_group and service.

Secret Management

With secret management Greenhouse wants to have alerts on expiring Secrets in need of rotation. These alerts will be routed to the respective support_groups. See roadmap item for further information.

5 - Ownership

What is Ownership within Greenhouse

Ownership in Greenhouse is the combination of two of the core features:

Greenhouse provides a 1:1 relationship between a Team and

  • PluginPresets
  • Plugins
  • Clusters
  • TeamRoleBindings
  • Secrets

Within the context of Greenhouse this relationship is called Ownership.

Why Ownership of Resources

Operational processes facilitated via Greenhouse rely on Ownership:

By identifying the owner of a resource it is possible to route operational tasks on the resource to the owner.

Additionally, Ownership enables the Authorization Webhook to enforce support-group-scoped access control for greenhouse.sap API-group resources when RBAC does not already allow the request. RBAC can still grant broader read access, and core resources such as Secrets are authorized by RBAC only.

How is Ownership achieved

Greenhouse expects a label with the key greenhouse.sap/owned-by with a value matching an existing Team on the following resources in the Greenhouse central cluster:

  • PluginPresets
  • Plugins
  • Clusters
  • TeamRoleBindings
  • Secrets

Missing greenhouse.sap/owned-by label results in a StatusCondition called OwnerLabelSetCondition set to false. A greenhouse_owned_by_label_missing metric on missing owner labels is exposed and alerted on.

The owner label is also expected on k8s resources (e.g. Deployments, Pods, …) exposing metrics on the remote clusters.

Label Transport

On Greenhouse central cluster

The Greenhouse controller transports labels from a source resource to a target resource on the Greenhouse cluster. This is currently active for:

  • Secrets that are used to bootstrap a Cluster
  • PluginPresets creating Plugins

The transport works via metadata.annotation on the source:

metadata:
  ...
  labels:
    foo: bar
    qux: baz
    greenhouse.sap/owned_by: foo-team
    ...
  annotations:
    greenhouse.sap/propagate-labels: "foo, greenhouse.sap/owned_by"
  ...

which results in metadata.labels and a state in metadata.annotations added to the target:

metadata:
  annotations:
   ...
    greenhouse.sap/last-applied-propagator: '{"labelKeys":["foo","greenhouse.sap/owned_by"]}'
  labels:
    foo: bar
    greenhouse.sap/owned_by: foo-team
   ...

It also supports wildcards to propagate multiple labels that share a common prefix, e.g. greenhouse.sap/propagate-labels: "metadata.greenhouse.sap/*".

On Resources on Remote Clusters

Greenhouse will provide the automation to label all resources created by a Plugin on the remote Cluster in the future: https://github.com/cloudoperators/greenhouse-extensions/issues/704

Currently Greenhouse provides the owned-by label as a OptionValue to be consumed by the underlying helm chart of the Plugin.

6 - Authorization Webhook

Overview

The Greenhouse Authorization Webhook enforces fine-grained access control on Greenhouse resources based on Team ownership. The webhook checks if a user’s support-group claims match the greenhouse.sap/owned-by label on resources before granting access.

This enables Teams to have elevated permissions on resources they own, while maintaining visibility across the Organization.

Why This Exists

Greenhouse uses a single namespace per Organization for all resources. While this simplifies management, it requires a mechanism to allow Teams to manage their own resources without unrestricted access to resources owned by other Teams.

The authorization model combines two layers:

LayerPurpose
RBACProvides organization-wide permissions (e.g., view all resources, admin roles)
Authorization WebhookGrants elevated permissions on resources owned by the requesting Team

This allows:

  • All Teams to view resources across their Organization (via RBAC)
  • Resource owners to get, update, patch, and delete their own existing resources (via the webhook)
  • Organization admins to manage resources organization-wide via RBAC roles (including create and collection operations)

How It Works

The authorization webhook integrates with the Kubernetes API server’s authorization chain as an additional authorizer after RBAC. When a user attempts to access a Greenhouse resource:

  1. RBAC is evaluated first — If RBAC allows the request, it is granted immediately
  2. If RBAC returns NoOpinion (no matching rule), the webhook is consulted for greenhouse.sap resources
  3. The webhook extracts the user’s support-group claims from their IdP token groups
  4. It fetches the target resource and reads its greenhouse.sap/owned-by label
  5. It validates that the referenced Team exists and is marked as a support-group
  6. Access is allowed only if one of the user’s support-groups matches the resource owner

If no authorizer in the chain allows the request, it is denied by default. Note that the webhook can only authorize requests targeting a specific named resource — collection operations (list, watch) must be granted via RBAC.

sequenceDiagram participant User participant APIServer as Kubernetes API Server participant RBAC participant Webhook as Authz Webhook participant K8s as Kubernetes API User->>APIServer: Request access to resource APIServer->>RBAC: Evaluate RBAC rules alt RBAC allows RBAC->>APIServer: Allow APIServer->>User: Response (allowed) else RBAC returns NoOpinion RBAC->>APIServer: NoOpinion APIServer->>Webhook: SubjectAccessReview alt User Request Webhook->>Webhook: Extract support-group claims else ServiceAccount Request Webhook->>K8s: Fetch ServiceAccount Webhook->>Webhook: Extract team from owned-by label end Webhook->>K8s: Fetch target resource Webhook->>Webhook: Extract owned-by label Webhook->>K8s: Validate Team exists and is support-group Webhook->>Webhook: Check support-group matches owner Webhook->>APIServer: Allow or NoOpinion APIServer->>User: Response end

Note: The webhook only handles resources in the greenhouse.sap API group. Core Kubernetes resources (Secrets, ConfigMaps, etc.) are authorized by RBAC only.

Identity Resolution

The webhook supports two types of identities:

User Requests

For human users, the webhook extracts support-group claims from the user’s group memberships. Groups with the prefix support-group: are recognized as support-group claims.

Example: A user with groups ["support-group:my-team", "developers"] would have my-team as their support-group.

Users are expected to belong to only one Support Group, as described in the Teams documentation. However, the webhook also supports users with multiple support-group: claims and grants access if any of those claims matches the resource owner.

ServiceAccount Requests (Team Automation)

ServiceAccounts enable Teams to set up automation that has the same elevated permissions on their owned resources as human team members.

For ServiceAccounts, the webhook:

  1. Extracts the ServiceAccount name from the username (format: system:serviceaccount:{namespace}:{name})
  2. Fetches the ServiceAccount from the cluster
  3. Extracts the team name from the greenhouse.sap/owned-by label on the ServiceAccount

The ServiceAccount is then authorized as if it were a member of the owning Team.

Troubleshooting

ErrorCauseFix
user has no support-group claims and is not an authorized ServiceAccountUser’s IdP token has no support-group: prefixed groupsEnsure the IdP token includes claims in the format support-group:{team-name}
resource has no owned-by labelTarget resource is missing greenhouse.sap/owned-bykubectl label <resource> <name> greenhouse.sap/owned-by=<team> -n <org>
team <name> is not a support-groupTeam exists but lacks greenhouse.sap/support-group: "true"kubectl label team <name> greenhouse.sap/support-group=true -n <org>
support-group does not match resource ownerUser’s support-group doesn’t match the resource’s owned-by labelVerify the user’s group membership and the resource label are consistent
ServiceAccount <name> not foundSA for team automation doesn’t exist yetVerify the Team has greenhouse.sap/support-group: "true" set; the controller creates the SA automatically