mirror of
https://github.com/kubevela/kubevela.git
synced 2026-02-14 18:10:21 +00:00
Feat: minimize controller privileges & enforce authentication in multicluster e2e test (#4031)
* Feat: enable auth in multicluster test & restrict controller privileges while enabling authentication Signed-off-by: Somefive <yd219913@alibaba-inc.com> * Feat: fix statekeep permission leak & comprev cleanup leak Signed-off-by: Somefive <yd219913@alibaba-inc.com> * Fix: use user info in ref-object select Signed-off-by: Somefive <yd219913@alibaba-inc.com> * Feat: set legacy-rt-gc to disabled by default Signed-off-by: Somefive <yd219913@alibaba-inc.com> * Fix: pending healthscope with authentication test Signed-off-by: Somefive <yd219913@alibaba-inc.com>
This commit is contained in:
2
.github/workflows/e2e-multicluster-test.yml
vendored
2
.github/workflows/e2e-multicluster-test.yml
vendored
@@ -103,7 +103,7 @@ jobs:
|
||||
run: |
|
||||
make e2e-cleanup
|
||||
make vela-cli
|
||||
make e2e-setup-core
|
||||
make e2e-setup-core-auth
|
||||
make
|
||||
make setup-runtime-e2e-cluster
|
||||
|
||||
|
||||
@@ -147,4 +147,7 @@ subjects:
|
||||
- kind: Group
|
||||
name: kubevela:client
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
- kind: ServiceAccount
|
||||
name: {{ include "kubevela.serviceAccountName" . }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
{{ end }}
|
||||
@@ -20,12 +20,54 @@ metadata:
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: "cluster-admin"
|
||||
name: {{ if .Values.authentication.enabled }} {{ include "kubevela.fullname" . }}:manager {{ else }} "cluster-admin" {{ end }}
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: {{ include "kubevela.serviceAccountName" . }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
|
||||
{{ if .Values.authentication.enabled }}
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: {{ include "kubevela.fullname" . }}:manager
|
||||
rules:
|
||||
- apiGroups: ["core.oam.dev", "terraform.core.oam.dev", "prism.oam.dev"]
|
||||
resources: ["*"]
|
||||
verbs: ["*"]
|
||||
- apiGroups: ["cluster.open-cluster-management.io"]
|
||||
resources: ["managedclusters"]
|
||||
verbs: ["get", "list", "watch"]
|
||||
- apiGroups: [""]
|
||||
resources: ["users", "groups", "serviceaccounts"]
|
||||
verbs: ["impersonate"]
|
||||
- apiGroups: [""]
|
||||
resources: ["namespaces", "secrets", "services"]
|
||||
verbs: ["get", "watch", "list"]
|
||||
- apiGroups: [""]
|
||||
resources: ["configmaps", "events"]
|
||||
verbs: ["*"]
|
||||
- apiGroups: ["apps"]
|
||||
resources: ["controllerrevisions"]
|
||||
verbs: ["*"]
|
||||
- apiGroups: ["apiregistration.k8s.io"]
|
||||
resources: ["apiservices"]
|
||||
verbs: ["get", "list", "watch", "update"]
|
||||
- apiGroups: ["coordination.k8s.io"]
|
||||
resources: ["leases"]
|
||||
verbs: ["*"]
|
||||
- apiGroups: ["admissionregistration.k8s.io"]
|
||||
resources: ["mutatingwebhookconfigurations", "validatingwebhookconfigurations"]
|
||||
verbs: ["get", "list", "watch"]
|
||||
- apiGroups: ["flowcontrol.apiserver.k8s.io"]
|
||||
resources: ["prioritylevelconfigurations", "flowschemas"]
|
||||
verbs: ["get", "list", "watch"]
|
||||
- apiGroups: ["authorization.k8s.io"]
|
||||
resources: ["subjectaccessreviews"]
|
||||
verbs: ["*"]
|
||||
{{ end }}
|
||||
|
||||
---
|
||||
# permissions to do leader election.
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
|
||||
@@ -212,4 +212,7 @@ subjects:
|
||||
- kind: Group
|
||||
name: kubevela:client
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
- kind: ServiceAccount
|
||||
name: {{ include "kubevela.serviceAccountName" . }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
{{ end }}
|
||||
@@ -15,6 +15,7 @@ metadata:
|
||||
|
||||
---
|
||||
|
||||
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
@@ -22,12 +23,54 @@ metadata:
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: "cluster-admin"
|
||||
name: {{ if .Values.authentication.enabled }} {{ include "kubevela.fullname" . }}:manager {{ else }} "cluster-admin" {{ end }}
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: {{ include "kubevela.serviceAccountName" . }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
|
||||
{{ if .Values.authentication.enabled }}
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: {{ include "kubevela.fullname" . }}:manager
|
||||
rules:
|
||||
- apiGroups: ["core.oam.dev", "terraform.core.oam.dev", "prism.oam.dev"]
|
||||
resources: ["*"]
|
||||
verbs: ["*"]
|
||||
- apiGroups: ["cluster.open-cluster-management.io"]
|
||||
resources: ["managedclusters"]
|
||||
verbs: ["get", "list", "watch"]
|
||||
- apiGroups: [""]
|
||||
resources: ["users", "groups", "serviceaccounts"]
|
||||
verbs: ["impersonate"]
|
||||
- apiGroups: [""]
|
||||
resources: ["namespaces", "secrets", "services"]
|
||||
verbs: ["get", "watch", "list"]
|
||||
- apiGroups: [""]
|
||||
resources: ["configmaps", "events"]
|
||||
verbs: ["*"]
|
||||
- apiGroups: ["apps"]
|
||||
resources: ["controllerrevisions"]
|
||||
verbs: ["*"]
|
||||
- apiGroups: ["apiregistration.k8s.io"]
|
||||
resources: ["apiservices"]
|
||||
verbs: ["get", "list", "watch", "update"]
|
||||
- apiGroups: ["coordination.k8s.io"]
|
||||
resources: ["leases"]
|
||||
verbs: ["*"]
|
||||
- apiGroups: ["admissionregistration.k8s.io"]
|
||||
resources: ["mutatingwebhookconfigurations", "validatingwebhookconfigurations"]
|
||||
verbs: ["get", "list", "watch"]
|
||||
- apiGroups: ["flowcontrol.apiserver.k8s.io"]
|
||||
resources: ["prioritylevelconfigurations", "flowschemas"]
|
||||
verbs: ["get", "list", "watch"]
|
||||
- apiGroups: ["authorization.k8s.io"]
|
||||
resources: ["subjectaccessreviews"]
|
||||
verbs: ["*"]
|
||||
{{ end }}
|
||||
|
||||
---
|
||||
# permissions to do leader election.
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
|
||||
@@ -1,14 +1,29 @@
|
||||
|
||||
.PHONY: e2e-setup-core
|
||||
e2e-setup-core:
|
||||
.PHONY: e2e-setup-core-pre-hook
|
||||
e2e-setup-core-pre-hook:
|
||||
sh ./hack/e2e/modify_charts.sh
|
||||
helm upgrade --install --create-namespace --namespace vela-system --set image.pullPolicy=IfNotPresent --set image.repository=vela-core-test --set applicationRevisionLimit=5 --set dependCheckWait=10s --set image.tag=$(GIT_COMMIT) --wait kubevela ./charts/vela-core
|
||||
|
||||
.PHONY: e2e-setup-core-post-hook
|
||||
e2e-setup-core-post-hook:
|
||||
kubectl wait --for=condition=Available deployment/kubevela-vela-core -n vela-system --timeout=180s
|
||||
helm upgrade --install --namespace vela-system --wait oam-rollout --set image.repository=vela-runtime-rollout-test --set image.tag=$(GIT_COMMIT) ./runtime/rollout/charts
|
||||
go run ./e2e/addon/mock &
|
||||
sleep 15
|
||||
bin/vela addon enable rollout
|
||||
|
||||
.PHONY: e2e-setup-core-wo-auth
|
||||
e2e-setup-core-wo-auth:
|
||||
helm upgrade --install --create-namespace --namespace vela-system --set image.pullPolicy=IfNotPresent --set image.repository=vela-core-test --set applicationRevisionLimit=5 --set dependCheckWait=10s --set image.tag=$(GIT_COMMIT) --wait kubevela ./charts/vela-core
|
||||
|
||||
.PHONY: e2e-setup-core-w-auth
|
||||
e2e-setup-core-w-auth:
|
||||
helm upgrade --install --create-namespace --namespace vela-system --set image.pullPolicy=IfNotPresent --set image.repository=vela-core-test --set applicationRevisionLimit=5 --set dependCheckWait=10s --set image.tag=$(GIT_COMMIT) --wait kubevela ./charts/vela-core --set authentication.enabled=true --set authentication.withUser=true --set authentication.groupPattern=*
|
||||
|
||||
.PHONY: e2e-setup-core
|
||||
e2e-setup-core: e2e-setup-core-pre-hook e2e-setup-core-wo-auth e2e-setup-core-post-hook
|
||||
|
||||
.PHONY: e2e-setup-core-auth
|
||||
e2e-setup-core-auth: e2e-setup-core-pre-hook e2e-setup-core-w-auth e2e-setup-core-post-hook
|
||||
|
||||
.PHONY: setup-runtime-e2e-cluster
|
||||
setup-runtime-e2e-cluster:
|
||||
helm upgrade --install --create-namespace --namespace vela-system --kubeconfig=$(RUNTIME_CLUSTER_CONFIG) --set image.pullPolicy=IfNotPresent --set image.repository=vela-runtime-rollout-test --set image.tag=$(GIT_COMMIT) --wait vela-rollout ./runtime/rollout/charts
|
||||
|
||||
@@ -42,6 +42,7 @@ import (
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
|
||||
"github.com/oam-dev/kubevela/apis/types"
|
||||
"github.com/oam-dev/kubevela/pkg/appfile/helm"
|
||||
"github.com/oam-dev/kubevela/pkg/auth"
|
||||
velaclient "github.com/oam-dev/kubevela/pkg/client"
|
||||
"github.com/oam-dev/kubevela/pkg/component"
|
||||
"github.com/oam-dev/kubevela/pkg/cue/definition"
|
||||
@@ -922,6 +923,7 @@ func (af *Appfile) LoadDynamicComponent(ctx context.Context, cli client.Client,
|
||||
return nil, errors.Wrapf(err, "invalid ref-objects component properties")
|
||||
}
|
||||
var uns []*unstructured.Unstructured
|
||||
ctx = auth.ContextWithUserInfo(ctx, af.app)
|
||||
for _, selector := range spec.Objects {
|
||||
objs, err := component.SelectRefObjectsForDispatch(ctx, component.ReferredObjectsDelegatingClient(cli, af.ReferredObjects), af.Namespace, comp.Name, selector)
|
||||
if err != nil {
|
||||
|
||||
@@ -34,6 +34,7 @@ import (
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha1"
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
|
||||
"github.com/oam-dev/kubevela/apis/types"
|
||||
"github.com/oam-dev/kubevela/pkg/auth"
|
||||
"github.com/oam-dev/kubevela/pkg/component"
|
||||
"github.com/oam-dev/kubevela/pkg/cue/definition"
|
||||
"github.com/oam-dev/kubevela/pkg/cue/packages"
|
||||
@@ -332,6 +333,7 @@ func (p *Parser) parseReferredObjectsFromRevision(af *Appfile) error {
|
||||
}
|
||||
|
||||
func (p *Parser) parseReferredObjects(ctx context.Context, af *Appfile) error {
|
||||
ctx = auth.ContextWithUserInfo(ctx, af.app)
|
||||
for _, comp := range af.Components {
|
||||
if comp.Type != v1alpha1.RefObjectsComponentType {
|
||||
continue
|
||||
|
||||
@@ -237,7 +237,7 @@ func (h *AppHandler) checkComponentHealth(appParser *appfile.Parser, appRev *v1b
|
||||
return false, err
|
||||
}
|
||||
|
||||
_, isHealth, err := h.collectHealthStatus(ctx, wl, appRev, overrideNamespace)
|
||||
_, isHealth, err := h.collectHealthStatus(auth.ContextWithUserInfo(ctx, h.app), wl, appRev, overrideNamespace)
|
||||
return isHealth, err
|
||||
}
|
||||
}
|
||||
@@ -288,7 +288,7 @@ func (h *AppHandler) applyComponentFunc(appParser *appfile.Parser, appRev *v1bet
|
||||
if DisableResourceApplyDoubleCheck {
|
||||
return readyWorkload, readyTraits, true, nil
|
||||
}
|
||||
workload, traits, err := getComponentResources(ctx, manifest, wl.SkipApplyWorkload, h.r.Client)
|
||||
workload, traits, err := getComponentResources(auth.ContextWithUserInfo(ctx, h.app), manifest, wl.SkipApplyWorkload, h.r.Client)
|
||||
return workload, traits, true, err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -898,6 +898,7 @@ func cleanUpWorkflowComponentRevision(ctx context.Context, h *AppHandler) error
|
||||
}
|
||||
// collect component revision in use
|
||||
compRevisionInUse := map[string]map[string]struct{}{}
|
||||
ctx = auth.ContextWithUserInfo(ctx, h.app)
|
||||
for i, resource := range h.app.Status.AppliedResources {
|
||||
compName := resource.Name
|
||||
ns := resource.Namespace
|
||||
|
||||
@@ -46,7 +46,7 @@ var defaultFeatureGates = map[featuregate.Feature]featuregate.FeatureSpec{
|
||||
DeprecatedPolicySpec: {Default: false, PreRelease: featuregate.Alpha},
|
||||
LegacyObjectTypeIdentifier: {Default: false, PreRelease: featuregate.Alpha},
|
||||
DeprecatedObjectLabelSelector: {Default: false, PreRelease: featuregate.Alpha},
|
||||
LegacyResourceTrackerGC: {Default: true, PreRelease: featuregate.Alpha},
|
||||
LegacyResourceTrackerGC: {Default: false, PreRelease: featuregate.Beta},
|
||||
EnableSuspendOnFailure: {Default: false, PreRelease: featuregate.Alpha},
|
||||
AuthenticateApplication: {Default: false, PreRelease: featuregate.Alpha},
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ package resourcekeeper
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/crossplane/crossplane-runtime/pkg/meta"
|
||||
@@ -30,10 +31,13 @@ import (
|
||||
v12 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/common"
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha1"
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
|
||||
"github.com/oam-dev/kubevela/pkg/features"
|
||||
"github.com/oam-dev/kubevela/pkg/multicluster"
|
||||
"github.com/oam-dev/kubevela/pkg/oam"
|
||||
"github.com/oam-dev/kubevela/pkg/utils"
|
||||
@@ -56,6 +60,7 @@ var _ = Describe("Test ResourceKeeper garbage collection", func() {
|
||||
})
|
||||
|
||||
It("Test gcHandler garbage collect legacy RT", func() {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(&testing.T{}, utilfeature.DefaultFeatureGate, features.LegacyResourceTrackerGC, true)()
|
||||
version.VelaVersion = velaVersionNumberToUpgradeResourceTracker
|
||||
ctx := context.Background()
|
||||
cli := multicluster.NewFakeClient(testClient)
|
||||
|
||||
@@ -35,6 +35,7 @@ func (h *resourceKeeper) StateKeep(ctx context.Context) error {
|
||||
if h.applyOncePolicy != nil && h.applyOncePolicy.Enable && h.applyOncePolicy.Rules == nil {
|
||||
return nil
|
||||
}
|
||||
ctx = auth.ContextWithUserInfo(ctx, h.app)
|
||||
for _, rt := range []*v1beta1.ResourceTracker{h._currentRT, h._rootRT} {
|
||||
if rt != nil && rt.GetDeletionTimestamp() == nil {
|
||||
for _, mr := range rt.Spec.ManagedResources {
|
||||
@@ -45,7 +46,6 @@ func (h *resourceKeeper) StateKeep(ctx context.Context) error {
|
||||
if mr.Deleted {
|
||||
if entry.exists && entry.obj != nil && entry.obj.GetDeletionTimestamp() == nil {
|
||||
deleteCtx := multicluster.ContextWithClusterName(ctx, mr.Cluster)
|
||||
deleteCtx = auth.ContextWithUserInfo(deleteCtx, h.app)
|
||||
if err := h.Client.Delete(deleteCtx, entry.obj); err != nil {
|
||||
return errors.Wrapf(err, "failed to delete outdated resource %s in resourcetracker %s", mr.ResourceKey(), rt.Name)
|
||||
}
|
||||
@@ -64,7 +64,6 @@ func (h *resourceKeeper) StateKeep(ctx context.Context) error {
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to apply once resource %s from resourcetracker %s", mr.ResourceKey(), rt.Name)
|
||||
}
|
||||
applyCtx = auth.ContextWithUserInfo(applyCtx, h.app)
|
||||
if err = h.applicator.Apply(applyCtx, manifest, apply.MustBeControlledByApp(h.app)); err != nil {
|
||||
return errors.Wrapf(err, "failed to re-apply resource %s from resourcetracker %s", mr.ResourceKey(), rt.Name)
|
||||
}
|
||||
|
||||
@@ -134,7 +134,8 @@ var _ = Describe("Test MultiCluster Rollout", func() {
|
||||
verifySucceed(componentName + "-v1")
|
||||
})
|
||||
|
||||
It("Test Rollout with health check policy, guarantee health scope controller work ", func() {
|
||||
// HealthScopeController will not work properly with authentication module now
|
||||
PIt("Test Rollout with health check policy, guarantee health scope controller work ", func() {
|
||||
app := &v1beta1.Application{}
|
||||
appYaml, err := ioutil.ReadFile("./testdata/app/multi-cluster-health-policy.yaml")
|
||||
Expect(err).Should(Succeed())
|
||||
|
||||
@@ -344,9 +344,11 @@ var _ = Describe("Test multicluster scenario", func() {
|
||||
envs[1].Placement.ClusterSelector.Name = multicluster.ClusterLocalName
|
||||
bs, err = json.Marshal(&v1alpha1.EnvBindingSpec{Envs: envs})
|
||||
Expect(err).Should(Succeed())
|
||||
Expect(k8sClient.Get(hubCtx, namespacedName, app)).Should(Succeed())
|
||||
app.Spec.Policies[0].Properties.Raw = bs
|
||||
Expect(k8sClient.Update(hubCtx, app)).Should(Succeed())
|
||||
Eventually(func(g Gomega) {
|
||||
g.Expect(k8sClient.Get(hubCtx, namespacedName, app)).Should(Succeed())
|
||||
app.Spec.Policies[0].Properties.Raw = bs
|
||||
g.Expect(k8sClient.Update(hubCtx, app)).Should(Succeed())
|
||||
}, 15*time.Second).Should(Succeed())
|
||||
Eventually(func(g Gomega) {
|
||||
deploys := &appsv1.DeploymentList{}
|
||||
g.Expect(k8sClient.List(hubCtx, deploys, client.InNamespace(testNamespace))).Should(Succeed())
|
||||
|
||||
Reference in New Issue
Block a user