Skip to content
Open
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
5 changes: 5 additions & 0 deletions api/api/v1/api_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ type ApiSpec struct {
Category string `json:"category"`
Oauth2Scopes []string `json:"oauth2Scopes,omitempty"`
XVendor bool `json:"xVendor"`

// Specification contains the file ID reference from the file manager for
// the optional OpenAPI specification document that describes this API.
// +optional
Specification string `json:"specification,omitempty"`
}

// ApiStatus defines the observed state of Api
Expand Down
5 changes: 5 additions & 0 deletions api/config/crd/bases/api.cp.ei.telekom.de_apis.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ spec:
items:
type: string
type: array
specification:
description: |-
Specification contains the file ID reference from the file manager for
the optional OpenAPI specification document that describes this API.
type: string
version:
type: string
xVendor:
Expand Down
5 changes: 5 additions & 0 deletions common/pkg/config/feature.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ var (
FeatureFileManager Feature = NewFeature("file_manager", true) // File Manager feature enabled by default
)

// SetFeatureEnabled sets the enabled state for a feature. Intended for tests.
func SetFeatureEnabled(f Feature, enabled bool) {
features[f] = enabled
}

// logFeatureStates logs the enabled/disabled state of all registered features.
func logFeatureStates() {
for f, enabled := range features {
Expand Down
35 changes: 25 additions & 10 deletions controlplane-api/cmd/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,19 @@ import (
)

type ServerConfig struct {
Database DatabaseConfig `yaml:"database"`
Server HTTPServerConfig `yaml:"server"`
Security SecurityConfig `yaml:"security"`
GraphQL GraphQLConfig `yaml:"graphql"`
Log LogConfig `yaml:"log"`
Kubernetes KubernetesConfig `yaml:"kubernetes"`
Database DatabaseConfig `yaml:"database"`
Server HTTPServerConfig `yaml:"server"`
Security SecurityConfig `yaml:"security"`
GraphQL GraphQLConfig `yaml:"graphql"`
Log LogConfig `yaml:"log"`
Kubernetes KubernetesConfig `yaml:"kubernetes"`
FileManager FileManagerConfig `yaml:"fileManager"`
}

type KubernetesConfig struct {
Enabled bool `yaml:"enabled"`
Kubeconfig string `yaml:"kubeconfig"` // optional, defaults to in-cluster config
Enabled bool `yaml:"enabled"`
Kubeconfig string `yaml:"kubeconfig"` // optional, defaults to in-cluster config
Environment string `yaml:"environment"` // environment scope for the scoped client
}

type DatabaseConfig struct {
Expand Down Expand Up @@ -53,10 +55,16 @@ type LogConfig struct {
Level string `yaml:"level"`
}

// FileManagerConfig holds the configuration for constructing specification
// download URLs. The BaseURL is the root URL of the file-manager service.
type FileManagerConfig struct {
BaseURL string `yaml:"baseUrl"`
}

func DefaultConfig() *ServerConfig {
return &ServerConfig{
Database: DatabaseConfig{
URL: "postgres://localhost:5432/controlplane?sslmode=disable",
URL: "postgres://controlplane:controlplane@localhost:5432/controlplane?sslmode=disable",
},
Server: HTTPServerConfig{
Address: ":8443",
Expand All @@ -73,7 +81,14 @@ func DefaultConfig() *ServerConfig {
PlaygroundEnabled: true,
},
Log: LogConfig{
Level: "info",
Level: "debug",
},
Kubernetes: KubernetesConfig{
Enabled: true,
Environment: "poc", // TODO: for now, this is fine. Needs to be refined later
},
FileManager: FileManagerConfig{
BaseURL: "file-manager.controlplane-system.svc",
},
}
}
Expand Down
20 changes: 13 additions & 7 deletions controlplane-api/cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
cserver "github.com/telekom/controlplane/common-server/pkg/server"
"github.com/telekom/controlplane/common-server/pkg/server/middleware/security"
"github.com/telekom/controlplane/common-server/pkg/server/serve"
cc "github.com/telekom/controlplane/common/pkg/client"
"github.com/vektah/gqlparser/v2/ast"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
Expand All @@ -41,8 +42,10 @@ import (
gqlcontroller "github.com/telekom/controlplane/controlplane-api/internal/graphql"
"github.com/telekom/controlplane/controlplane-api/internal/interceptor"
"github.com/telekom/controlplane/controlplane-api/internal/resolvers"
"github.com/telekom/controlplane/controlplane-api/internal/secrets"
"github.com/telekom/controlplane/controlplane-api/internal/service"
organizationv1 "github.com/telekom/controlplane/organization/api/v1"
secretsapi "github.com/telekom/controlplane/secret-manager/api"
)

var configFile string
Expand Down Expand Up @@ -76,18 +79,19 @@ func main() {
log.Error(err, "failed to create Kubernetes client")
os.Exit(1)
}
scopedClient := cc.NewScopedClient(k8sClient, cfg.Kubernetes.Environment)
services = service.Services{
Team: service.NewTeamK8sService(k8sClient),
Application: service.NewApplicationK8sService(k8sClient),
Approval: service.NewApprovalK8sService(k8sClient),
Team: service.NewTeamK8sService(scopedClient),
Application: service.NewApplicationK8sService(scopedClient),
Approval: service.NewApprovalK8sService(scopedClient),
}
log.Info("Kubernetes integration enabled")
} else {
log.Info("Kubernetes integration disabled, mutations will be unavailable")
}

srv := newGraphQLServer(client, services, cfg.Security.Enabled)

secretResolver := secrets.NewResolver(secretsapi.NewSecrets())
srv := newGraphQLServer(client, services, secretResolver, cfg.Security.Enabled, cfg.FileManager.BaseURL)
appCfg := cserver.NewAppConfig()
appCfg.CtxLog = log
appCfg.EnableCors = true
Expand Down Expand Up @@ -176,8 +180,8 @@ func newK8sClient(cfg config.KubernetesConfig) (client.Client, error) {
return client.New(restConfig, client.Options{Scheme: scheme})
}

func newGraphQLServer(entClient *ent.Client, services service.Services, securityEnabled bool) *handler.Server {
srv := handler.New(resolvers.NewSchema(entClient, services))
func newGraphQLServer(entClient *ent.Client, services service.Services, secretResolver *secrets.Resolver, securityEnabled bool, fileManagerBaseURL string) *handler.Server {
srv := handler.New(resolvers.NewSchema(entClient, services, secretResolver, fileManagerBaseURL))
srv.AddTransport(transport.Options{})
srv.AddTransport(transport.GET{})
srv.AddTransport(transport.POST{})
Expand All @@ -187,8 +191,10 @@ func newGraphQLServer(entClient *ent.Client, services service.Services, security
srv.Use(extension.AutomaticPersistedQuery{
Cache: lru.New[string](100),
})
srv.SetErrorPresenter(gqlcontroller.ErrorPresenter)

srv.AroundOperations(gqlcontroller.ViewerFromBusinessContext(entClient, securityEnabled))
srv.AroundOperations(gqlcontroller.LogMutationUser())

return srv
}
34 changes: 34 additions & 0 deletions controlplane-api/config/default/deployment_patch.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,37 @@
name: cert-volume
mountPath: /etc/tls
readOnly: true

# [SECRET_MANAGER] This patch will configure the necessary service account token projection for the secret manager client
- op: add
path: /spec/template/spec/volumes/0
value:
name: secretmgr-token
projected:
sources:
- serviceAccountToken:
path: token
expirationSeconds: 600
audience: secret-manager
- op: add
path: /spec/template/spec/containers/0/volumeMounts/-
value:
name: secretmgr-token
mountPath: /var/run/secrets/secretmgr
readOnly: true

# This patch will add the trust-manager bundle to the deployment
# Only if trust-manager is installed, see https://cert-manager.io/docs/trust/trust-manager
- op: add
path: /spec/template/spec/volumes/0
value:
name: trust-bundle
configMap:
name: secret-manager-trust-bundle

- op: add
path: /spec/template/spec/containers/0/volumeMounts/-
value:
name: trust-bundle
mountPath: /var/run/secrets/trust-bundle
readOnly: true
4 changes: 4 additions & 0 deletions controlplane-api/config/default/kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,14 @@ configMapGenerator:

patches:
# This is only needed when using the cert-manager to issue certificates.
# [SECRET_MANAGER] The following patch will add the secret manager to the deployment.
- path: deployment_patch.yaml
target:
kind: Deployment
name: controlplane-api
- path: namespace_patch.yaml
target:
kind: Namespace

# This is only needed when using the cert-manager to issue certificates.
replacements:
Expand Down
8 changes: 8 additions & 0 deletions controlplane-api/config/default/namespace_patch.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Copyright 2025 Deutsche Telekom IT GmbH
#
# SPDX-License-Identifier: Apache-2.0

# This patch is only needed when you want to use the network policy
- op: add
path: /metadata/labels/cp.ei.telekom.de~1secret-manager
value: "enabled"
Loading