-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(backend): authorize readArtifacts and ReportMetrics endpoints (#…
…7819) * Authorize readArtifacts and ReportMetrics endpoints New Verbs (reportMetrics and readArtifact) are added to ClusterRole with name: aggregate-to-kubeflow-pipelines-edit Signed-off-by: Diana Atanasova <[email protected]> * Add authorization when Persistent Agent communicate with the api-server Persistent Agent authorize itself based ot the namespace and the current user Fixes: #7818 * Update persistence_agent.csv license file Signed-off-by: Diana Atanasova <[email protected]> * Fix lexical error in persistent agent cluster role Signed-off-by: Diana Atanasova <[email protected]> * Fix integration tests/Fix MULTIUSER= false usecase Cover MULTIUSER=false usecase/Standalone pipeline installation. In this case the namespace doesn't have `user` annotation and there is no need to provide `kubeflow-userid` Header when making a request against kfp-api-server Signed-off-by: Diana Atanasova <[email protected]> * rebase: fix conflixt in license file Signed-off-by: Diana Atanasova <[email protected]> * rebase add new line in the end of licensing file Signed-off-by: Diana Atanasova <[email protected]>
- Loading branch information
Showing
24 changed files
with
695 additions
and
84 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
package client | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
"github.com/golang/glog" | ||
v1 "k8s.io/api/core/v1" | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
types "k8s.io/apimachinery/pkg/types" | ||
watch "k8s.io/apimachinery/pkg/watch" | ||
corev1 "k8s.io/client-go/applyconfigurations/core/v1" | ||
) | ||
|
||
type FakeNamespaceClient struct { | ||
namespace string | ||
user string | ||
} | ||
|
||
func (f *FakeNamespaceClient) SetReturnValues(namespace string, user string) { | ||
f.namespace = namespace | ||
f.user = user | ||
} | ||
|
||
func (f FakeNamespaceClient) Get(ctx context.Context, name string, opts metav1.GetOptions) (*v1.Namespace, error) { | ||
if f.namespace == name && len(f.user) != 0 { | ||
ns := v1.Namespace{ObjectMeta: metav1.ObjectMeta{ | ||
Namespace: f.namespace, | ||
Annotations: map[string]string{ | ||
"owner": f.user, | ||
}, | ||
}} | ||
return &ns, nil | ||
} | ||
return nil, errors.New("failed to get namespace") | ||
} | ||
|
||
func (f FakeNamespaceClient) Create(ctx context.Context, namespace *v1.Namespace, opts metav1.CreateOptions) (*v1.Namespace, error) { | ||
glog.Error("This fake method is not yet implemented.") | ||
return nil, nil | ||
} | ||
|
||
func (f FakeNamespaceClient) Update(ctx context.Context, namespace *v1.Namespace, opts metav1.UpdateOptions) (*v1.Namespace, error) { | ||
glog.Error("This fake method is not yet implemented.") | ||
return nil, nil | ||
} | ||
|
||
func (f FakeNamespaceClient) UpdateStatus(ctx context.Context, namespace *v1.Namespace, opts metav1.UpdateOptions) (*v1.Namespace, error) { | ||
glog.Error("This fake method is not yet implemented.") | ||
return nil, nil | ||
} | ||
|
||
func (f FakeNamespaceClient) Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error { | ||
glog.Error("This fake method is not yet implemented.") | ||
return nil | ||
} | ||
|
||
func (f FakeNamespaceClient) List(ctx context.Context, opts metav1.ListOptions) (*v1.NamespaceList, error) { | ||
glog.Error("This fake method is not yet implemented.") | ||
return nil, nil | ||
} | ||
|
||
func (f FakeNamespaceClient) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) { | ||
glog.Error("This fake method is not yet implemented.") | ||
return nil, nil | ||
} | ||
|
||
func (f FakeNamespaceClient) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *v1.Namespace, err error) { | ||
glog.Error("This fake method is not yet implemented.") | ||
return nil, nil | ||
} | ||
|
||
func (f FakeNamespaceClient) Apply(ctx context.Context, namespace *corev1.NamespaceApplyConfiguration, opts metav1.ApplyOptions) (result *v1.Namespace, err error) { | ||
glog.Error("This fake method is not yet implemented.") | ||
return nil, nil | ||
} | ||
|
||
func (f FakeNamespaceClient) ApplyStatus(ctx context.Context, namespace *corev1.NamespaceApplyConfiguration, opts metav1.ApplyOptions) (result *v1.Namespace, err error) { | ||
glog.Error("This fake method is not yet implemented.") | ||
return nil, nil | ||
} | ||
|
||
func (f FakeNamespaceClient) Finalize(ctx context.Context, item *v1.Namespace, opts metav1.UpdateOptions) (*v1.Namespace, error) { | ||
glog.Error("This fake method is not yet implemented.") | ||
return nil, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
package client | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"os" | ||
"time" | ||
|
||
"github.com/cenkalti/backoff" | ||
"github.com/golang/glog" | ||
"github.com/pkg/errors" | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
"k8s.io/client-go/kubernetes" | ||
v1 "k8s.io/client-go/kubernetes/typed/core/v1" | ||
"k8s.io/client-go/rest" | ||
|
||
"github.com/kubeflow/pipelines/backend/src/common/util" | ||
) | ||
|
||
type KubernetesCoreInterface interface { | ||
NamespaceClient() v1.NamespaceInterface | ||
GetNamespaceOwner(namespace string) (string, error) | ||
} | ||
|
||
type KubernetesCore struct { | ||
coreV1Client v1.CoreV1Interface | ||
} | ||
|
||
func (c *KubernetesCore) NamespaceClient() v1.NamespaceInterface { | ||
return c.coreV1Client.Namespaces() | ||
} | ||
|
||
func (c *KubernetesCore) GetNamespaceOwner(namespace string) (string, error) { | ||
if os.Getenv("MULTIUSER") == "" || os.Getenv("MULTIUSER") == "false" { | ||
return "", nil | ||
} | ||
ns, err := c.NamespaceClient().Get(context.Background(), namespace, metav1.GetOptions{}) | ||
if err != nil { | ||
return "", errors.Wrapf(err, fmt.Sprintf("failed to get namespace '%v'", namespace)) | ||
} | ||
owner, ok := ns.Annotations["owner"] | ||
if !ok { | ||
return "", errors.New(fmt.Sprintf("namespace '%v' has no owner in the annotations", namespace)) | ||
} | ||
return owner, nil | ||
} | ||
|
||
func createKubernetesCore(clientParams util.ClientParameters) (KubernetesCoreInterface, error) { | ||
clientSet, err := getKubernetesClientset(clientParams) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return &KubernetesCore{clientSet.CoreV1()}, nil | ||
} | ||
|
||
// CreateKubernetesCoreOrFatal creates a new client for the Kubernetes pod. | ||
func CreateKubernetesCoreOrFatal(initConnectionTimeout time.Duration, clientParams util.ClientParameters) KubernetesCoreInterface { | ||
var client KubernetesCoreInterface | ||
var err error | ||
var operation = func() error { | ||
client, err = createKubernetesCore(clientParams) | ||
return err | ||
} | ||
b := backoff.NewExponentialBackOff() | ||
b.MaxElapsedTime = initConnectionTimeout | ||
err = backoff.Retry(operation, b) | ||
|
||
if err != nil { | ||
glog.Fatalf("Failed to create namespace client. Error: %v", err) | ||
} | ||
return client | ||
} | ||
|
||
func getKubernetesClientset(clientParams util.ClientParameters) (*kubernetes.Clientset, error) { | ||
restConfig, err := rest.InClusterConfig() | ||
if err != nil { | ||
return nil, errors.Wrap(err, "Failed to initialize kubernetes client.") | ||
} | ||
restConfig.QPS = float32(clientParams.QPS) | ||
restConfig.Burst = clientParams.Burst | ||
|
||
clientSet, err := kubernetes.NewForConfig(restConfig) | ||
if err != nil { | ||
return nil, errors.Wrap(err, "Failed to initialize kubernetes client set.") | ||
} | ||
return clientSet, nil | ||
} |
37 changes: 37 additions & 0 deletions
37
backend/src/agent/persistence/client/kubernetes_core_fake.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package client | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
"fmt" | ||
|
||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
v1 "k8s.io/client-go/kubernetes/typed/core/v1" | ||
) | ||
|
||
type KubernetesCoreFake struct { | ||
coreV1ClientFake *FakeNamespaceClient | ||
} | ||
|
||
func (c *KubernetesCoreFake) NamespaceClient() v1.NamespaceInterface { | ||
return c.coreV1ClientFake | ||
} | ||
|
||
func (c *KubernetesCoreFake) GetNamespaceOwner(namespace string) (string, error) { | ||
ns, err := c.NamespaceClient().Get(context.Background(), namespace, metav1.GetOptions{}) | ||
if err != nil { | ||
return "", err | ||
} | ||
owner, ok := ns.Annotations["owner"] | ||
if !ok { | ||
return "", errors.New(fmt.Sprintf("namespace '%v' has no owner in the annotations", namespace)) | ||
} | ||
return owner, nil | ||
} | ||
|
||
func NewKubernetesCoreFake() *KubernetesCoreFake { | ||
return &KubernetesCoreFake{&FakeNamespaceClient{}} | ||
} | ||
func (c *KubernetesCoreFake) Set(namespaceToReturn string, userToReturn string) { | ||
c.coreV1ClientFake.SetReturnValues(namespaceToReturn, userToReturn) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.