diff --git a/federation/pkg/kubefed/init/init.go b/federation/pkg/kubefed/init/init.go index b0704c5b224..680aceeda1d 100644 --- a/federation/pkg/kubefed/init/init.go +++ b/federation/pkg/kubefed/init/init.go @@ -47,6 +47,7 @@ import ( "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/resource" "k8s.io/kubernetes/pkg/apis/extensions" + "k8s.io/kubernetes/pkg/apis/rbac" client "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" @@ -62,6 +63,16 @@ const ( AdminCN = "admin" HostClusterLocalDNSZoneName = "cluster.local." + // User name used by federation controller manager to make + // calls to federation API server. + ControllerManagerUser = "federation-controller-manager" + + // Name of the ServiceAccount used by the federation controller manager. + ControllerManagerSA = "federation-controller-manager" + + // Group name of the legacy/core API group + legacyAPIGroup = "" + lbAddrRetryInterval = 5 * time.Second podWaitInterval = 2 * time.Second ) @@ -220,7 +231,21 @@ func initFederation(cmdOut io.Writer, config util.AdminConfig, cmd *cobra.Comman } // 7. Create federation controller manager - _, err = createControllerManager(hostClientset, initFlags.FederationSystemNamespace, initFlags.Name, svc.Name, cmName, image, cmKubeconfigName, dnsZoneName, dnsProvider, dryRun) + // 7a. Create service accounts for federation controller manager + sa, err := createControllerManagerSA(hostClientset, initFlags.FederationSystemNamespace, dryRun) + if err != nil { + return err + } + + // 7b. Create RBAC role and role binding for federation controller + // manager service account. + _, _, err = createRoleBindings(hostClientset, initFlags.FederationSystemNamespace, sa.Name, dryRun) + if err != nil { + return err + } + + // 7c. Create federation controller manager deployment. + _, err = createControllerManager(hostClientset, initFlags.FederationSystemNamespace, initFlags.Name, svc.Name, cmName, image, cmKubeconfigName, dnsZoneName, dnsProvider, sa.Name, dryRun) if err != nil { return err } @@ -375,7 +400,7 @@ func createControllerManagerKubeconfigSecret(clientset *client.Clientset, namesp config := kubeadmkubeconfigphase.MakeClientConfigWithCerts( fmt.Sprintf("https://%s", svcName), name, - "federation-controller-manager", + ControllerManagerUser, certutil.EncodeCertPEM(entKeyPairs.ca.Cert), certutil.EncodePrivateKeyPEM(entKeyPairs.controllerManager.Key), certutil.EncodeCertPEM(entKeyPairs.controllerManager.Cert), @@ -520,7 +545,46 @@ func createAPIServer(clientset *client.Clientset, namespace, name, image, creden return clientset.Extensions().Deployments(namespace).Create(dep) } -func createControllerManager(clientset *client.Clientset, namespace, name, svcName, cmName, image, kubeconfigName, dnsZoneName, dnsProvider string, dryRun bool) (*extensions.Deployment, error) { +func createControllerManagerSA(clientset *client.Clientset, namespace string, dryRun bool) (*api.ServiceAccount, error) { + sa := &api.ServiceAccount{ + ObjectMeta: metav1.ObjectMeta{ + Name: ControllerManagerSA, + Namespace: namespace, + }, + } + if dryRun { + return sa, nil + } + return clientset.Core().ServiceAccounts(namespace).Create(sa) +} + +func createRoleBindings(clientset *client.Clientset, namespace, saName string, dryRun bool) (*rbac.Role, *rbac.RoleBinding, error) { + roleName := "federation-system:federation-controller-manager" + role := &rbac.Role{ + // a role to use for bootstrapping the federation-controller-manager so it can access + // secrets in the host cluster to access other clusters. + ObjectMeta: metav1.ObjectMeta{ + Name: roleName, + }, + Rules: []rbac.PolicyRule{ + rbac.NewRule("get", "list", "watch").Groups(legacyAPIGroup).Resources("secrets").RuleOrDie(), + }, + } + rolebinding := rbac.NewRoleBinding(roleName, namespace).SAs(namespace, saName).BindingOrDie() + + if dryRun { + newRole, err := clientset.Rbac().Roles(namespace).Create(role) + if err != nil { + return nil, nil, err + } + + newRolebinding, err := clientset.Rbac().RoleBindings(namespace).Create(&rolebinding) + return newRole, newRolebinding, err + } + return role, &rolebinding, nil +} + +func createControllerManager(clientset *client.Clientset, namespace, name, svcName, cmName, image, kubeconfigName, dnsZoneName, dnsProvider, saName string, dryRun bool) (*extensions.Deployment, error) { dep := &extensions.Deployment{ ObjectMeta: metav1.ObjectMeta{ Name: cmName, @@ -578,6 +642,7 @@ func createControllerManager(clientset *client.Clientset, namespace, name, svcNa }, }, }, + ServiceAccountName: saName, }, }, },