Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Separate calico-node and calico-cni-plugin service accounts #2393

Merged
merged 15 commits into from
Mar 24, 2023
Merged
106 changes: 98 additions & 8 deletions pkg/render/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ const (
CalicoNodeMetricsService = "calico-node-metrics"
NodePrometheusTLSServerSecret = "calico-node-prometheus-server-tls"
CalicoNodeObjectName = "calico-node"
CalicoCNIPluginObjectName = "calico-cni-plugin"
)

var (
Expand Down Expand Up @@ -182,6 +183,9 @@ func (c *nodeComponent) Objects() ([]client.Object, []client.Object) {
c.nodeServiceAccount(),
c.nodeRole(),
c.nodeRoleBinding(),
c.cniPluginServiceAccount(),
c.cniPluginRole(),
c.cniPluginRoleBinding(),
}

// These are objects to keep even when we're terminating
Expand Down Expand Up @@ -254,6 +258,23 @@ func (c *nodeComponent) nodeServiceAccount() *corev1.ServiceAccount {
}
}

// cniPluginServiceAccount creates the Calico CNI plugin's service account.
func (c *nodeComponent) cniPluginServiceAccount() *corev1.ServiceAccount {
finalizer := []string{}
if !c.cfg.Terminating {
finalizer = []string{NodeFinalizer}
}

return &corev1.ServiceAccount{
TypeMeta: metav1.TypeMeta{Kind: "ServiceAccount", APIVersion: "v1"},
ObjectMeta: metav1.ObjectMeta{
Name: CalicoCNIPluginObjectName,
Namespace: common.CalicoNamespace,
Finalizers: finalizer,
},
}
}

