diff --git a/pkg/apis/ome/v1alpha1/auth_types.go b/pkg/apis/ome/v1alpha1/auth_types.go new file mode 100644 index 00000000..8c9d7c81 --- /dev/null +++ b/pkg/apis/ome/v1alpha1/auth_types.go @@ -0,0 +1,144 @@ +package v1beta1 + +import ( + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// AuthMethod defines the authentication method to use. +// +kubebuilder:validation:Enum=None;Bearer;ApiKey;Basic;JWT;ClientCertificate;OAuth2 +type AuthMethod string + +const ( + AuthMethodNone AuthMethod = "None" + AuthMethodBearer AuthMethod = "Bearer" + AuthMethodApiKey AuthMethod = "ApiKey" + AuthMethodBasic AuthMethod = "Basic" + AuthMethodJWT AuthMethod = "JWT" + AuthMethodClientCertificate AuthMethod = "ClientCertificate" + AuthMethodOAuth2 AuthMethod = "OAuth2" +) + +// CredentialRef provides a reference to a secret containing authentication credentials. +type CredentialRef struct { + // SecretRef references a Kubernetes secret containing the credential. + // +optional + SecretRef *corev1.SecretKeySelector `json:"secretRef,omitempty"` + + // Value contains the credential value directly (not recommended for sensitive data). + // +optional + Value string `json:"value,omitempty"` + + // HeaderName specifies the header name for API key authentication. + // +optional + HeaderName string `json:"headerName,omitempty"` +} + +// AuthConfig provides unified authentication configuration for all components. +type AuthConfig struct { + // Method defines the authentication method to use. + // +kubebuilder:validation:Required + Method AuthMethod `json:"method"` + + // Token provides the authentication token (Bearer, API Key). + // +optional + Token *CredentialRef `json:"token,omitempty"` + + // Basic provides basic authentication credentials. + // +optional + Basic *BasicCredentials `json:"basic,omitempty"` + + // JWT provides JWT authentication configuration. + // +optional + JWT *JWTCredentials `json:"jwt,omitempty"` + + // ClientCert provides client certificate authentication. + // +optional + ClientCert *ClientCertCredentials `json:"clientCert,omitempty"` + + // OAuth2 provides OAuth2 authentication configuration. + // +optional + OAuth2 *OAuth2Credentials `json:"oAuth2,omitempty"` + + // Timeout defines the authentication request timeout. + // +kubebuilder:default="30s" + // +optional + Timeout *metav1.Duration `json:"timeout,omitempty"` +} + +// BasicCredentials defines basic authentication credentials. +type BasicCredentials struct { + // Username for basic authentication. + // +kubebuilder:validation:Required + Username string `json:"username"` + + // Password references the password secret. + // +kubebuilder:validation:Required + Password CredentialRef `json:"password"` +} + +// JWTCredentials defines JWT authentication credentials. +type JWTCredentials struct { + // SigningKey references the JWT signing key secret. + // +kubebuilder:validation:Required + SigningKey CredentialRef `json:"signingKey"` + + // Algorithm defines the JWT signing algorithm. + // +kubebuilder:validation:Enum=HS256;HS384;HS512;RS256;RS384;RS512;ES256;ES384;ES512 + // +kubebuilder:default=RS256 + // +optional + Algorithm string `json:"algorithm,omitempty"` + + // Issuer defines the expected JWT issuer. + // +optional + Issuer string `json:"issuer,omitempty"` + + // Audience defines the expected JWT audience. + // +optional + Audience string `json:"audience,omitempty"` + + // ExpirationTolerance defines tolerance for token expiration. + // +kubebuilder:default="30s" + // +optional + ExpirationTolerance *metav1.Duration `json:"expirationTolerance,omitempty"` +} + +// ClientCertCredentials defines client certificate authentication. +type ClientCertCredentials struct { + // CertificateRef references the client certificate secret. + // +kubebuilder:validation:Required + CertificateRef CredentialRef `json:"certificateRef"` + + // PrivateKeyRef references the private key secret. + // +kubebuilder:validation:Required + PrivateKeyRef CredentialRef `json:"privateKeyRef"` + + // CARef references the CA certificate secret for verification. + // +optional + CARef *CredentialRef `json:"caRef,omitempty"` + + // VerifyServerCert controls whether to verify the server certificate. + // +kubebuilder:default=true + // +optional + VerifyServerCert *bool `json:"verifyServerCert,omitempty"` +} + +// OAuth2Credentials defines OAuth2 authentication credentials. +type OAuth2Credentials struct { + // ClientID for OAuth2 authentication. + // +kubebuilder:validation:Required + ClientID string `json:"clientID"` + + // ClientSecret references the OAuth2 client secret. + // +kubebuilder:validation:Required + ClientSecret CredentialRef `json:"clientSecret"` + + // TokenURL is the OAuth2 token endpoint. + // +kubebuilder:validation:Required + TokenURL string `json:"tokenURL"` + + // Scopes define the OAuth2 scopes to request. + // +optional + // +listType=set + Scopes []string `json:"scopes,omitempty"` +} diff --git a/pkg/apis/ome/v1alpha1/mcp_gateway.go b/pkg/apis/ome/v1alpha1/mcp_gateway.go new file mode 100644 index 00000000..5c9dd15a --- /dev/null +++ b/pkg/apis/ome/v1alpha1/mcp_gateway.go @@ -0,0 +1,416 @@ +package v1beta1 + +import ( + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// MCPGatewaySpec defines the desired state of MCPGateway. +// +kubebuilder:validation:XValidation:rule="has(self.mcpServers.static) || has(self.mcpServers.selector)", message="either static MCP server references or dynamic selector must be specified" +type MCPGatewaySpec struct { + // Replicas is the number of desired replicas for the gateway. + // +kubebuilder:validation:Minimum=1 + // +kubebuilder:default=1 + // +optional + Replicas *int32 `json:"replicas,omitempty"` + + // PodSpec defines the pod template for the gateway deployment. + // +optional + PodSpec *corev1.PodTemplateSpec `json:"podSpec,omitempty"` + + // MCPServers defines how the gateway discovers and connects to MCP servers. + // +kubebuilder:validation:Required + MCPServers MCPServerDiscoveryConfig `json:"mcpServers"` + + // Policy defines unified security, authentication, authorization, and traffic policies. + // +optional + Policy *MCPGatewayPolicyConfig `json:"policy,omitempty"` + + // Network defines service exposure and ingress settings. + // +optional + Network *MCPGatewayNetworkConfig `json:"network,omitempty"` + + // ProtocolVersion defines MCP protocol version constraints and negotiation settings. + // +optional + ProtocolVersion *MCPProtocolVersionConfig `json:"protocolVersion,omitempty"` +} + +// MCPServerDiscoveryConfig defines how the gateway discovers and connects to MCP servers. +type MCPServerDiscoveryConfig struct { + // Static provides a fixed list of MCP server references. + // +optional + // +listType=atomic + Static []MCPServerRef `json:"static,omitempty"` + + // Selector allows dynamic discovery of MCPServer resources using a label selector. + // +optional + Selector *metav1.LabelSelector `json:"selector,omitempty"` + + // NamespaceSelector restricts server discovery to specific namespaces. + // Only applicable when using Selector. If empty, searches all accessible namespaces. + // +optional + NamespaceSelector *metav1.LabelSelector `json:"namespaceSelector,omitempty"` + + // AutoDiscovery enables automatic discovery of MCP servers + // +kubebuilder:default=true + // +optional + AutoDiscovery *bool `json:"autoDiscovery,omitempty"` + + // HealthCheck defines health checking configuration for discovered servers. + // +optional + HealthCheck *HealthCheckConfig `json:"healthCheck,omitempty"` +} + +// MCPServerRef defines a reference to an upstream MCP server with routing parameters. +type MCPServerRef struct { + // Name of the referenced MCPServer resource. + Name string `json:"name"` + + // Namespace of the referenced MCPServer resource. + // If empty, assumes the gateway's namespace. + // +optional + Namespace string `json:"namespace,omitempty"` + + // Priority for server selection (lower value is higher priority). + // +kubebuilder:validation:Minimum=0 + // +kubebuilder:default=0 + // +optional + Priority *int32 `json:"priority,omitempty"` + + // Tags define semantic tags for routing decisions. + // +optional + // +listType=set + Tags []string `json:"tags,omitempty"` + + // Capabilities override the server's advertised capabilities for routing. + // +optional + Capabilities *MCPCapabilities `json:"capabilities,omitempty"` + + // Auth defines the credentials for this specific server. + // +optional + Auth *AuthConfig `json:"auth,omitempty"` + + // Transport override for this specific server. + // +optional + Transport *MCPTransportType `json:"transport,omitempty"` +} + +// HealthCheckConfig defines health checking configuration. +type HealthCheckConfig struct { + // Enabled controls whether health checking is performed. + // +kubebuilder:default=true + // +optional + Enabled *bool `json:"enabled,omitempty"` + + // Interval is the time between health checks. + // +kubebuilder:default="30s" + // +optional + Interval *metav1.Duration `json:"interval,omitempty"` + + // Timeout is the maximum time to wait for a health check response. + // +kubebuilder:default="5s" + // +optional + Timeout *metav1.Duration `json:"timeout,omitempty"` + + // UnhealthyThreshold is the number of consecutive failures before marking unhealthy. + // +kubebuilder:validation:Minimum=1 + // +kubebuilder:default=3 + // +optional + UnhealthyThreshold *int32 `json:"unhealthyThreshold,omitempty"` + + // HealthyThreshold is the number of consecutive successes before marking healthy. + // +kubebuilder:validation:Minimum=1 + // +kubebuilder:default=2 + // +optional + HealthyThreshold *int32 `json:"healthyThreshold,omitempty"` +} + +// GatewayNetworkConfig defines service exposure, transport protocols, and ingress settings. +type MCPGatewayNetworkConfig struct { + // Service defines the service configuration for the gateway. + // +optional + Service *GatewayServiceConfig `json:"service,omitempty"` + + // Transport defines the transport protocol configuration. + // +optional + Transport *GatewayTransportConfig `json:"transport,omitempty"` + + // Ingress defines ingress configuration for external access. + // +optional + Ingress *GatewayIngressConfig `json:"ingress,omitempty"` +} + +// GatewayServiceConfig defines service configuration. +type GatewayServiceConfig struct { + // Type defines the service type. + // +kubebuilder:validation:Enum=ClusterIP;NodePort;LoadBalancer + // +kubebuilder:default=ClusterIP + // +optional + Type corev1.ServiceType `json:"type,omitempty"` + + // Ports define the service ports. + // +optional + // +listType=atomic + Ports []GatewayServicePort `json:"ports,omitempty"` + + // Annotations define service annotations. + // +optional + // +mapType=atomic + Annotations map[string]string `json:"annotations,omitempty"` +} + +// GatewayServicePort defines a service port. +type GatewayServicePort struct { + // Name is the port name. + // +kubebuilder:validation:Required + Name string `json:"name"` + + // Port is the service port. + // +kubebuilder:validation:Minimum=1 + // +kubebuilder:validation:Maximum=65535 + // +kubebuilder:validation:Required + Port int32 `json:"port"` + + // TargetPort is the target port on pods. + // +kubebuilder:validation:Minimum=1 + // +kubebuilder:validation:Maximum=65535 + // +optional + TargetPort *int32 `json:"targetPort,omitempty"` + + // Protocol is the port protocol. + // +kubebuilder:validation:Enum=TCP;UDP + // +kubebuilder:default=TCP + // +optional + Protocol corev1.Protocol `json:"protocol,omitempty"` +} + +// GatewayTransportConfig defines transport protocol configuration. +type GatewayTransportConfig struct { + // HTTP defines HTTP transport configuration. + // +optional + HTTP *HTTPTransportConfig `json:"http,omitempty"` + + // GRPC defines gRPC transport configuration. + // +optional + GRPC *GRPCTransportConfig `json:"grpc,omitempty"` + + // WebSocket defines WebSocket transport configuration. + // +optional + WebSocket *WebSocketTransportConfig `json:"webSocket,omitempty"` +} + +// HTTPTransportConfig defines HTTP transport configuration. +type HTTPTransportConfig struct { + // Port defines the HTTP port. + // +kubebuilder:validation:Minimum=1 + // +kubebuilder:validation:Maximum=65535 + // +kubebuilder:default=8080 + // +optional + Port *int32 `json:"port,omitempty"` + + // ReadTimeout defines the HTTP read timeout. + // +kubebuilder:default="30s" + // +optional + ReadTimeout *metav1.Duration `json:"readTimeout,omitempty"` + + // WriteTimeout defines the HTTP write timeout. + // +kubebuilder:default="30s" + // +optional + WriteTimeout *metav1.Duration `json:"writeTimeout,omitempty"` + + // MaxHeaderSize defines the maximum header size. + // +optional + MaxHeaderSize *resource.Quantity `json:"maxHeaderSize,omitempty"` +} + +// GRPCTransportConfig defines gRPC transport configuration. +type GRPCTransportConfig struct { + // Port defines the gRPC port. + // +kubebuilder:validation:Minimum=1 + // +kubebuilder:validation:Maximum=65535 + // +kubebuilder:default=9090 + // +optional + Port *int32 `json:"port,omitempty"` + + // MaxMessageSize defines the maximum message size. + // +optional + MaxMessageSize *resource.Quantity `json:"maxMessageSize,omitempty"` + + // ConnectionTimeout defines the connection timeout. + // +kubebuilder:default="10s" + // +optional + ConnectionTimeout *metav1.Duration `json:"connectionTimeout,omitempty"` +} + +// WebSocketTransportConfig defines WebSocket transport configuration. +type WebSocketTransportConfig struct { + // Port defines the WebSocket port. + // +kubebuilder:validation:Minimum=1 + // +kubebuilder:validation:Maximum=65535 + // +kubebuilder:default=8081 + // +optional + Port *int32 `json:"port,omitempty"` + + // ReadBufferSize defines the read buffer size. + // +optional + ReadBufferSize *resource.Quantity `json:"readBufferSize,omitempty"` + + // WriteBufferSize defines the write buffer size. + // +optional + WriteBufferSize *resource.Quantity `json:"writeBufferSize,omitempty"` + + // PingInterval defines the ping interval for keep-alive. + // +kubebuilder:default="30s" + // +optional + PingInterval *metav1.Duration `json:"pingInterval,omitempty"` +} + +// GatewayIngressConfig defines ingress configuration. +type GatewayIngressConfig struct { + // Enabled controls whether ingress is created. + // +kubebuilder:default=false + // +optional + Enabled *bool `json:"enabled,omitempty"` + + // ClassName defines the ingress class name. + // +optional + ClassName string `json:"className,omitempty"` + + // Hosts define the ingress hosts. + // +optional + // +listType=atomic + Hosts []GatewayIngressHost `json:"hosts,omitempty"` + + // TLS defines TLS configuration for ingress. + // +optional + // +listType=atomic + TLS []GatewayIngressTLS `json:"tls,omitempty"` + + // Annotations define ingress annotations. + // +optional + // +mapType=atomic + Annotations map[string]string `json:"annotations,omitempty"` +} + +// GatewayIngressHost defines an ingress host. +type GatewayIngressHost struct { + // Host is the host name. + // +kubebuilder:validation:Required + Host string `json:"host"` + + // Paths define the host paths. + // +optional + // +listType=atomic + Paths []GatewayIngressPath `json:"paths,omitempty"` +} + +// GatewayIngressPath defines an ingress path. +type GatewayIngressPath struct { + // Path is the URL path. + // +kubebuilder:validation:Required + Path string `json:"path"` + + // PathType defines the path type. + // +kubebuilder:validation:Enum=Exact;Prefix;ImplementationSpecific + // +kubebuilder:default=Prefix + // +optional + PathType string `json:"pathType,omitempty"` + + // ServiceName is the backend service name. + // +kubebuilder:validation:Required + ServiceName string `json:"serviceName"` + + // ServicePort is the backend service port. + // +kubebuilder:validation:Minimum=1 + // +kubebuilder:validation:Maximum=65535 + // +kubebuilder:validation:Required + ServicePort int32 `json:"servicePort"` +} + +// GatewayIngressTLS defines ingress TLS configuration. +type GatewayIngressTLS struct { + // Hosts define the TLS hosts. + // +optional + // +listType=set + Hosts []string `json:"hosts,omitempty"` + + // SecretName references the TLS secret. + // +optional + SecretName string `json:"secretName,omitempty"` +} + +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status +// +kubebuilder:subresource:scale:specpath=.spec.replicas,statuspath=.status.replicas +// +kubebuilder:printcolumn:name="Phase",type="string",JSONPath=".status.phase" +// +kubebuilder:printcolumn:name="Replicas",type="string",JSONPath=".status.readyReplicas/.status.replicas" +// +kubebuilder:printcolumn:name="Servers",type="string",JSONPath=".status.serverStatusSummary.connected/.status.serverStatusSummary.total" +// +kubebuilder:printcolumn:name="Tools",type="integer",JSONPath=".status.toolRegistry.totalTools" +// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp" + +// MCPGateway is the Schema for the mcpgateways API. +// capabilities for Model Context Protocol (MCP) servers and tools. +type MCPGateway struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec MCPGatewaySpec `json:"spec,omitempty"` + Status MCPGatewayStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true + +// MCPGatewayList contains a list of MCPGateway. +type MCPGatewayList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []MCPGateway `json:"items"` +} + +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status +// +kubebuilder:subresource:scale:specpath=.spec.replicas,statuspath=.status.replicas +// +kubebuilder:resource:scope="Cluster" +// +kubebuilder:printcolumn:name="Phase",type="string",JSONPath=".status.phase" +// +kubebuilder:printcolumn:name="Replicas",type="string",JSONPath=".status.readyReplicas/.status.replicas" +// +kubebuilder:printcolumn:name="Servers",type="string",JSONPath=".status.serverStatusSummary.connected/.status.serverStatusSummary.total" +// +kubebuilder:printcolumn:name="Tools",type="integer",JSONPath=".status.toolRegistry.totalTools" +// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp" + +// MCPProtocolVersionConfig defines MCP protocol version constraints and negotiation settings. +type MCPProtocolVersionConfig struct { + // Supported defines the list of supported MCP protocol versions. + // If empty, the gateway will support all known versions. + // +optional + // +listType=set + Supported []string `json:"supported,omitempty"` + + // MinVersion defines the minimum acceptable MCP protocol version. + // +kubebuilder:default="2025-06-18" + // +optional + MinVersion string `json:"minVersion,omitempty"` + + // MaxVersion defines the maximum acceptable MCP protocol version. + // +optional + MaxVersion string `json:"maxVersion,omitempty"` + + // PreferredVersion defines the preferred protocol version for new connections. + // +kubebuilder:default="2025-06-18" + // +optional + PreferredVersion string `json:"preferredVersion,omitempty"` + + // AllowVersionNegotiation controls whether version negotiation is allowed. + // +kubebuilder:default=true + // +optional + AllowVersionNegotiation *bool `json:"allowVersionNegotiation,omitempty"` + + // StrictVersioning controls whether to reject connections with unsupported versions. + // +kubebuilder:default=false + // +optional + StrictVersioning *bool `json:"strictVersioning,omitempty"` +} + +func init() { + SchemeBuilder.Register(&MCPGateway{}, &MCPGatewayList{}) +} diff --git a/pkg/apis/ome/v1alpha1/mcp_gateway_policy.go b/pkg/apis/ome/v1alpha1/mcp_gateway_policy.go new file mode 100644 index 00000000..90c8d399 --- /dev/null +++ b/pkg/apis/ome/v1alpha1/mcp_gateway_policy.go @@ -0,0 +1,658 @@ +package v1beta1 + +import ( + "k8s.io/apimachinery/pkg/api/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// GatewayPolicyConfig defines unified security, authentication, authorization, and traffic policies. +type MCPGatewayPolicyConfig struct { + // Authentication defines client authentication configuration. + // +optional + Authentication *MCPAuthenticationConfig `json:"authentication,omitempty"` + + // RateLimit defines rate limiting configuration. + // +optional + RateLimit *RateLimitConfig `json:"rateLimit,omitempty"` + + // CircuitBreaker defines the circuit breaking configuration. + // +optional + CircuitBreaker *CircuitBreakerConfig `json:"circuitBreaker,omitempty"` + + // Audit defines audit logging configuration. + // +optional + Audit *AuditConfig `json:"audit,omitempty"` + + // RequestFiltering defines request filtering policies. + // +optional + RequestFiltering *RequestFilteringConfig `json:"requestFiltering,omitempty"` + + // ResponseFiltering defines response filtering policies. + // +optional + ResponseFiltering *ResponseFilteringConfig `json:"responseFiltering,omitempty"` + + // Compliance defines compliance-related policies. + // +optional + Compliance *ComplianceConfig `json:"compliance,omitempty"` + + // Sampling defines server-to-client sampling request policy. + // +optional + Sampling *SamplingPolicyConfig `json:"sampling,omitempty"` + + // Elicitation defines server-to-client elicitation request policy. + // +optional + Elicitation *ElicitationPolicyConfig `json:"elicitation,omitempty"` + + // SessionIsolation defines session isolation and context boundary policies. + // +optional + SessionIsolation *SessionIsolationConfig `json:"sessionIsolation,omitempty"` +} + +// MCPAuthenticationConfig defines simplified client authentication configuration. +type MCPAuthenticationConfig struct { + // Enabled controls whether authentication is required. + // +kubebuilder:default=true + // +optional + Enabled *bool `json:"enabled,omitempty"` + + // Methods define the supported authentication methods in order of preference. + // +optional + // +listType=atomic + Methods []AuthConfig `json:"methods,omitempty"` + + // Default provides the default authentication method when none is specified. + // +optional + Default *AuthConfig `json:"default,omitempty"` +} + +// RateLimitConfig defines rate limiting policies. +type RateLimitConfig struct { + // Global rate limit applied to all requests. + // +optional + Global *RateLimitPolicy `json:"global,omitempty"` + + // PerUser defines rate limits per authenticated user. + // +optional + PerUser *RateLimitPolicy `json:"perUser,omitempty"` + + // PerIP defines rate limits per client IP address. + // +optional + PerIP *RateLimitPolicy `json:"perIP,omitempty"` + + // PerServer defines rate limits per upstream server. + // +optional + PerServer *RateLimitPolicy `json:"perServer,omitempty"` +} + +// RateLimitPolicy defines a rate limiting policy. +type RateLimitPolicy struct { + // RequestsPerSecond is the number of requests allowed per second. + // +kubebuilder:validation:Minimum=1 + // +optional + RequestsPerSecond *int32 `json:"requestsPerSecond,omitempty"` + + // RequestsPerMinute is the number of requests allowed per minute. + // +kubebuilder:validation:Minimum=1 + // +optional + RequestsPerMinute *int32 `json:"requestsPerMinute,omitempty"` + + // RequestsPerHour is the number of requests allowed per hour. + // +kubebuilder:validation:Minimum=1 + // +optional + RequestsPerHour *int32 `json:"requestsPerHour,omitempty"` + + // Burst is the burst capacity for rate limiting. + // +kubebuilder:validation:Minimum=1 + // +optional + Burst *int32 `json:"burst,omitempty"` +} + +// AuditConfig defines audit logging configuration. +type AuditConfig struct { + // Enabled controls whether audit logging is active. + // +kubebuilder:default=false + // +optional + Enabled *bool `json:"enabled,omitempty"` + + // Level defines the audit logging level. + // +kubebuilder:validation:Enum=None;Request;Response;Full + // +kubebuilder:default=Request + // +optional + Level AuditLevel `json:"level,omitempty"` + + // Destination defines where audit logs are sent. + // +optional + Destination *AuditDestinationConfig `json:"destination,omitempty"` + + // Format defines the audit log format. + // +kubebuilder:validation:Enum=JSON;CEF;SYSLOG + // +kubebuilder:default=JSON + // +optional + Format AuditFormat `json:"format,omitempty"` + + // IncludeMetadata controls whether to include request metadata in audit logs. + // +kubebuilder:default=true + // +optional + IncludeMetadata *bool `json:"includeMetadata,omitempty"` +} + +// AuditLevel defines audit logging levels. +type AuditLevel string + +const ( + AuditLevelNone AuditLevel = "None" + AuditLevelRequest AuditLevel = "Request" + AuditLevelResponse AuditLevel = "Response" + AuditLevelFull AuditLevel = "Full" +) + +// AuditFormat defines audit log formats. +type AuditFormat string + +const ( + AuditFormatJSON AuditFormat = "JSON" + AuditFormatCEF AuditFormat = "CEF" + AuditFormatSyslog AuditFormat = "SYSLOG" +) + +// AuditDestinationConfig defines audit log destinations. +type AuditDestinationConfig struct { + // Type defines the destination type. + // +kubebuilder:validation:Enum=File;Syslog;HTTP;S3;Database + // +kubebuilder:default=File + // +optional + Type AuditDestinationType `json:"type,omitempty"` + + // File defines file-based audit logging. + // +optional + File *AuditFileConfig `json:"file,omitempty"` + + // HTTP defines HTTP-based audit logging. + // +optional + HTTP *AuditHTTPConfig `json:"http,omitempty"` + + // Syslog defines syslog-based audit logging. + // +optional + Syslog *AuditSyslogConfig `json:"syslog,omitempty"` +} + +// AuditDestinationType defines audit destination types. +type AuditDestinationType string + +const ( + AuditDestinationTypeFile AuditDestinationType = "File" + AuditDestinationTypeSyslog AuditDestinationType = "Syslog" + AuditDestinationTypeHTTP AuditDestinationType = "HTTP" + AuditDestinationTypeS3 AuditDestinationType = "S3" + AuditDestinationTypeDatabase AuditDestinationType = "Database" +) + +// AuditFileConfig defines file-based audit logging. +type AuditFileConfig struct { + // Path defines the audit log file path. + // +kubebuilder:default="/var/log/mcpgateway/audit.log" + // +optional + Path string `json:"path,omitempty"` + + // MaxSize defines the maximum log file size before rotation. + // +optional + MaxSize *resource.Quantity `json:"maxSize,omitempty"` + + // MaxBackups defines the maximum number of backup files to keep. + // +kubebuilder:validation:Minimum=0 + // +kubebuilder:default=3 + // +optional + MaxBackups *int32 `json:"maxBackups,omitempty"` +} + +// AuditHTTPConfig defines HTTP-based audit logging. +type AuditHTTPConfig struct { + // Endpoint defines the HTTP endpoint for audit logs. + // +kubebuilder:validation:Required + Endpoint string `json:"endpoint"` + + // Method defines the HTTP method to use. + // +kubebuilder:validation:Enum=POST;PUT + // +kubebuilder:default=POST + // +optional + Method string `json:"method,omitempty"` + + // Headers define additional HTTP headers. + // +optional + // +mapType=atomic + Headers map[string]string `json:"headers,omitempty"` + + // Timeout defines the HTTP request timeout. + // +kubebuilder:default="30s" + // +optional + Timeout *metav1.Duration `json:"timeout,omitempty"` +} + +// AuditSyslogConfig defines syslog-based audit logging. +type AuditSyslogConfig struct { + // Server defines the syslog server address. + // +kubebuilder:validation:Required + Server string `json:"server"` + + // Protocol defines the syslog protocol. + // +kubebuilder:validation:Enum=UDP;TCP;TLS + // +kubebuilder:default=UDP + // +optional + Protocol SyslogProtocol `json:"protocol,omitempty"` + + // Facility defines the syslog facility. + // +kubebuilder:validation:Minimum=0 + // +kubebuilder:validation:Maximum=23 + // +kubebuilder:default=16 + // +optional + Facility *int32 `json:"facility,omitempty"` +} + +// SyslogProtocol defines syslog protocols. +type SyslogProtocol string + +const ( + SyslogProtocolUDP SyslogProtocol = "UDP" + SyslogProtocolTCP SyslogProtocol = "TCP" + SyslogProtocolTLS SyslogProtocol = "TLS" +) + +// RequestFilteringConfig defines request filtering policies. +type RequestFilteringConfig struct { + // SizeLimit defines maximum request size. + // +optional + SizeLimit *resource.Quantity `json:"sizeLimit,omitempty"` + + // ContentTypeFilter defines allowed content types. + // +optional + // +listType=set + ContentTypeFilter []string `json:"contentTypeFilter,omitempty"` + + // HeaderFilters define header filtering rules. + // +optional + // +listType=atomic + HeaderFilters []HeaderFilter `json:"headerFilters,omitempty"` + + // BodyFilters define body content filtering rules. + // +optional + // +listType=atomic + BodyFilters []BodyFilter `json:"bodyFilters,omitempty"` +} + +// HeaderFilter defines header filtering rules. +type HeaderFilter struct { + // Name is the header name to filter. + // +kubebuilder:validation:Required + Name string `json:"name"` + + // Action defines the filtering action. + // +kubebuilder:validation:Enum=Allow;Deny;Remove;Redact + // +kubebuilder:validation:Required + Action FilterAction `json:"action"` + + // Pattern is a regex pattern to match header values. + // +optional + Pattern string `json:"pattern,omitempty"` +} + +// BodyFilter defines body content filtering rules. +type BodyFilter struct { + // Type defines the filter type. + // +kubebuilder:validation:Enum=Regex;JSONPath;Size + // +kubebuilder:validation:Required + Type BodyFilterType `json:"type"` + + // Pattern defines the pattern to match. + // +optional + Pattern string `json:"pattern,omitempty"` + + // Action defines the filtering action. + // +kubebuilder:validation:Enum=Allow;Deny;Remove;Redact + // +kubebuilder:validation:Required + Action FilterAction `json:"action"` + + // Replacement defines the replacement value for redaction. + // +optional + Replacement string `json:"replacement,omitempty"` +} + +// FilterAction defines filtering actions. +type FilterAction string + +const ( + FilterActionAllow FilterAction = "Allow" + FilterActionDeny FilterAction = "Deny" + FilterActionRemove FilterAction = "Remove" + FilterActionRedact FilterAction = "Redact" +) + +// BodyFilterType defines body filter types. +type BodyFilterType string + +const ( + BodyFilterTypeRegex BodyFilterType = "Regex" + BodyFilterTypeJSONPath BodyFilterType = "JSONPath" + BodyFilterTypeSize BodyFilterType = "Size" +) + +// ResponseFilteringConfig defines response filtering policies. +type ResponseFilteringConfig struct { + // SizeLimit defines maximum response size. + // +optional + SizeLimit *resource.Quantity `json:"sizeLimit,omitempty"` + + // HeaderFilters define response header filtering rules. + // +optional + // +listType=atomic + HeaderFilters []HeaderFilter `json:"headerFilters,omitempty"` + + // BodyFilters define response body filtering rules. + // +optional + // +listType=atomic + BodyFilters []BodyFilter `json:"bodyFilters,omitempty"` + + // RemoveInternalHeaders controls whether to remove internal headers. + // +kubebuilder:default=true + // +optional + RemoveInternalHeaders *bool `json:"removeInternalHeaders,omitempty"` +} + +// ComplianceConfig defines compliance-related policies. +type ComplianceConfig struct { + // DataRetention defines data retention policies. + // +optional + DataRetention *DataRetentionConfig `json:"dataRetention,omitempty"` + + // PIIDetection defines PII detection and handling. + // +optional + PIIDetection *PIIDetectionConfig `json:"piiDetection,omitempty"` + + // Encryption defines encryption requirements. + // +optional + Encryption *ComplianceEncryptionConfig `json:"encryption,omitempty"` +} + +// DataRetentionConfig defines data retention policies. +type DataRetentionConfig struct { + // AuditLogRetention defines how long to keep audit logs. + // +kubebuilder:default="90d" + // +optional + AuditLogRetention *metav1.Duration `json:"auditLogRetention,omitempty"` + + // ContextRetention defines how long to keep context data. + // +kubebuilder:default="30d" + // +optional + ContextRetention *metav1.Duration `json:"contextRetention,omitempty"` + + // SessionRetention defines how long to keep session data. + // +kubebuilder:default="7d" + // +optional + SessionRetention *metav1.Duration `json:"sessionRetention,omitempty"` +} + +// PIIDetectionConfig defines PII detection and handling. +type PIIDetectionConfig struct { + // Enabled controls whether PII detection is active. + // +kubebuilder:default=false + // +optional + Enabled *bool `json:"enabled,omitempty"` + + // Patterns define PII detection patterns. + // +optional + // +listType=atomic + Patterns []PIIPattern `json:"patterns,omitempty"` + + // Action defines the action to take when PII is detected. + // +kubebuilder:validation:Enum=Log;Block;Redact + // +kubebuilder:default=Log + // +optional + Action PIIAction `json:"action,omitempty"` +} + +// PIIPattern defines a PII detection pattern. +type PIIPattern struct { + // Type defines the PII type. + // +kubebuilder:validation:Enum=SSN;CreditCard;Email;Phone;Custom + // +kubebuilder:validation:Required + Type PIIType `json:"type"` + + // Pattern is a regex pattern for custom PII detection. + // +optional + Pattern string `json:"pattern,omitempty"` + + // Description provides a human-readable description. + // +optional + Description string `json:"description,omitempty"` +} + +// PIIType defines PII types. +type PIIType string + +const ( + PIITypeSSN PIIType = "SSN" + PIITypeCreditCard PIIType = "CreditCard" + PIITypeEmail PIIType = "Email" + PIITypePhone PIIType = "Phone" + PIITypeCustom PIIType = "Custom" +) + +// PIIAction defines PII handling actions. +type PIIAction string + +const ( + PIIActionLog PIIAction = "Log" + PIIActionBlock PIIAction = "Block" + PIIActionRedact PIIAction = "Redact" +) + +// ComplianceEncryptionConfig defines compliance encryption configuration. +type ComplianceEncryptionConfig struct { + // RequireEncryption controls whether encryption is required. + // +kubebuilder:default=false + // +optional + RequireEncryption *bool `json:"requireEncryption,omitempty"` + + // EncryptionAtRest controls whether data must be encrypted at rest. + // +kubebuilder:default=false + // +optional + EncryptionAtRest *bool `json:"encryptionAtRest,omitempty"` + + // EncryptionInTransit controls whether data must be encrypted in transit. + // +kubebuilder:default=true + // +optional + EncryptionInTransit *bool `json:"encryptionInTransit,omitempty"` +} + +// CircuitBreakerConfig defines circuit breaker configuration. +type CircuitBreakerConfig struct { + // FailureThreshold is the number of consecutive failures to open the circuit. + // +kubebuilder:validation:Minimum=1 + // +kubebuilder:default=5 + // +optional + FailureThreshold *int32 `json:"failureThreshold,omitempty"` + + // SuccessThreshold is the number of consecutive successes to close the circuit. + // +kubebuilder:validation:Minimum=1 + // +kubebuilder:default=1 + // +optional + SuccessThreshold *int32 `json:"successThreshold,omitempty"` + + // OpenStateTimeout is the time to wait before transitioning to half-open. + // +kubebuilder:default="30s" + // +optional + OpenStateTimeout *metav1.Duration `json:"openStateTimeout,omitempty"` + + // MaxRequestsHalfOpen is the maximum requests allowed in half-open state. + // +kubebuilder:validation:Minimum=1 + // +kubebuilder:default=10 + // +optional + MaxRequestsHalfOpen *int32 `json:"maxRequestsHalfOpen,omitempty"` + + // RequestTimeout defines the timeout for requests in various states. + // +kubebuilder:default="30s" + // +optional + RequestTimeout *metav1.Duration `json:"requestTimeout,omitempty"` + + // ErrorRateThreshold defines the error rate percentage to open the circuit. + // +kubebuilder:validation:Pattern=`^[0-9]+(\.[0-9]+)?$` + // +kubebuilder:default="50.0" + // +optional + ErrorRateThreshold *string `json:"errorRateThreshold,omitempty"` + + // MinRequestsThreshold is the minimum requests before error rate is calculated. + // +kubebuilder:validation:Minimum=1 + // +kubebuilder:default=20 + // +optional + MinRequestsThreshold *int32 `json:"minRequestsThreshold,omitempty"` +} + +// SamplingPolicyConfig defines server-to-client sampling request policy. +type SamplingPolicyConfig struct { + // Enabled controls whether servers can request sampling from clients. + // +kubebuilder:default=false + // +optional + Enabled *bool `json:"enabled,omitempty"` + + // ClientModel defines which AI model to use for sampling requests. + // +optional + ClientModel string `json:"clientModel,omitempty"` + + // MaxTokens defines the maximum tokens for sampling requests. + // +kubebuilder:validation:Minimum=1 + // +kubebuilder:validation:Maximum=100000 + // +kubebuilder:default=1000 + // +optional + MaxTokens *int32 `json:"maxTokens,omitempty"` + + // Temperature controls the randomness of sampling responses. + // +kubebuilder:validation:Pattern=`^[0-9]+(\.[0-9]+)?$` + // +kubebuilder:default="0.7" + // +optional + Temperature *string `json:"temperature,omitempty"` + + // Timeout defines the maximum time to wait for sampling responses. + // +kubebuilder:default="30s" + // +optional + Timeout *metav1.Duration `json:"timeout,omitempty"` + + // RateLimit defines rate limiting for sampling requests. + // +optional + RateLimit *SamplingRateLimit `json:"rateLimit,omitempty"` +} + +// SamplingRateLimit defines rate limiting for sampling requests. +type SamplingRateLimit struct { + // RequestsPerMinute is the maximum sampling requests per minute. + // +kubebuilder:validation:Minimum=1 + // +kubebuilder:default=10 + // +optional + RequestsPerMinute *int32 `json:"requestsPerMinute,omitempty"` + + // RequestsPerHour is the maximum sampling requests per hour. + // +kubebuilder:validation:Minimum=1 + // +kubebuilder:default=100 + // +optional + RequestsPerHour *int32 `json:"requestsPerHour,omitempty"` +} + +// ElicitationPolicyConfig defines server-to-client elicitation request policy. +type ElicitationPolicyConfig struct { + // Enabled controls whether servers can request elicitation from clients. + // +kubebuilder:default=false + // +optional + Enabled *bool `json:"enabled,omitempty"` + + // RequireConfirmation controls whether user confirmation is required for elicitation. + // +kubebuilder:default=true + // +optional + RequireConfirmation *bool `json:"requireConfirmation,omitempty"` + + // AllowedTypes defines which types of elicitation are allowed. + // +optional + // +listType=set + AllowedTypes []ElicitationType `json:"allowedTypes,omitempty"` + + // Timeout defines the maximum time to wait for elicitation responses. + // +kubebuilder:default="60s" + // +optional + Timeout *metav1.Duration `json:"timeout,omitempty"` + + // MaxConcurrentRequests is the maximum concurrent elicitation requests. + // +kubebuilder:validation:Minimum=1 + // +kubebuilder:default=5 + // +optional + MaxConcurrentRequests *int32 `json:"maxConcurrentRequests,omitempty"` +} + +// ElicitationType defines types of elicitation requests. +type ElicitationType string + +const ( + ElicitationTypeQuestion ElicitationType = "question" + ElicitationTypeConfirmation ElicitationType = "confirmation" + ElicitationTypeInput ElicitationType = "input" + ElicitationTypeChoice ElicitationType = "choice" +) + +// SessionIsolationConfig defines session isolation and context boundary policies. +type SessionIsolationConfig struct { + // Mode defines the isolation level for MCP sessions. + // +kubebuilder:validation:Enum=strict;relaxed;custom + // +kubebuilder:default=strict + // +optional + Mode SessionIsolationMode `json:"mode,omitempty"` + + // CrossSessionSharing controls whether data can be shared between sessions. + // +kubebuilder:default=false + // +optional + CrossSessionSharing *bool `json:"crossSessionSharing,omitempty"` + + // ContextRetention defines how long session context is retained. + // +kubebuilder:default="1h" + // +optional + ContextRetention *metav1.Duration `json:"contextRetention,omitempty"` + + // AuditLevel defines the audit logging level for session boundaries. + // +kubebuilder:validation:Enum=None;Basic;Full + // +kubebuilder:default=Basic + // +optional + AuditLevel SessionAuditLevel `json:"auditLevel,omitempty"` + + // EnforceResourceBoundaries controls whether resource access is strictly bounded per session. + // +kubebuilder:default=true + // +optional + EnforceResourceBoundaries *bool `json:"enforceResourceBoundaries,omitempty"` + + // AllowedCrossSessionData defines what data types can be shared across sessions when enabled. + // +optional + // +listType=set + AllowedCrossSessionData []CrossSessionDataType `json:"allowedCrossSessionData,omitempty"` +} + +// SessionIsolationMode defines session isolation levels. +type SessionIsolationMode string + +const ( + SessionIsolationModeStrict SessionIsolationMode = "strict" + SessionIsolationModeRelaxed SessionIsolationMode = "relaxed" + SessionIsolationModeCustom SessionIsolationMode = "custom" +) + +// SessionAuditLevel defines session audit logging levels. +type SessionAuditLevel string + +const ( + SessionAuditLevelNone SessionAuditLevel = "None" + SessionAuditLevelBasic SessionAuditLevel = "Basic" + SessionAuditLevelFull SessionAuditLevel = "Full" +) + +// CrossSessionDataType defines types of data that can be shared across sessions. +type CrossSessionDataType string + +const ( + CrossSessionDataTypeTools CrossSessionDataType = "tools" + CrossSessionDataTypeResources CrossSessionDataType = "resources" + CrossSessionDataTypePrompts CrossSessionDataType = "prompts" + CrossSessionDataTypeMetrics CrossSessionDataType = "metrics" +) diff --git a/pkg/apis/ome/v1alpha1/mcp_server.go b/pkg/apis/ome/v1alpha1/mcp_server.go new file mode 100644 index 00000000..802a2dcd --- /dev/null +++ b/pkg/apis/ome/v1alpha1/mcp_server.go @@ -0,0 +1,262 @@ +package v1beta1 + +import ( + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// MCPTransportType defines the transport method for MCP communication. +// +kubebuilder:validation:Enum=stdio;streamable-http;sse +type MCPTransportType string + +const ( + // MCPTransportStdio uses standard input/output for communication. + MCPTransportStdio MCPTransportType = "stdio" + // MCPTransportStreamableHTTP uses HTTP with streaming support. + MCPTransportStreamableHTTP MCPTransportType = "streamable-http" + // MCPTransportSSE uses Server-Sent Events for communication. + MCPTransportSSE MCPTransportType = "sse" +) + +// MCPServerSpec defines the desired state of an MCPServer. +// An MCPServer can either be 'Hosted' within the cluster or a 'Remote' external service. +// +kubebuilder:validation:XValidation:rule="has(self.hosted) || has(self.remote)", message="either hosted or remote must be specified" +// +kubebuilder:validation:XValidation:rule="!(has(self.hosted) && has(self.remote))", message="hosted and remote are mutually exclusive" +type MCPServerSpec struct { + // Hosted defines a server that runs as pods within the cluster. + // +optional + Hosted *HostedMCPServer `json:"hosted,omitempty"` + + // Remote defines a server that is accessed via an external URL. + // +optional + Remote *RemoteMCPServer `json:"remote,omitempty"` + + // Transport specifies the transport protocol for MCP communication. + // +kubebuilder:default=stdio + // +optional + Transport MCPTransportType `json:"transport,omitempty"` + + // Capabilities defines the features supported by this server. + // +optional + Capabilities *MCPCapabilities `json:"capabilities,omitempty"` + + // Version of the MCP server software. + // +optional + Version string `json:"version,omitempty"` + + // PermissionProfile defines the operational permissions for the server. + // +optional + PermissionProfile *PermissionProfileSource `json:"permissionProfile,omitempty"` + + // OIDCConfig defines OIDC authentication for authenticating clients. + // +optional + OIDCConfig *OIDCConfigSource `json:"oidcConfig,omitempty"` + + // AuthzConfig defines authorization policies for the server. + // +optional + AuthzConfig *AuthzConfigSource `json:"authzConfig,omitempty"` + + // ToolsFilter restricts the tools exposed by this server. + // +optional + // +listType=set + ToolsFilter []string `json:"toolsFilter,omitempty"` +} + +// HostedMCPServer defines a server that runs as pods in the cluster. +type HostedMCPServer struct { + // PodSpec defines the pod template to use for the MCP server. + PodSpec corev1.PodTemplateSpec `json:"podSpec"` + + // Replicas is the number of desired replicas for the server. + // Only applicable for servers with network-based transports (e.g., http, sse). + // +kubebuilder:validation:Minimum=0 + // +kubebuilder:default=1 + // +optional + Replicas *int32 `json:"replicas,omitempty"` +} + +// RemoteMCPServer defines a server that is accessed via an external URL. +type RemoteMCPServer struct { + // URL is the external URL of the remote MCP server. + // +kubebuilder:validation:Pattern=`^https?://.*` + URL string `json:"url"` +} + +// MCPCapabilities defines the features supported by the MCP server. +type MCPCapabilities struct { + // Tools indicates whether the server supports tool execution. + // +kubebuilder:default=true + // +optional + Tools *bool `json:"tools,omitempty"` + + // Resources indicates whether the server supports exposing resources. + // +kubebuilder:default=false + // +optional + Resources *bool `json:"resources,omitempty"` + + // Prompts indicates whether the server supports prompt elicitation. + // +kubebuilder:default=false + // +optional + Prompts *bool `json:"prompts,omitempty"` +} + +// PermissionProfileSource defines the source of a permission profile. +// Only one of the fields may be set. +// +kubebuilder:validation:XValidation:rule="(has(self.builtin) + has(self.configMap) + has(self.inline)) <= 1",message="at most one of builtin, configMap, or inline can be set" +type PermissionProfileSource struct { + // Builtin selects a pre-defined, named permission profile. + // +optional + Builtin *BuiltinPermissionProfile `json:"builtin,omitempty"` + + // ConfigMap references a ConfigMap containing a permission profile specification. + // +optional + ConfigMap *corev1.ConfigMapKeySelector `json:"configMap,omitempty"` + + // Inline contains an embedded permission profile specification. + // +optional + Inline *PermissionProfileSpec `json:"inline,omitempty"` +} + +// BuiltinPermissionProfile defines a built-in permission profile. +type BuiltinPermissionProfile struct { + // Name of the built-in permission profile. + // +kubebuilder:validation:Enum=none;network-only;full-access + Name string `json:"name"` +} + +// PermissionProfileSpec defines the permissions for an MCP server. +type PermissionProfileSpec struct { + // Allow specifies the permissions granted to the server. + // +listType=atomic + Allow []PermissionRule `json:"allow"` +} + +// PermissionRule defines a single permission grant. +type PermissionRule struct { + // KubeResources defines permissions for accessing Kubernetes resources. + // +optional + KubeResources *KubeResourcePermission `json:"kubeResources,omitempty"` + // Network defines permissions for making outbound network calls. + // +optional + Network *NetworkPermission `json:"network,omitempty"` +} + +// KubeResourcePermission defines permissions for a set of Kubernetes resources. +type KubeResourcePermission struct { + // APIGroups is the list of API groups. "*" means all. + // +listType=set + APIGroups []string `json:"apiGroups"` + // Resources is the list of resource names. "*" means all. + // +listType=set + Resources []string `json:"resources"` + // Verbs is the list of allowed verbs. + // +listType=set + Verbs []string `json:"verbs"` +} + +// NetworkPermission defines outbound network permissions. +type NetworkPermission struct { + // AllowHost is a list of glob patterns for hosts to allow connections to. + // +listType=set + AllowHost []string `json:"allowHost"` +} + +// OIDCConfigSource defines the source of OIDC configuration. +// Only one of the fields may be set. +// +kubebuilder:validation:XValidation:rule="(has(self.kubernetes) + has(self.inline)) <= 1",message="at most one of kubernetes or inline can be set" +type OIDCConfigSource struct { + // Kubernetes configures OIDC to validate Kubernetes service account tokens. + // +optional + Kubernetes *KubernetesOIDCConfig `json:"kubernetes,omitempty"` + + // Inline contains a direct OIDC provider configuration. + // +optional + Inline *InlineOIDCConfig `json:"inline,omitempty"` +} + +// KubernetesOIDCConfig configures OIDC for Kubernetes service account token validation. +type KubernetesOIDCConfig struct { + // Issuer is the OIDC issuer URL of the Kubernetes cluster. + // If not specified, it defaults to the cluster's issuer URL. + // +optional + Issuer string `json:"issuer,omitempty"` +} + +// InlineOIDCConfig contains direct OIDC provider configuration. +type InlineOIDCConfig struct { + // Issuer is the OIDC issuer URL. + // +kubebuilder:validation:Required + // +kubebuilder:validation:Pattern=`^https?://.*` + Issuer string `json:"issuer"` + + // Audience is the expected audience for the token. + // +optional + Audience string `json:"audience,omitempty"` + + // JWKSURL is the URL to fetch the JSON Web Key Set from. + // If empty, OIDC discovery will be used. + // +kubebuilder:validation:Pattern=`^https?://.*` + // +optional + JWKSURL string `json:"jwksURL,omitempty"` +} + +// AuthzConfigSource defines the source of an authorization policy. +// Only one of the fields may be set. +// +kubebuilder:validation:XValidation:rule="(has(self.configMap) + has(self.inline)) <= 1",message="at most one of configMap or inline can be set" +type AuthzConfigSource struct { + // ConfigMap references a ConfigMap containing the authorization policy. + // +optional + ConfigMap *corev1.ConfigMapKeySelector `json:"configMap,omitempty"` + + // Inline contains an embedded authorization policy. + // +optional + Inline *InlineAuthzConfig `json:"inline,omitempty"` +} + +// InlineAuthzConfig contains an embedded authorization policy. +type InlineAuthzConfig struct { + // Policies is a list of Cedar policy strings. + // +kubebuilder:validation:MinItems=1 + // +listType=set + Policies []string `json:"policies"` + + // EntitiesJSON is a JSON string representing Cedar entities. + // +kubebuilder:default="[]" + // +optional + EntitiesJSON string `json:"entitiesJSON,omitempty"` +} + +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status +// +kubebuilder:printcolumn:name="Status",type="string",JSONPath=".status.phase" +// +kubebuilder:printcolumn:name="URL",type="string",JSONPath=".status.url" +// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp" + +// MCPServer is the Schema for the mcpservers API +type MCPServer struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // +kubebuilder:validation:Required + Spec MCPServerSpec `json:"spec"` + Status MCPServerStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status +// +kubebuilder:resource:scope="Cluster" +// +kubebuilder:printcolumn:name="Status",type="string",JSONPath=".status.phase" +// +kubebuilder:printcolumn:name="URL",type="string",JSONPath=".status.url" +// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp" + +// +kubebuilder:object:root=true +// MCPServerList contains a list of MCPServer +type MCPServerList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []MCPServer `json:"items"` +} + +func init() { + SchemeBuilder.Register(&MCPServer{}, &MCPServerList{}) +} diff --git a/pkg/apis/ome/v1alpha1/mcp_status.go b/pkg/apis/ome/v1alpha1/mcp_status.go new file mode 100644 index 00000000..6d49e13d --- /dev/null +++ b/pkg/apis/ome/v1alpha1/mcp_status.go @@ -0,0 +1,452 @@ +package v1beta1 + +import ( + "k8s.io/apimachinery/pkg/api/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// MCPServerStatus defines the observed state of MCPServer +type MCPServerStatus struct { + // Conditions represent the latest available observations of the MCPServer's state + // Standard condition types: Ready, Available, Progressing + // +optional + // +listType=map + // +listMapKey=type + Conditions []metav1.Condition `json:"conditions,omitempty"` + + // URL is the URL where the MCP server can be accessed + // For Hosted servers, this is the cluster-internal or external service URL + // For Remote servers, this reflects the configured external URL + // +optional + URL string `json:"url,omitempty"` + + // Phase is the current phase of the MCPServer lifecycle + // +optional + Phase MCPServerPhase `json:"phase,omitempty"` + + // Message provides additional information about the current phase + // +optional + Message string `json:"message,omitempty"` + + // ObservedGeneration reflects the generation most recently observed by the controller + // +optional + ObservedGeneration int64 `json:"observedGeneration,omitempty"` + + // Replicas is the most recently observed number of replicas for hosted servers + // +optional + Replicas int32 `json:"replicas,omitempty"` + + // ReadyReplicas is the number of ready replicas for hosted servers + // +optional + ReadyReplicas int32 `json:"readyReplicas,omitempty"` + + // LastUpdateTime is the last time the status was updated + // +optional + LastUpdateTime *metav1.Time `json:"lastUpdateTime,omitempty"` +} + +// MCPServerPhase is the phase of the MCPServer +// +kubebuilder:validation:Enum=Pending;Starting;Running;Updating;Failed;Terminating +type MCPServerPhase string + +const ( + // MCPServerPhasePending means the MCPServer is being created + MCPServerPhasePending MCPServerPhase = "Pending" + + // MCPServerPhaseStarting means the MCPServer is starting up + MCPServerPhaseStarting MCPServerPhase = "Starting" + + // MCPServerPhaseRunning means the MCPServer is running and ready + MCPServerPhaseRunning MCPServerPhase = "Running" + + // MCPServerPhaseUpdating means the MCPServer is being updated + MCPServerPhaseUpdating MCPServerPhase = "Updating" + + // MCPServerPhaseFailed means the MCPServer failed to start or run + MCPServerPhaseFailed MCPServerPhase = "Failed" + + // MCPServerPhaseTerminating means the MCPServer is being deleted + MCPServerPhaseTerminating MCPServerPhase = "Terminating" +) + +// MCPGatewayStatus defines the observed state of MCPGateway. +type MCPGatewayStatus struct { + // Conditions represent the latest available observations of the MCPGateway's state. + // +optional + // +listType=map + // +listMapKey=type + Conditions []metav1.Condition `json:"conditions,omitempty"` + + // Phase is the current phase of the MCPGateway lifecycle. + // +optional + Phase MCPGatewayPhase `json:"phase,omitempty"` + + // ObservedGeneration reflects the generation most recently observed by the controller. + // +optional + ObservedGeneration int64 `json:"observedGeneration,omitempty"` + + // Replicas is the most recently observed number of replicas. + // +optional + Replicas int32 `json:"replicas,omitempty"` + + // ReadyReplicas is the number of ready replicas. + // +optional + ReadyReplicas int32 `json:"readyReplicas,omitempty"` + + // AvailableReplicas is the number of available replicas. + // +optional + AvailableReplicas int32 `json:"availableReplicas,omitempty"` + + // ActiveSessions is the current number of active sessions. + // +optional + ActiveSessions int32 `json:"activeSessions,omitempty"` + + // TotalRequests is the total number of requests processed. + // +optional + TotalRequests int64 `json:"totalRequests,omitempty"` + + // TotalErrors is the total number of errors encountered. + // +optional + TotalErrors int64 `json:"totalErrors,omitempty"` + + // AverageLatency is the average request latency in milliseconds. + // +optional + AverageLatency int32 `json:"averageLatency,omitempty"` + + // ConnectedServers is the list of currently connected servers. + // +optional + // +listType=map + // +listMapKey=name + ConnectedServers []MCPGatewayServerStatus `json:"connectedServers,omitempty"` + + // ServerStatusSummary provides an aggregated summary of server statuses. + // +optional + ServerStatusSummary *ServerStatusSummary `json:"serverStatusSummary,omitempty"` + + // UnhealthyServers lists servers that are currently unhealthy. + // +optional + // +listType=map + // +listMapKey=name + UnhealthyServers []MCPGatewayServerStatus `json:"unhealthyServers,omitempty"` + + // ServiceURL is the URL where the gateway service can be accessed. + // +optional + ServiceURL string `json:"serviceURL,omitempty"` + + // LastUpdateTime is the last time the status was updated. + // +optional + LastUpdateTime *metav1.Time `json:"lastUpdateTime,omitempty"` + + // Metrics provides real-time performance metrics. + // +optional + Metrics *GatewayMetrics `json:"metrics,omitempty"` + + // ConfigStatus provides configuration validation status. + // +optional + ConfigStatus *ConfigValidationStatus `json:"configStatus,omitempty"` + + // ResourceUsage provides current resource utilization information. + // +optional + ResourceUsage *ResourceUsageStatus `json:"resourceUsage,omitempty"` + + // ToolRegistry provides status of the tool registry. + // +optional + ToolRegistry *ToolRegistryStatus `json:"toolRegistry,omitempty"` + + // ResourceRegistry provides status of the resource registry. + // +optional + ResourceRegistry *ResourceRegistryStatus `json:"resourceRegistry,omitempty"` + + // PromptRegistry provides status of the prompt registry. + // +optional + PromptRegistry *PromptRegistryStatus `json:"promptRegistry,omitempty"` + + // WorkflowStatus provides status of workflow orchestration. + // +optional + WorkflowStatus *WorkflowStatus `json:"workflowStatus,omitempty"` +} + +// MCPGatewayPhase is the phase of the MCPGateway. +// +kubebuilder:validation:Enum=Pending;Starting;Running;Updating;Failed;Terminating +type MCPGatewayPhase string + +const ( + // MCPGatewayPhasePending means the MCPGateway is being created. + MCPGatewayPhasePending MCPGatewayPhase = "Pending" + + // MCPGatewayPhaseStarting means the MCPGateway is starting up. + MCPGatewayPhaseStarting MCPGatewayPhase = "Starting" + + // MCPGatewayPhaseRunning means the MCPGateway is running and ready. + MCPGatewayPhaseRunning MCPGatewayPhase = "Running" + + // MCPGatewayPhaseUpdating means the MCPGateway is being updated. + MCPGatewayPhaseUpdating MCPGatewayPhase = "Updating" + + // MCPGatewayPhaseFailed means the MCPGateway failed to start or run. + MCPGatewayPhaseFailed MCPGatewayPhase = "Failed" + + // MCPGatewayPhaseTerminating means the MCPGateway is being deleted. + MCPGatewayPhaseTerminating MCPGatewayPhase = "Terminating" +) + +// MCPGatewayServerStatus defines the status of a connected MCP server. +type MCPGatewayServerStatus struct { + // Name is the name of the MCP server. + Name string `json:"name"` + + // Namespace is the namespace of the MCP server. + // +optional + Namespace string `json:"namespace,omitempty"` + + // State is the current connection state. + // +kubebuilder:validation:Enum=Connected;Disconnected;Connecting;Unhealthy;CircuitOpen + State string `json:"state"` + + // LastConnected is the timestamp of the last successful connection. + // +optional + LastConnected *metav1.Time `json:"lastConnected,omitempty"` + + // LastError contains the last error encountered. + // +optional + LastError string `json:"lastError,omitempty"` + + // RequestCount is the total number of requests sent to this server. + // +optional + RequestCount int64 `json:"requestCount,omitempty"` + + // ErrorCount is the total number of errors from this server. + // +optional + ErrorCount int64 `json:"errorCount,omitempty"` + + // AverageResponseTime is the average response time in milliseconds. + // +optional + AverageResponseTime int32 `json:"averageResponseTime,omitempty"` + + // CircuitBreakerState is the current circuit breaker state. + // +kubebuilder:validation:Enum=Closed;Open;HalfOpen + // +optional + CircuitBreakerState string `json:"circuitBreakerState,omitempty"` + + // Weight is the current effective weight for load balancing. + // +optional + Weight int32 `json:"weight,omitempty"` + + // Tags are the current tags associated with this server. + // +optional + // +listType=set + Tags []string `json:"tags,omitempty"` + + // Capabilities are the server's current capabilities. + // +optional + Capabilities *MCPCapabilities `json:"capabilities,omitempty"` +} + +// ServerStatusSummary provides an aggregated summary of server statuses. +type ServerStatusSummary struct { + // Total number of configured servers. + Total int32 `json:"total"` + + // Number of servers that are connected and healthy. + Connected int32 `json:"connected"` + + // Number of servers that are disconnected. + Disconnected int32 `json:"disconnected"` + + // Number of servers that are unhealthy. + Unhealthy int32 `json:"unhealthy"` + + // Number of servers with open circuit breakers. + CircuitOpen int32 `json:"circuitOpen"` +} + +// GatewayMetrics provides real-time performance metrics for the gateway. +type GatewayMetrics struct { + // RequestsPerSecond is the current requests per second rate. + // +optional + RequestsPerSecond string `json:"requestsPerSecond,omitempty"` + + // P50Latency is the 50th percentile latency in milliseconds. + // +optional + P50Latency int32 `json:"p50Latency,omitempty"` + + // P90Latency is the 99th percentile latency in milliseconds. + // +optional + P90Latency int32 `json:"p90Latency,omitempty"` + + // ErrorRate is the current error rate as a percentage. + // +optional + ErrorRate string `json:"errorRate,omitempty"` + + // ActiveConnections is the number of currently active connections. + // +optional + ActiveConnections int32 `json:"activeConnections,omitempty"` + + // CacheHitRate is the cache hit rate as a percentage. + // +optional + CacheHitRate string `json:"cacheHitRate,omitempty"` + + // ToolInvocations tracks tool invocation statistics. + // +optional + // +mapType=atomic + ToolInvocations map[string]int64 `json:"toolInvocations,omitempty"` +} + +// ConfigValidationStatus provides configuration validation status. +type ConfigValidationStatus struct { + // Valid indicates whether the current configuration is valid. + Valid bool `json:"valid"` + + // ValidationErrors contains any configuration validation errors. + // +optional + // +listType=atomic + ValidationErrors []ConfigValidationError `json:"validationErrors,omitempty"` + + // Warnings contains non-blocking configuration warnings. + // +optional + // +listType=atomic + Warnings []string `json:"warnings,omitempty"` + + // LastValidated is when the configuration was last validated. + // +optional + LastValidated *metav1.Time `json:"lastValidated,omitempty"` +} + +// ConfigValidationError represents a configuration validation error. +type ConfigValidationError struct { + // Field is the configuration field that failed validation. + Field string `json:"field"` + + // Message describes the validation error. + Message string `json:"message"` + + // Severity indicates the error severity. + // +kubebuilder:validation:Enum=Error;Warning + Severity ValidationSeverity `json:"severity"` +} + +// ValidationSeverity defines validation error severities. +type ValidationSeverity string + +const ( + ValidationSeverityError ValidationSeverity = "Error" + ValidationSeverityWarning ValidationSeverity = "Warning" +) + +// ResourceUsageStatus provides current resource utilization information. +type ResourceUsageStatus struct { + // CPU usage as a percentage of allocated resources. + // +optional + CPUUsage string `json:"cpuUsage,omitempty"` + + // Memory usage as a percentage of allocated resources. + // +optional + MemoryUsage string `json:"memoryUsage,omitempty"` + + // Storage usage for context and cache storage. + // +optional + StorageUsage *StorageUsageInfo `json:"storageUsage,omitempty"` + + // Network usage statistics. + // +optional + NetworkUsage *NetworkUsageInfo `json:"networkUsage,omitempty"` +} + +// StorageUsageInfo provides storage usage information. +type StorageUsageInfo struct { + // ContextStorage usage information. + // +optional + ContextStorage *StorageMetrics `json:"contextStorage,omitempty"` + + // CacheStorage usage information. + // +optional + CacheStorage *StorageMetrics `json:"cacheStorage,omitempty"` +} + +// StorageMetrics provides storage metrics. +type StorageMetrics struct { + // Used storage in bytes. + Used resource.Quantity `json:"used"` + + // Available storage in bytes. + Available resource.Quantity `json:"available"` + + // Usage percentage. + UsagePercent string `json:"usagePercent"` +} + +// NetworkUsageInfo provides network usage information. +type NetworkUsageInfo struct { + // BytesIn is the total bytes received. + BytesIn int64 `json:"bytesIn"` + + // BytesOut is the total bytes sent. + BytesOut int64 `json:"bytesOut"` + + // ConnectionsPerSecond is the rate of new connections. + ConnectionsPerSecond string `json:"connectionsPerSecond"` +} + +// ToolRegistryStatus provides status of the tool registry. +type ToolRegistryStatus struct { + // TotalTools is the total number of registered tools. + // +optional + TotalTools int32 `json:"totalTools,omitempty"` + + // MCPTools is the number of native MCP tools. + // +optional + MCPTools int32 `json:"mcpTools,omitempty"` + + // RestTools is the number of virtualized REST API tools. + // +optional + RestTools int32 `json:"restTools,omitempty"` + + // LastUpdated is when the registry was last updated. + // +optional + LastUpdated *metav1.Time `json:"lastUpdated,omitempty"` +} + +// ResourceRegistryStatus provides status of the resource registry. +type ResourceRegistryStatus struct { + // TotalResources is the total number of registered resources. + // +optional + TotalResources int32 `json:"totalResources,omitempty"` + + // CacheHitRate is the resource cache hit rate as a percentage. + // +optional + CacheHitRate string `json:"cacheHitRate,omitempty"` + + // LastUpdated is when the registry was last updated. + // +optional + LastUpdated *metav1.Time `json:"lastUpdated,omitempty"` +} + +// PromptRegistryStatus provides status of the prompt registry. +type PromptRegistryStatus struct { + // TotalPrompts is the total number of registered prompts. + // +optional + TotalPrompts int32 `json:"totalPrompts,omitempty"` + + // LastUpdated is when the registry was last updated. + // +optional + LastUpdated *metav1.Time `json:"lastUpdated,omitempty"` +} + +// WorkflowStatus provides status of workflow orchestration. +type WorkflowStatus struct { + // ActiveWorkflows is the number of currently active workflows. + // +optional + ActiveWorkflows int32 `json:"activeWorkflows,omitempty"` + + // CompletedWorkflows is the total number of completed workflows. + // +optional + CompletedWorkflows int64 `json:"completedWorkflows,omitempty"` + + // FailedWorkflows is the total number of failed workflows. + // +optional + FailedWorkflows int64 `json:"failedWorkflows,omitempty"` + + // AverageExecutionTime is the average workflow execution time in seconds. + // +optional + AverageExecutionTime string `json:"averageExecutionTime,omitempty"` +}