Skip to content

Commit

Permalink
[no-cluster-rbac] OSSM-1420: Ensure istiod can run with no cluster-sc…
Browse files Browse the repository at this point in the history
…oped privileges (maistra#513) (maistra#548)

Co-authored-by: Marko Lukša <marko.luksa@gmail.com>
  • Loading branch information
jewertow and luksa committed Jul 17, 2023
1 parent 15997eb commit c16e21d
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 35 deletions.
8 changes: 4 additions & 4 deletions pilot/pkg/config/kube/crdclient/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,6 @@ func NewForSchemas(client kube.Client, opts Option, schemas collection.Schemas)
kinds: map[config.GroupVersionKind]*cacheHandler{},
handlers: map[config.GroupVersionKind][]model.EventHandler{},
client: client,
crdWatcher: crdwatcher.NewController(client),
logger: scope.WithLabels("controller", opts.Identifier),
namespacesFilter: opts.NamespacesFilter,
crdWatches: map[config.GroupVersionKind]*waiter{
Expand All @@ -162,11 +161,12 @@ func NewForSchemas(client kube.Client, opts Option, schemas collection.Schemas)
},
}

out.crdWatcher.AddCallBack(func(name string) {
handleCRDAdd(out, name)
})
var known map[string]struct{}
if opts.EnableCRDScan {
out.crdWatcher = crdwatcher.NewController(client)
out.crdWatcher.AddCallBack(func(name string) {
handleCRDAdd(out, name)
})
var err error
known, err = knownCRDs(client.Ext())
if err != nil {
Expand Down
14 changes: 5 additions & 9 deletions pilot/pkg/credentials/kube/secrets.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import (
authorizationv1 "k8s.io/api/authorization/v1"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/fields"
sa "k8s.io/apiserver/pkg/authentication/serviceaccount"
authorizationv1client "k8s.io/client-go/kubernetes/typed/authorization/v1"

Expand Down Expand Up @@ -80,15 +79,12 @@ func NewCredentialsController(kc kube.Client) *CredentialsController {
// This makes the assumption we will never care about Helm secrets or SA token secrets - two common
// large secrets in clusters.
// This is a best effort optimization only; the code would behave correctly if we watched all secrets.
fieldSelector := fields.AndSelectors(
fields.OneTermNotEqualSelector("type", "helm.sh/release.v1"),
fields.OneTermNotEqualSelector("type", string(v1.SecretTypeServiceAccountToken))).String()
secrets := kclient.NewFiltered[*v1.Secret](kc, kclient.Filter{
FieldSelector: fieldSelector,
})

// TODO: Shouldn't we use "github.com/maistra/xns-informer/pkg/generated/kube/core/v1".NewFilteredSecretInformer with
// fieldSelector := fields.AndSelectors(
// fields.OneTermNotEqualSelector("type", "helm.sh/release.v1"),
// fields.OneTermNotEqualSelector("type", string(v1.SecretTypeServiceAccountToken))).String()
return &CredentialsController{
secrets: secrets,
secrets: kclient.New[*v1.Secret](kc),
sar: kc.Kube().AuthorizationV1().SubjectAccessReviews(),
authorizationCache: make(map[authorizationKey]authorizationResponse),
}
Expand Down
2 changes: 1 addition & 1 deletion pilot/pkg/leaderelection/leaderelection.go
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ func NewLeaderElectionMulticluster(namespace, name, electionID, revision string,

func newLeaderElection(namespace, name, electionID, revision string, perRevision bool, remote bool, client kube.Client) *LeaderElection {
var watcher revisions.DefaultWatcher
if features.EnableLeaderElection && features.PrioritizedLeaderElection {
if features.EnableLeaderElection && features.PrioritizedLeaderElection && client.GetMemberRoll() == nil {
watcher = revisions.NewDefaultWatcher(client, revision)
}
if name == "" {
Expand Down
44 changes: 23 additions & 21 deletions pilot/pkg/serviceregistry/kube/controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -317,29 +317,31 @@ func NewController(kubeClient kubelib.Client, options Options) *Controller {
configCluster: options.ConfigCluster,
}

c.namespaces = kclient.New[*v1.Namespace](kubeClient)
// Don't start the namespace informer if Maistra's MemberRoll is in use.
if c.opts.SystemNamespace != "" && options.MemberRollName == "" {
registerHandlers[*v1.Namespace](
c,
c.namespaces,
"Namespaces",
func(old *v1.Namespace, cur *v1.Namespace, event model.Event) error {
if cur.Name == c.opts.SystemNamespace {
return c.onSystemNamespaceEvent(old, cur, event)
}
return nil
},
nil,
)
}

if c.opts.DiscoveryNamespacesFilter == nil {
c.opts.DiscoveryNamespacesFilter = namespace.NewDiscoveryNamespacesFilter(c.namespaces, options.MeshWatcher.Mesh().DiscoverySelectors)
if options.MemberRollName == "" {
c.namespaces = kclient.New[*v1.Namespace](kubeClient)
if c.opts.SystemNamespace != "" {
registerHandlers[*v1.Namespace](
c,
c.namespaces,
"Namespaces",
func(old *v1.Namespace, cur *v1.Namespace, event model.Event) error {
if cur.Name == c.opts.SystemNamespace {
return c.onSystemNamespaceEvent(old, cur, event)
}
return nil
},
nil,
)
}
if c.opts.DiscoveryNamespacesFilter == nil {
c.opts.DiscoveryNamespacesFilter = namespace.NewDiscoveryNamespacesFilter(c.namespaces, options.MeshWatcher.Mesh().DiscoverySelectors)
}
c.initDiscoveryHandlers(options.MeshWatcher, c.opts.DiscoveryNamespacesFilter)
} else if c.opts.DiscoveryNamespacesFilter == nil {
c.opts.DiscoveryNamespacesFilter = namespace.NewMaistraDiscoveryNamespacesFilter(kubeClient.GetMemberRoll())
}

c.initDiscoveryHandlers(options.MeshWatcher, c.opts.DiscoveryNamespacesFilter)

c.services = kclient.NewFiltered[*v1.Service](kubeClient, kclient.Filter{ObjectFilter: c.opts.DiscoveryNamespacesFilter.Filter})

registerHandlers[*v1.Service](c, c.services, "Services", c.onServiceEvent, nil)
Expand Down Expand Up @@ -659,7 +661,7 @@ func (c *Controller) HasSynced() bool {
}

func (c *Controller) informersSynced() bool {
if !c.namespaces.HasSynced() ||
if (c.namespaces != nil && !c.namespaces.HasSynced()) ||
!c.services.HasSynced() ||
!c.endpoints.HasSynced() ||
!c.pods.pods.HasSynced() ||
Expand Down
67 changes: 67 additions & 0 deletions pkg/kube/namespace/filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (

"istio.io/istio/pkg/kube/controllers"
"istio.io/istio/pkg/kube/kclient"
memberroll "istio.io/istio/pkg/servicemesh/controller"
"istio.io/istio/pkg/util/sets"
"istio.io/pkg/log"
)
Expand Down Expand Up @@ -240,3 +241,69 @@ func (d *discoveryNamespacesFilter) isSelected(labels labels.Set) bool {

return false
}

type maistraDiscoveryNamespacesFilter struct {
lock sync.RWMutex
namespaces sets.String
}

func NewMaistraDiscoveryNamespacesFilter(mrc memberroll.MemberRollController) DiscoveryNamespacesFilter {
d := &maistraDiscoveryNamespacesFilter{}
mrc.Register(d, "MaistraDiscoveryNamespacesFilter")
return d
}

func (d *maistraDiscoveryNamespacesFilter) SetNamespaces(namespaces []string) {
d.lock.Lock()
defer d.lock.Unlock()
d.namespaces = sets.New[string](namespaces...)
}

func (d *maistraDiscoveryNamespacesFilter) Filter(obj interface{}) bool {
// xns-informers make sure we only receive objects in member namespaces
return true
}

// FilterNamespace is not implemented, because Maistra does not filter namespaces;
// this function should never be called if memberRollName is specified, so it's safe to call panic.
func (d *maistraDiscoveryNamespacesFilter) FilterNamespace(nsMeta metav1.ObjectMeta) bool {
panic("Not implemented")
}

// SelectorsChanged is not implemented, because Maistra does not filter namespaces by selectors;
// this function should never be called if memberRollName is specified, so it's safe to call panic.
func (d *maistraDiscoveryNamespacesFilter) SelectorsChanged(_ []*metav1.LabelSelector) (selectedNamespaces []string, deselectedNamespaces []string) {
panic("Not implemented")
}

// SyncNamespaces is not implemented, because this function should never be called if memberRollName is specified,
// so it's safe to call panic.
func (d *maistraDiscoveryNamespacesFilter) SyncNamespaces() error {
panic("Not implemented")
}

// NamespaceCreated is not implemented, because added namespaces are handled by serviceMeshMemberRollListener;
// this function should never be called if memberRollName is specified, so it's safe to call panic.
func (d *maistraDiscoveryNamespacesFilter) NamespaceCreated(_ metav1.ObjectMeta) (membershipChanged bool) {
panic("Not implemented")
}

// NamespaceUpdated is not implemented, because updated namespaces are handled by serviceMeshMemberRollListener;
// this function should never be called if memberRollName is specified, so it's safe to call panic.
func (d *maistraDiscoveryNamespacesFilter) NamespaceUpdated(_, _ metav1.ObjectMeta) (membershipChanged bool, namespaceAdded bool) {
panic("Not implemented")
}

// NamespaceDeleted is not implemented, because deleted namespaces are handled by serviceMeshMemberRollListener;
// this function should never be called if memberRollName is specified, so it's safe to call panic.
func (d *maistraDiscoveryNamespacesFilter) NamespaceDeleted(_ metav1.ObjectMeta) (membershipChanged bool) {
panic("Not implemented")
}

func (d *maistraDiscoveryNamespacesFilter) GetMembers() sets.String {
d.lock.RLock()
defer d.lock.RUnlock()
members := sets.New[string]()
members.InsertAll(d.namespaces.UnsortedList()...)
return members
}

0 comments on commit c16e21d

Please sign in to comment.