// nodeRoleBinding creates a clusterrolebinding giving the node service account the required permissions to operate.
func (c *nodeComponent) nodeRoleBinding() *rbacv1.ClusterRoleBinding {
finalizer := []string{}
Expand Down Expand Up @@ -286,6 +307,34 @@ func (c *nodeComponent) nodeRoleBinding() *rbacv1.ClusterRoleBinding {
return crb
}

// cniPluginRoleBinding creates a rolebinding giving the Calico CNI plugin service account the required permissions to operate.
func (c *nodeComponent) cniPluginRoleBinding() *rbacv1.ClusterRoleBinding {
finalizer := []string{}
if !c.cfg.Terminating {
finalizer = []string{NodeFinalizer}
}
crb := &rbacv1.ClusterRoleBinding{
TypeMeta: metav1.TypeMeta{Kind: "ClusterRoleBinding", APIVersion: "rbac.authorization.k8s.io/v1"},
ObjectMeta: metav1.ObjectMeta{
Name: CalicoCNIPluginObjectName,
Finalizers: finalizer,
},
RoleRef: rbacv1.RoleRef{
APIGroup: "rbac.authorization.k8s.io",
Kind: "ClusterRole",
Name: CalicoCNIPluginObjectName,
},
Subjects: []rbacv1.Subject{
{
Kind: "ServiceAccount",
Name: CalicoCNIPluginObjectName,
Namespace: common.CalicoNamespace,
},
},
}
return crb
}

// nodeRole creates the clusterrole containing policy rules that allow the node daemonset to operate normally.
func (c *nodeComponent) nodeRole() *rbacv1.ClusterRole {
finalizer := []string{}
Expand Down Expand Up @@ -347,7 +396,7 @@ func (c *nodeComponent) nodeRole() *rbacv1.ClusterRole {
// Used for creating service account tokens to be used by the CNI plugin.
APIGroups: []string{""},
Resources: []string{"serviceaccounts/token"},
ResourceNames: []string{"calico-node"},
ResourceNames: []string{"calico-cni-plugin"},
Verbs: []string{"create"},
},
{
Expand All @@ -360,6 +409,7 @@ func (c *nodeComponent) nodeRole() *rbacv1.ClusterRole {
// For monitoring Calico-specific configuration.
APIGroups: []string{"crd.projectcalico.org"},
Resources: []string{
"bgpfilters",
"bgpconfigurations",
"bgppeers",
"blockaffinities",
Expand Down Expand Up @@ -437,13 +487,6 @@ func (c *nodeComponent) nodeRole() *rbacv1.ClusterRole {
Resources: []string{"blockaffinities"},
Verbs: []string{"watch"},
},
{
caseydavenport marked this conversation as resolved.
Show resolved Hide resolved
// Allows Calico to use the K8s TokenRequest API to create the tokens used by the CNI plugin.
APIGroups: []string{""},
Resources: []string{"serviceaccounts/token"},
ResourceNames: []string{"calico-node"},
Verbs: []string{"create"},
},
},
}
if c.cfg.Installation.Variant == operatorv1.TigeraSecureEnterprise {
Expand Down Expand Up @@ -493,6 +536,53 @@ func (c *nodeComponent) nodeRole() *rbacv1.ClusterRole {
return role
}

// cniPluginRole creates the role containing policy rules that allow the Calico CNI plugin to operate normally.
func (c *nodeComponent) cniPluginRole() *rbacv1.ClusterRole {
finalizer := []string{}
if !c.cfg.Terminating {
finalizer = []string{NodeFinalizer}
}
role := &rbacv1.ClusterRole{
TypeMeta: metav1.TypeMeta{Kind: "ClusterRole", APIVersion: "rbac.authorization.k8s.io/v1"},
ObjectMeta: metav1.ObjectMeta{
Name: CalicoCNIPluginObjectName,
Finalizers: finalizer,
},

Rules: []rbacv1.PolicyRule{
{
// The CNI plugin needs to get pods, nodes, namespaces.
APIGroups: []string{""},
Resources: []string{"pods", "nodes", "namespaces"},
Verbs: []string{"get"},
},
{
// Calico patches the allocated IP onto the pod.
APIGroups: []string{""},
Resources: []string{"pods/status"},
Verbs: []string{"patch"},
},
{
// Most IPAM resources need full CRUD permissions so we can allocate and
// release IP addresses for pods.
APIGroups: []string{"crd.projectcalico.org"},
Resources: []string{
"blockaffinities",
"ipamblocks",
"ipamhandles",
"ipamconfigs",
"clusterinformations",
"ippools",
"ipreservations",
},
Verbs: []string{"get", "list", "create", "update", "delete"},
},
},
}

return role
}

func (c *nodeComponent) createCalicoPluginConfig() map[string]interface{} {
// Determine MTU to use for veth interfaces.
// Zero means to use auto-detection.
Expand Down
41 changes: 40 additions & 1 deletion pkg/render/node_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ var _ = Describe("Node rendering tests", func() {
var typhaNodeTLS *render.TyphaNodeTLS
var k8sServiceEp k8sapi.ServiceEndpoint
one := intstr.FromInt(1)
defaultNumExpectedResources := 6
defaultNumExpectedResources := 9
const defaultClusterDomain = "svc.cluster.local"
var defaultMode int32 = 420
var cfg render.NodeConfiguration
Expand Down Expand Up @@ -166,6 +166,9 @@ var _ = Describe("Node rendering tests", func() {
{name: "calico-node", ns: common.CalicoNamespace, group: "", version: "v1", kind: "ServiceAccount"},
{name: "calico-node", ns: "", group: "rbac.authorization.k8s.io", version: "v1", kind: "ClusterRole"},
{name: "calico-node", ns: "", group: "rbac.authorization.k8s.io", version: "v1", kind: "ClusterRoleBinding"},
{name: "calico-cni-plugin", ns: common.CalicoNamespace, group: "", version: "v1", kind: "ServiceAccount"},
{name: "calico-cni-plugin", ns: "", group: "rbac.authorization.k8s.io", version: "v1", kind: "ClusterRole"},
{name: "calico-cni-plugin", ns: "", group: "rbac.authorization.k8s.io", version: "v1", kind: "ClusterRoleBinding"},
{name: "cni-config", ns: common.CalicoNamespace, group: "", version: "v1", kind: "ConfigMap"},
{name: common.NodeDaemonSetName, ns: "", group: "policy", version: "v1beta1", kind: "PodSecurityPolicy"},
{name: common.NodeDaemonSetName, ns: common.CalicoNamespace, group: "apps", version: "v1", kind: "DaemonSet"},
Expand Down Expand Up @@ -424,6 +427,9 @@ var _ = Describe("Node rendering tests", func() {
{name: "calico-node", ns: common.CalicoNamespace, group: "", version: "v1", kind: "ServiceAccount"},
{name: "calico-node", ns: "", group: "rbac.authorization.k8s.io", version: "v1", kind: "ClusterRole"},
{name: "calico-node", ns: "", group: "rbac.authorization.k8s.io", version: "v1", kind: "ClusterRoleBinding"},
{name: "calico-cni-plugin", ns: common.CalicoNamespace, group: "", version: "v1", kind: "ServiceAccount"},
{name: "calico-cni-plugin", ns: "", group: "rbac.authorization.k8s.io", version: "v1", kind: "ClusterRole"},
{name: "calico-cni-plugin", ns: "", group: "rbac.authorization.k8s.io", version: "v1", kind: "ClusterRoleBinding"},
{name: "cni-config", ns: common.CalicoNamespace, group: "", version: "v1", kind: "ConfigMap"},
{name: common.NodeDaemonSetName, ns: "", group: "policy", version: "v1beta1", kind: "PodSecurityPolicy"},
{name: common.NodeDaemonSetName, ns: common.CalicoNamespace, group: "apps", version: "v1", kind: "DaemonSet"},
Expand Down Expand Up @@ -747,6 +753,9 @@ var _ = Describe("Node rendering tests", func() {
{name: "calico-node", ns: common.CalicoNamespace, group: "", version: "v1", kind: "ServiceAccount"},
{name: "calico-node", ns: "", group: "rbac.authorization.k8s.io", version: "v1", kind: "ClusterRole"},
{name: "calico-node", ns: "", group: "rbac.authorization.k8s.io", version: "v1", kind: "ClusterRoleBinding"},
{name: "calico-cni-plugin", ns: common.CalicoNamespace, group: "", version: "v1", kind: "ServiceAccount"},
{name: "calico-cni-plugin", ns: "", group: "rbac.authorization.k8s.io", version: "v1", kind: "ClusterRole"},
{name: "calico-cni-plugin", ns: "", group: "rbac.authorization.k8s.io", version: "v1", kind: "ClusterRoleBinding"},
{name: "calico-node-metrics", ns: "calico-system", group: "", version: "v1", kind: "Service"},
{name: "cni-config", ns: common.CalicoNamespace, group: "", version: "v1", kind: "ConfigMap"},
{name: common.NodeDaemonSetName, ns: "", group: "policy", version: "v1beta1", kind: "PodSecurityPolicy"},
Expand Down Expand Up @@ -835,6 +844,9 @@ var _ = Describe("Node rendering tests", func() {
{name: "calico-node", ns: common.CalicoNamespace, group: "", version: "v1", kind: "ServiceAccount"},
{name: "calico-node", ns: "", group: "rbac.authorization.k8s.io", version: "v1", kind: "ClusterRole"},
{name: "calico-node", ns: "", group: "rbac.authorization.k8s.io", version: "v1", kind: "ClusterRoleBinding"},
{name: "calico-cni-plugin", ns: common.CalicoNamespace, group: "", version: "v1", kind: "ServiceAccount"},
{name: "calico-cni-plugin", ns: "", group: "rbac.authorization.k8s.io", version: "v1", kind: "ClusterRole"},
{name: "calico-cni-plugin", ns: "", group: "rbac.authorization.k8s.io", version: "v1", kind: "ClusterRoleBinding"},
{name: "cni-config", ns: common.CalicoNamespace, group: "", version: "v1", kind: "ConfigMap"},
{name: common.NodeDaemonSetName, ns: "", group: "policy", version: "v1beta1", kind: "PodSecurityPolicy"},
{name: common.NodeDaemonSetName, ns: common.CalicoNamespace, group: "apps", version: "v1", kind: "DaemonSet"},
Expand Down Expand Up @@ -981,6 +993,9 @@ var _ = Describe("Node rendering tests", func() {
{name: "calico-node", ns: common.CalicoNamespace, group: "", version: "v1", kind: "ServiceAccount"},
{name: "calico-node", ns: "", group: "rbac.authorization.k8s.io", version: "v1", kind: "ClusterRole"},
{name: "calico-node", ns: "", group: "rbac.authorization.k8s.io", version: "v1", kind: "ClusterRoleBinding"},
{name: "calico-cni-plugin", ns: common.CalicoNamespace, group: "", version: "v1", kind: "ServiceAccount"},
{name: "calico-cni-plugin", ns: "", group: "rbac.authorization.k8s.io", version: "v1", kind: "ClusterRole"},
{name: "calico-cni-plugin", ns: "", group: "rbac.authorization.k8s.io", version: "v1", kind: "ClusterRoleBinding"},
{name: "cni-config", ns: common.CalicoNamespace, group: "", version: "v1", kind: "ConfigMap"},
{name: common.NodeDaemonSetName, ns: "", group: "policy", version: "v1beta1", kind: "PodSecurityPolicy"},
{name: common.NodeDaemonSetName, ns: common.CalicoNamespace, group: "apps", version: "v1", kind: "DaemonSet"},
Expand Down Expand Up @@ -1391,6 +1406,9 @@ var _ = Describe("Node rendering tests", func() {
{name: "calico-node", ns: common.CalicoNamespace, group: "", version: "v1", kind: "ServiceAccount"},
{name: "calico-node", ns: "", group: "rbac.authorization.k8s.io", version: "v1", kind: "ClusterRole"},
{name: "calico-node", ns: "", group: "rbac.authorization.k8s.io", version: "v1", kind: "ClusterRoleBinding"},
{name: "calico-cni-plugin", ns: common.CalicoNamespace, group: "", version: "v1", kind: "ServiceAccount"},
{name: "calico-cni-plugin", ns: "", group: "rbac.authorization.k8s.io", version: "v1", kind: "ClusterRole"},
{name: "calico-cni-plugin", ns: "", group: "rbac.authorization.k8s.io", version: "v1", kind: "ClusterRoleBinding"},
{name: "cni-config", ns: common.CalicoNamespace, group: "", version: "v1", kind: "ConfigMap"},
{name: common.NodeDaemonSetName, ns: "", group: "policy", version: "v1beta1", kind: "PodSecurityPolicy"},
{name: common.NodeDaemonSetName, ns: common.CalicoNamespace, group: "apps", version: "v1", kind: "DaemonSet"},
Expand Down Expand Up @@ -1740,6 +1758,9 @@ var _ = Describe("Node rendering tests", func() {
{name: "calico-node", ns: common.CalicoNamespace, group: "", version: "v1", kind: "ServiceAccount"},
{name: "calico-node", ns: "", group: "rbac.authorization.k8s.io", version: "v1", kind: "ClusterRole"},
{name: "calico-node", ns: "", group: "rbac.authorization.k8s.io", version: "v1", kind: "ClusterRoleBinding"},
{name: "calico-cni-plugin", ns: common.CalicoNamespace, group: "", version: "v1", kind: "ServiceAccount"},
{name: "calico-cni-plugin", ns: "", group: "rbac.authorization.k8s.io", version: "v1", kind: "ClusterRole"},
{name: "calico-cni-plugin", ns: "", group: "rbac.authorization.k8s.io", version: "v1", kind: "ClusterRoleBinding"},
{name: "cni-config", ns: common.CalicoNamespace, group: "", version: "v1", kind: "ConfigMap"},
{name: common.NodeDaemonSetName, ns: "", group: "policy", version: "v1beta1", kind: "PodSecurityPolicy"},
{name: common.NodeDaemonSetName, ns: common.CalicoNamespace, group: "apps", version: "v1", kind: "DaemonSet"},
Expand Down Expand Up @@ -1852,6 +1873,9 @@ var _ = Describe("Node rendering tests", func() {
{name: "calico-node", ns: common.CalicoNamespace, group: "", version: "v1", kind: "ServiceAccount"},
{name: "calico-node", ns: "", group: "rbac.authorization.k8s.io", version: "v1", kind: "ClusterRole"},
{name: "calico-node", ns: "", group: "rbac.authorization.k8s.io", version: "v1", kind: "ClusterRoleBinding"},
{name: "calico-cni-plugin", ns: common.CalicoNamespace, group: "", version: "v1", kind: "ServiceAccount"},
{name: "calico-cni-plugin", ns: "", group: "rbac.authorization.k8s.io", version: "v1", kind: "ClusterRole"},
{name: "calico-cni-plugin", ns: "", group: "rbac.authorization.k8s.io", version: "v1", kind: "ClusterRoleBinding"},
{name: "calico-node-metrics", ns: "calico-system", group: "", version: "v1", kind: "Service"},
{name: "cni-config", ns: common.CalicoNamespace, group: "", version: "v1", kind: "ConfigMap"},
{name: common.NodeDaemonSetName, ns: "", group: "policy", version: "v1beta1", kind: "PodSecurityPolicy"},
Expand Down Expand Up @@ -1948,6 +1972,9 @@ var _ = Describe("Node rendering tests", func() {
{name: "calico-node", ns: common.CalicoNamespace, group: "", version: "v1", kind: "ServiceAccount"},
{name: "calico-node", ns: "", group: "rbac.authorization.k8s.io", version: "v1", kind: "ClusterRole"},
{name: "calico-node", ns: "", group: "rbac.authorization.k8s.io", version: "v1", kind: "ClusterRoleBinding"},
{name: "calico-cni-plugin", ns: common.CalicoNamespace, group: "", version: "v1", kind: "ServiceAccount"},
{name: "calico-cni-plugin", ns: "", group: "rbac.authorization.k8s.io", version: "v1", kind: "ClusterRole"},
{name: "calico-cni-plugin", ns: "", group: "rbac.authorization.k8s.io", version: "v1", kind: "ClusterRoleBinding"},
{name: "calico-node-metrics", ns: "calico-system", group: "", version: "v1", kind: "Service"},
{name: "cni-config", ns: common.CalicoNamespace, group: "", version: "v1", kind: "ConfigMap"},
{name: common.NodeDaemonSetName, ns: "", group: "policy", version: "v1beta1", kind: "PodSecurityPolicy"},
Expand Down Expand Up @@ -2044,6 +2071,9 @@ var _ = Describe("Node rendering tests", func() {
{name: "calico-node", ns: common.CalicoNamespace, group: "", version: "v1", kind: "ServiceAccount"},
{name: "calico-node", ns: "", group: "rbac.authorization.k8s.io", version: "v1", kind: "ClusterRole"},
{name: "calico-node", ns: "", group: "rbac.authorization.k8s.io", version: "v1", kind: "ClusterRoleBinding"},
{name: "calico-cni-plugin", ns: common.CalicoNamespace, group: "", version: "v1", kind: "ServiceAccount"},
{name: "calico-cni-plugin", ns: "", group: "rbac.authorization.k8s.io", version: "v1", kind: "ClusterRole"},
{name: "calico-cni-plugin", ns: "", group: "rbac.authorization.k8s.io", version: "v1", kind: "ClusterRoleBinding"},
{name: "cni-config", ns: common.CalicoNamespace, group: "", version: "v1", kind: "ConfigMap"},
{name: render.BirdTemplatesConfigMapName, ns: common.CalicoNamespace, group: "", version: "v1", kind: "ConfigMap"},
{name: common.NodeDaemonSetName, ns: "", group: "policy", version: "v1beta1", kind: "PodSecurityPolicy"},
Expand Down Expand Up @@ -2538,6 +2568,9 @@ var _ = Describe("Node rendering tests", func() {
{name: "calico-node", ns: common.CalicoNamespace, group: "", version: "v1", kind: "ServiceAccount"},
{name: "calico-node", ns: "", group: "rbac.authorization.k8s.io", version: "v1", kind: "ClusterRole"},
{name: "calico-node", ns: "", group: "rbac.authorization.k8s.io", version: "v1", kind: "ClusterRoleBinding"},
{name: "calico-cni-plugin", ns: common.CalicoNamespace, group: "", version: "v1", kind: "ServiceAccount"},
{name: "calico-cni-plugin", ns: "", group: "rbac.authorization.k8s.io", version: "v1", kind: "ClusterRole"},
{name: "calico-cni-plugin", ns: "", group: "rbac.authorization.k8s.io", version: "v1", kind: "ClusterRoleBinding"},
{name: "cni-config", ns: common.CalicoNamespace, group: "", version: "v1", kind: "ConfigMap"},
{name: common.NodeDaemonSetName, ns: "", group: "policy", version: "v1beta1", kind: "PodSecurityPolicy"},
{name: common.NodeDaemonSetName, ns: common.CalicoNamespace, group: "apps", version: "v1", kind: "DaemonSet"},
Expand Down Expand Up @@ -2993,6 +3026,9 @@ var _ = Describe("Node rendering tests", func() {
{name: "calico-node", ns: common.CalicoNamespace, group: "", version: "v1", kind: "ServiceAccount"},
{name: "calico-node", ns: "", group: "rbac.authorization.k8s.io", version: "v1", kind: "ClusterRole"},
{name: "calico-node", ns: "", group: "rbac.authorization.k8s.io", version: "v1", kind: "ClusterRoleBinding"},
{name: "calico-cni-plugin", ns: common.CalicoNamespace, group: "", version: "v1", kind: "ServiceAccount"},
{name: "calico-cni-plugin", ns: "", group: "rbac.authorization.k8s.io", version: "v1", kind: "ClusterRole"},
{name: "calico-cni-plugin", ns: "", group: "rbac.authorization.k8s.io", version: "v1", kind: "ClusterRoleBinding"},
{name: "cni-config", ns: common.CalicoNamespace, group: "", version: "v1", kind: "ConfigMap"},
{name: common.NodeDaemonSetName, ns: "", group: "policy", version: "v1beta1", kind: "PodSecurityPolicy"},
{name: common.NodeDaemonSetName, ns: common.CalicoNamespace, group: "apps", version: "v1", kind: "DaemonSet"},
Expand Down Expand Up @@ -3245,6 +3281,9 @@ var _ = Describe("Node rendering tests", func() {
{name: "calico-node", ns: common.CalicoNamespace, group: "", version: "v1", kind: "ServiceAccount"},
{name: "calico-node", ns: "", group: "rbac.authorization.k8s.io", version: "v1", kind: "ClusterRole"},
{name: "calico-node", ns: "", group: "rbac.authorization.k8s.io", version: "v1", kind: "ClusterRoleBinding"},
{name: "calico-cni-plugin", ns: common.CalicoNamespace, group: "", version: "v1", kind: "ServiceAccount"},
{name: "calico-cni-plugin", ns: "", group: "rbac.authorization.k8s.io", version: "v1", kind: "ClusterRole"},
{name: "calico-cni-plugin", ns: "", group: "rbac.authorization.k8s.io", version: "v1", kind: "ClusterRoleBinding"},
{name: "cni-config", ns: common.CalicoNamespace, group: "", version: "v1", kind: "ConfigMap"},
{name: common.NodeDaemonSetName, ns: "", group: "policy", version: "v1beta1", kind: "PodSecurityPolicy"},
{name: common.NodeDaemonSetName, ns: common.CalicoNamespace, group: "apps", version: "v1", kind: "DaemonSet"},
Expand Down
Loading