@@ -149,13 +149,6 @@ func (c *GuardianComponent) Objects() ([]client.Object, []client.Object) {
149149
150150 if c .cfg .Installation .Variant == operatorv1 .TigeraSecureEnterprise {
151151 objs = append (objs ,
152- // Add tigera-manager service account for impersonation. In managed clusters, the tigera-manager
153- // service account is always within the tigera-manager namespace - regardless of (multi)tenancy mode.
154- CreateNamespace (ManagerNamespace , c .cfg .Installation .KubernetesProvider , PSSRestricted , c .cfg .Installation .Azure ),
155- managerServiceAccount (ManagerNamespace ),
156- managerClusterRole (true , c .cfg .Installation .KubernetesProvider , nil ),
157- managerClusterRoleBinding (nil , []string {ManagerNamespace }, []string {}),
158-
159152 // Install default UI settings for this managed cluster.
160153 managerClusterWideSettingsGroup (),
161154 managerUserSpecificSettingsGroup (),
@@ -239,6 +232,8 @@ func (c *GuardianComponent) clusterRole() *rbacv1.ClusterRole {
239232 Verbs : []string {"impersonate" },
240233 })
241234
235+ policyRules = append (policyRules , rulesForManagementClusterRequests (c .cfg .OpenShift )... )
236+
242237 if c .cfg .OpenShift {
243238 policyRules = append (policyRules , rbacv1.PolicyRule {
244239 APIGroups : []string {"security.openshift.io" },
@@ -690,6 +685,292 @@ func GuardianService(clusterDomain string) string {
690685 return fmt .Sprintf ("https://%s.%s.svc.%s:%d" , GuardianServiceName , GuardianNamespace , clusterDomain , 443 )
691686}
692687
688+ // rulesForManagementClusterRequests returns the set of RBAC rules needed by Guardian in order to
689+ // satisfy requests from the management cluster over the tunnel.
690+ func rulesForManagementClusterRequests (isOpenShift bool ) []rbacv1.PolicyRule {
691+
692+ rules := []rbacv1.PolicyRule {
693+ // Common rules required to handle requests from multiple components in the management cluster.
694+ {
695+ // ID uses read-only permissions and KubeController uses both read and write verbs.
696+ APIGroups : []string {"" },
697+ Resources : []string {"configmaps" },
698+ Verbs : []string {"create" , "delete" , "get" , "list" , "update" , "watch" },
699+ },
700+ {
701+ // Allows Linseed to watch namespaces before copying its token.
702+ // Also enables PolicyRecommendation to watch namespaces,
703+ // and Manager/KubeController to list them.
704+ APIGroups : []string {"" },
705+ Resources : []string {"namespaces" },
706+ Verbs : []string {"get" , "list" , "watch" },
707+ },
708+ {
709+ // KubeController watches Nodes to monitor for deletions.
710+ // Manager performs a list operation on Nodes.
711+ APIGroups : []string {"" },
712+ Resources : []string {"nodes" },
713+ Verbs : []string {"get" , "list" , "watch" },
714+ },
715+ {
716+ // KubeController watches Pods to verify existence for IPAM garbage collection.
717+ // Manager performs get operations on Pods.
718+ APIGroups : []string {"" },
719+ Resources : []string {"pods" },
720+ Verbs : []string {"get" , "list" , "watch" },
721+ },
722+ {
723+ // The Federated Services Controller needs access to the remote kubeconfig secret
724+ // in order to create a remote syncer.
725+ APIGroups : []string {"" },
726+ Resources : []string {"secrets" },
727+ Verbs : []string {"get" , "list" , "watch" },
728+ },
729+ {
730+ // Manager uses list; KubeController uses 'get', 'list', 'watch', 'update'.
731+ APIGroups : []string {"" },
732+ Resources : []string {"services" },
733+ Verbs : []string {"get" , "list" , "update" , "watch" },
734+ },
735+ {
736+ // Needed by KubeController to validate licenses; also used by ID.
737+ APIGroups : []string {"crd.projectcalico.org" },
738+ Resources : []string {"licensekeys" },
739+ Verbs : []string {"get" , "watch" },
740+ },
741+ {
742+ // Manager uses list; PolicyRecommendation & ID uses all verbs.
743+ APIGroups : []string {"projectcalico.org" },
744+ Resources : []string {
745+ "globalnetworksets" ,
746+ "networkpolicies" ,
747+ "tier.networkpolicies" ,
748+ "stagednetworkpolicies" ,
749+ "tier.stagednetworkpolicies" ,
750+ },
751+ Verbs : []string {"create" , "delete" , "get" , "list" , "patch" , "update" , "watch" },
752+ },
753+ {
754+ // Manager uses list; PolicyRecommendation uses all verbs.
755+ APIGroups : []string {"projectcalico.org" },
756+ Resources : []string {"tiers" },
757+ Verbs : []string {"create" , "delete" , "get" , "list" , "patch" , "update" , "watch" },
758+ },
759+
760+ // Rules needed by guardian to handle manager requests.
761+ {
762+ APIGroups : []string {"" },
763+ Resources : []string {"events" },
764+ Verbs : []string {"list" },
765+ },
766+ {
767+ APIGroups : []string {"" },
768+ Resources : []string {"serviceaccounts" },
769+ Verbs : []string {"impersonate" , "list" },
770+ },
771+ {
772+ // When a request is made in the manager UI, they are proxied through the Voltron backend server. If the
773+ // request is targeting a k8s api or when it is targeting a managed cluster, Voltron will authenticate the
774+ // user based on the auth header and then impersonate the user.
775+ APIGroups : []string {"" },
776+ Resources : []string {"groups" , "users" },
777+ Verbs : []string {"impersonate" },
778+ },
779+ {
780+ // Allow query server talk to Prometheus via the manager user.
781+ APIGroups : []string {"" },
782+ Resources : []string {"services/proxy" },
783+ ResourceNames : []string {
784+ "calico-node-prometheus:9090" ,
785+ "https:tigera-api:8080" ,
786+ },
787+ Verbs : []string {"create" , "get" },
788+ },
789+ {
790+ APIGroups : []string {"apps" },
791+ Resources : []string {"daemonsets" , "replicasets" , "statefulsets" },
792+ Verbs : []string {"list" },
793+ },
794+ {
795+ APIGroups : []string {"authentication.k8s.io" },
796+ Resources : []string {"tokenreviews" },
797+ Verbs : []string {"create" },
798+ },
799+ {
800+ APIGroups : []string {"authorization.k8s.io" },
801+ Resources : []string {"subjectaccessreviews" },
802+ Verbs : []string {"create" },
803+ },
804+ {
805+ APIGroups : []string {"networking.k8s.io" },
806+ Resources : []string {"networkpolicies" },
807+ Verbs : []string {"get" , "list" },
808+ },
809+ {
810+ APIGroups : []string {"policy.networking.k8s.io" },
811+ Resources : []string {"adminnetworkpolicies" , "baselineadminnetworkpolicies" },
812+ Verbs : []string {"list" },
813+ },
814+ {
815+ APIGroups : []string {"projectcalico.org" },
816+ Resources : []string {"alertexceptions" },
817+ Verbs : []string {"get" , "list" , "update" },
818+ },
819+ {
820+ APIGroups : []string {"projectcalico.org" },
821+ Resources : []string {"felixconfigurations" },
822+ ResourceNames : []string {"default" },
823+ Verbs : []string {"get" },
824+ },
825+ {
826+ APIGroups : []string {"projectcalico.org" },
827+ Resources : []string {
828+ "globalnetworkpolicies" ,
829+ "networksets" ,
830+ "stagedglobalnetworkpolicies" ,
831+ "stagedkubernetesnetworkpolicies" ,
832+ "tier.globalnetworkpolicies" ,
833+ "tier.stagedglobalnetworkpolicies" ,
834+ },
835+ Verbs : []string {"list" },
836+ },
837+ {
838+ APIGroups : []string {"projectcalico.org" },
839+ Resources : []string {"hostendpoints" },
840+ Verbs : []string {"list" },
841+ },
842+
843+ // Rules needed by guardian to handle policy recommendation requests.
844+ {
845+ APIGroups : []string {"projectcalico.org" },
846+ Resources : []string {
847+ "policyrecommendationscopes" ,
848+ "policyrecommendationscopes/status" ,
849+ },
850+ Verbs : []string {"create" , "delete" , "get" , "list" , "patch" , "update" , "watch" },
851+ },
852+
853+ // Rules needed by guardian to handle calico-kube-controller requests.
854+ {
855+ // Nodes are watched to monitor for deletions.
856+ APIGroups : []string {"" },
857+ Resources : []string {"endpoints" },
858+ Verbs : []string {"create" , "delete" , "get" , "list" , "update" , "watch" },
859+ },
860+ {
861+ APIGroups : []string {"" },
862+ Resources : []string {"services/status" },
863+ Verbs : []string {"get" , "list" , "update" , "watch" },
864+ },
865+ {
866+ // Needs to manage hostendpoints.
867+ APIGroups : []string {"crd.projectcalico.org" },
868+ Resources : []string {"hostendpoints" },
869+ Verbs : []string {"create" , "delete" , "get" , "list" , "update" , "watch" },
870+ },
871+ {
872+ // Needs access to update clusterinformations.
873+ APIGroups : []string {"crd.projectcalico.org" },
874+ Resources : []string {"clusterinformations" },
875+ Verbs : []string {"create" , "get" , "list" , "update" , "watch" },
876+ },
877+ {
878+ // Needs to manipulate kubecontrollersconfiguration, which contains its config.
879+ // It creates a default if none exists, and updates status as well.
880+ APIGroups : []string {"crd.projectcalico.org" },
881+ Resources : []string {"kubecontrollersconfigurations" },
882+ Verbs : []string {"create" , "get" , "list" , "update" , "watch" },
883+ },
884+ {
885+ APIGroups : []string {"crd.projectcalico.org" },
886+ Resources : []string {"tiers" },
887+ Verbs : []string {"create" },
888+ },
889+ {
890+ APIGroups : []string {"crd.projectcalico.org" , "projectcalico.org" },
891+ Resources : []string {"deeppacketinspections" },
892+ Verbs : []string {"get" , "list" , "watch" },
893+ },
894+ {
895+ APIGroups : []string {"crd.projectcalico.org" },
896+ Resources : []string {"deeppacketinspections/status" },
897+ Verbs : []string {"update" },
898+ },
899+ {
900+ APIGroups : []string {"crd.projectcalico.org" },
901+ Resources : []string {"packetcaptures" },
902+ Verbs : []string {"get" , "list" , "update" },
903+ },
904+ {
905+ APIGroups : []string {"crd.projectcalico.org" },
906+ Resources : []string {"remoteclusterconfigurations" },
907+ Verbs : []string {"get" , "list" , "watch" },
908+ },
909+ {
910+ APIGroups : []string {"projectcalico.org" },
911+ Resources : []string {"licensekeys" },
912+ Verbs : []string {"create" , "get" , "list" , "update" , "watch" },
913+ },
914+ {
915+ // Grant permissions to access ClusterInformation resources in managed clusters.
916+ APIGroups : []string {"projectcalico.org" },
917+ Resources : []string {"clusterinformations" },
918+ Verbs : []string {"get" , "list" , "watch" },
919+ },
920+ {
921+ APIGroups : []string {"usage.tigera.io" },
922+ Resources : []string {"licenseusagereports" },
923+ Verbs : []string {"create" , "delete" , "get" , "list" , "update" , "watch" },
924+ },
925+
926+ // Rules needed by guardian to handle Intrusion detection requests.
927+ {
928+ APIGroups : []string {"" },
929+ Resources : []string {"podtemplates" },
930+ Verbs : []string {"get" },
931+ },
932+ {
933+ APIGroups : []string {"apps" },
934+ Resources : []string {"deployments" },
935+ Verbs : []string {"get" },
936+ },
937+ {
938+ APIGroups : []string {"crd.projectcalico.org" },
939+ Resources : []string {"alertexceptions" },
940+ Verbs : []string {"get" , "list" },
941+ },
942+ {
943+ APIGroups : []string {"crd.projectcalico.org" },
944+ Resources : []string {"securityeventwebhooks" },
945+ Verbs : []string {"get" , "list" , "update" , "watch" },
946+ },
947+ {
948+ APIGroups : []string {"projectcalico.org" },
949+ Resources : []string {
950+ "globalalerts" ,
951+ "globalalerts/status" ,
952+ "globalthreatfeeds" ,
953+ "globalthreatfeeds/status" ,
954+ },
955+ Verbs : []string {"create" , "delete" , "get" , "list" , "patch" , "update" , "watch" },
956+ },
957+ }
958+
959+ // Rules needed by policy recommendation in openshift.
960+ if isOpenShift {
961+ rules = append (rules ,
962+ rbacv1.PolicyRule {
963+ APIGroups : []string {"security.openshift.io" },
964+ Resources : []string {"securitycontextconstraints" },
965+ Verbs : []string {"use" },
966+ ResourceNames : []string {securitycontextconstraints .HostNetworkV2 },
967+ },
968+ )
969+ }
970+
971+ return rules
972+ }
973+
693974func deprecatedObjects () []client.Object {
694975 return []client.Object {
695976 // All the Guardian objects were moved to "calico-system" circa Calico v3.30, and so the legacy tigera-guardian
@@ -708,5 +989,23 @@ func deprecatedObjects() []client.Object {
708989 TypeMeta : metav1.TypeMeta {Kind : "ClusterRoleBinding" , APIVersion : "rbac.authorization.k8s.io/v1" },
709990 ObjectMeta : metav1.ObjectMeta {Name : "tigera-guardian" },
710991 },
992+
993+ // Remove manager namespace objects since the guardian identity is responsible for handling manager requests
994+ & corev1.ServiceAccount {
995+ TypeMeta : metav1.TypeMeta {Kind : "ServiceAccount" , APIVersion : "v1" },
996+ ObjectMeta : metav1.ObjectMeta {Name : "tigera-manager" , Namespace : "tigera-manager" },
997+ },
998+ & corev1.Namespace {
999+ TypeMeta : metav1.TypeMeta {Kind : "Namespace" , APIVersion : "v1" },
1000+ ObjectMeta : metav1.ObjectMeta {Name : "tigera-manager" },
1001+ },
1002+ & rbacv1.ClusterRole {
1003+ TypeMeta : metav1.TypeMeta {Kind : "ClusterRole" , APIVersion : "rbac.authorization.k8s.io/v1" },
1004+ ObjectMeta : metav1.ObjectMeta {Name : "tigera-manager-role" },
1005+ },
1006+ & rbacv1.ClusterRoleBinding {
1007+ TypeMeta : metav1.TypeMeta {Kind : "ClusterRoleBinding" , APIVersion : "rbac.authorization.k8s.io/v1" },
1008+ ObjectMeta : metav1.ObjectMeta {Name : "tigera-manager-binding" },
1009+ },
7111010 }
7121011}
0 commit comments