Skip to content

Commit 0e5f9ce

Browse files
Add configuration to conditionally disable shared pipeline resources
Signed-off-by: Krishan Bhasin <[email protected]>
1 parent a51b928 commit 0e5f9ce

File tree

4 files changed

+61
-0
lines changed

4 files changed

+61
-0
lines changed

backend/src/apiserver/common/config.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,17 @@ const (
3232
KubeflowUserIDPrefix string = "KUBEFLOW_USERID_PREFIX"
3333
UpdatePipelineVersionByDefault string = "AUTO_UPDATE_PIPELINE_DEFAULT_VERSION"
3434
TokenReviewAudience string = "TOKEN_REVIEW_AUDIENCE"
35+
RequireNamespaceForPipelines string = "REQUIRE_NAMESPACE_FOR_PIPELINES"
3536
)
3637

3738
func IsPipelineVersionUpdatedByDefault() bool {
3839
return GetBoolConfigWithDefault(UpdatePipelineVersionByDefault, true)
3940
}
4041

42+
func IsNamespaceRequiredForPipelines() bool {
43+
return GetBoolConfigWithDefault(RequireNamespaceForPipelines, false)
44+
}
45+
4146
func GetStringConfig(configName string) string {
4247
if !viper.IsSet(configName) {
4348
glog.Fatalf("Please specify flag %s", configName)

backend/src/apiserver/server/pipeline_server.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import (
2828
"github.com/kubeflow/pipelines/backend/src/apiserver/list"
2929
"github.com/kubeflow/pipelines/backend/src/apiserver/model"
3030
"github.com/kubeflow/pipelines/backend/src/apiserver/resource"
31+
"github.com/kubeflow/pipelines/backend/src/apiserver/validation"
3132
"github.com/kubeflow/pipelines/backend/src/common/util"
3233
"github.com/prometheus/client_golang/prometheus"
3334
"github.com/prometheus/client_golang/prometheus/promauto"
@@ -121,6 +122,10 @@ type PipelineServerV1 struct {
121122
// Applies common logic on v1beta1 and v2beta1 API.
122123
func (s *BasePipelineServer) createPipeline(ctx context.Context, pipeline *model.Pipeline) (*model.Pipeline, error) {
123124
pipeline.Namespace = s.resourceManager.ReplaceNamespace(pipeline.Namespace)
125+
err := validation.ValidateNamespaceRequired(pipeline.Namespace)
126+
if err != nil {
127+
return nil, err
128+
}
124129

125130
if pipeline.Name == "" {
126131
return nil, util.NewInvalidInputError("name is required")
@@ -151,6 +156,10 @@ func (s *BasePipelineServer) createPipelineAndPipelineVersion(ctx context.Contex
151156
}
152157

153158
pipeline.Namespace = s.resourceManager.ReplaceNamespace(pipeline.Namespace)
159+
err := validation.ValidateNamespaceRequired(pipeline.Namespace)
160+
if err != nil {
161+
return nil, nil, err
162+
}
154163

155164
// Check authorization
156165
resourceAttributes := &authorizationv1.ResourceAttributes{
@@ -328,6 +337,9 @@ func (s *PipelineServer) GetPipeline(ctx context.Context, request *apiv2beta1.Ge
328337
// Applies common logic on v1beta1 and v2beta1 API.
329338
func (s *BasePipelineServer) getPipelineByName(ctx context.Context, name string, namespace string, apiRequestVersion string) (*model.Pipeline, *model.PipelineVersion, error) {
330339
namespace = s.resourceManager.ReplaceNamespace(namespace)
340+
if err := validation.ValidateNamespaceRequired(namespace); err != nil {
341+
return nil, nil, err
342+
}
331343
resourceAttributes := &authorizationv1.ResourceAttributes{
332344
Namespace: namespace,
333345
Name: name,
@@ -389,6 +401,9 @@ func (s *PipelineServer) GetPipelineByName(ctx context.Context, request *apiv2be
389401
func (s *BasePipelineServer) listPipelines(ctx context.Context, namespace string, pageToken string, pageSize int32, sortBy string, opts *list.Options, apiRequestVersion string) ([]*model.Pipeline, []*model.PipelineVersion, int, string, error) {
390402
// Fill in the default namespace
391403
namespace = s.resourceManager.ReplaceNamespace(namespace)
404+
if err := validation.ValidateNamespaceRequired(namespace); err != nil {
405+
return nil, nil, 0, "", err
406+
}
392407
resourceAttributes := &authorizationv1.ResourceAttributes{
393408
Namespace: namespace,
394409
Verb: common.RbacResourceVerbList,

backend/src/apiserver/server/pipeline_upload_server.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,11 @@ func (s *PipelineUploadServer) uploadPipeline(api_version string, w http.Respons
115115
return
116116
}
117117
pipelineNamespace = s.resourceManager.ReplaceNamespace(pipelineNamespace)
118+
err = validation.ValidateNamespaceRequired(pipelineNamespace)
119+
if err != nil {
120+
http.Error(w, err.Error(), http.StatusBadRequest)
121+
return
122+
}
118123
resourceAttributes := &authorizationv1.ResourceAttributes{
119124
Namespace: pipelineNamespace,
120125
Verb: common.RbacResourceVerbCreate,
@@ -255,6 +260,12 @@ func (s *PipelineUploadServer) uploadPipelineVersion(api_version string, w http.
255260
return
256261
}
257262

263+
err = validation.ValidateNamespaceRequired(namespace)
264+
if err != nil {
265+
http.Error(w, err.Error(), http.StatusBadRequest)
266+
return
267+
}
268+
258269
resourceAttributes := &authorizationv1.ResourceAttributes{
259270
Namespace: namespace,
260271
Verb: common.RbacResourceVerbCreate,
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Copyright 2025 The Kubeflow Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package validation
16+
17+
import (
18+
"github.com/kubeflow/pipelines/backend/src/apiserver/common"
19+
"github.com/kubeflow/pipelines/backend/src/common/util"
20+
)
21+
22+
// ValidateNamespaceRequired validates that a namespace is provided when required by configuration.
23+
// This ensures consistent authorization behavior across all KFP resources.
24+
// Only validates in multi-user mode, since single-user mode always uses empty namespaces by design.
25+
func ValidateNamespaceRequired(namespace string) error {
26+
if common.IsMultiUserMode() && common.IsNamespaceRequiredForPipelines() && namespace == "" {
27+
return util.NewInvalidInputError("Namespace is required for pipeline operations")
28+
}
29+
return nil
30+
}

0 commit comments

Comments
 (0)