Skip to content
This repository was archived by the owner on Apr 25, 2023. It is now read-only.

Commit 0978060

Browse files
committed
fix: Use specific service account token secret
With `LegacyServiceAccountTokenNoAutoGeneration` feature graduating to beta in k8s v1.24, a token is not automatically generated when a service account is created. This commit fixes this by requesting a specific service token account secret which is populated by the token controller. This is backwards compatible with previous versions of Kubernetes. This commit also upgrades to use k8s v1.24 for both KinD image and for envtest to ensure this works with latest version of Kubernetes.
1 parent a402d2e commit 0978060

File tree

8 files changed

+79
-34
lines changed

8 files changed

+79
-34
lines changed

Makefile

+3-1
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,9 @@ all: container hyperfed controller kubefedctl webhook e2e
7676

7777
# Unit tests
7878
test:
79-
go test $(TEST_PKGS)
79+
go install sigs.k8s.io/controller-runtime/tools/setup-envtest@latest
80+
source <(setup-envtest use -i -p env 1.24.x) && \
81+
go test $(TEST_PKGS)
8082

8183
build: hyperfed controller kubefedctl webhook
8284

docs/environments/kind.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -43,17 +43,17 @@ script if you'd like to change the default:
4343
NUM_CLUSTERS=<num> ./scripts/create-clusters.sh
4444
```
4545

46-
The `KIND_TAG` is `v1.21.1@sha256:69860bda5563ac81e3c0057d654b5253219618a22ec3a346306239bba8cfa1a6` by default.
46+
The `KIND_TAG` is `v1.24.2@sha256:1f0cee2282f43150b52dc7933183ed96abdcfc8d293f30ec07082495874876f1` by default.
4747
Image `kindest/node:v1.21.1@sha256:69860bda5563ac81e3c0057d654b5253219618a22ec3a346306239bba8cfa1a6` is used as
4848
node docker image for booting the cluster.
4949

5050
You can use `KIND_IMAGE` or `KIND_TAG` to specify the image as you want.
5151
```bash
52-
KIND_TAG=v1.19.4@sha256:796d09e217d93bed01ecf8502633e48fd806fe42f9d02fdd468b81cd4e3bd40b ./scripts/create-clusters.sh
52+
KIND_TAG=v1.21.1@sha256:69860bda5563ac81e3c0057d654b5253219618a22ec3a346306239bba8cfa1a6 ./scripts/create-clusters.sh
5353
```
5454

5555
```bash
56-
KIND_IMAGE=kindest/node:v1.19.4@sha256:796d09e217d93bed01ecf8502633e48fd806fe42f9d02fdd468b81cd4e3bd40b ./scripts/create-clusters.sh
56+
KIND_IMAGE=kindest/node:v1.21.1@sha256:69860bda5563ac81e3c0057d654b5253219618a22ec3a346306239bba8cfa1a6 ./scripts/create-clusters.sh
5757
```
5858

5959
## Delete Clusters

pkg/kubefedctl/join.go

+59-19
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import (
3737
kubeclient "k8s.io/client-go/kubernetes"
3838
"k8s.io/client-go/rest"
3939
"k8s.io/klog/v2"
40+
"k8s.io/utils/pointer"
4041
runtimeclient "sigs.k8s.io/controller-runtime/pkg/client"
4142

4243
fedv1b1 "sigs.k8s.io/kubefed/pkg/apis/core/v1beta1"
@@ -417,8 +418,8 @@ func createKubeFedNamespace(clusterClientset kubeclient.Interface, kubefedNamesp
417418
return fedNamespace, nil
418419
}
419420

420-
// createAuthorizedServiceAccount creates a service account and grants
421-
// the privileges required by the KubeFed control plane to manage
421+
// createAuthorizedServiceAccount creates a service account and service account token secret
422+
// and grants the privileges required by the KubeFed control plane to manage
422423
// resources in the joining cluster. The name of the created service
423424
// account is returned on success.
424425
func createAuthorizedServiceAccount(joiningClusterClientset kubeclient.Interface,
@@ -436,6 +437,16 @@ func createAuthorizedServiceAccount(joiningClusterClientset kubeclient.Interface
436437

437438
klog.V(2).Infof("Created service account: %s in joining cluster: %s", saName, joiningClusterName)
438439

440+
secretName, err := createServiceAccountTokenSecret(saName, joiningClusterClientset, namespace,
441+
joiningClusterName, hostClusterName, dryRun, errorOnExisting)
442+
if err != nil {
443+
klog.V(2).Infof("Error creating service account: %s in joining cluster: %s due to: %v",
444+
saName, joiningClusterName, err)
445+
return "", err
446+
}
447+
448+
klog.V(2).Infof("Created service account token secret: %s in joining cluster: %s", secretName, joiningClusterName)
449+
439450
if scope == apiextv1.NamespaceScoped {
440451
klog.V(2).Infof("Creating role and binding for service account: %s in joining cluster: %s", saName, joiningClusterName)
441452

@@ -487,7 +498,11 @@ func createServiceAccount(clusterClientset kubeclient.Interface, namespace,
487498
ObjectMeta: metav1.ObjectMeta{
488499
Name: saName,
489500
Namespace: namespace,
501+
Annotations: map[string]string{
502+
"kubernetes.io/enforce-mountable-secrets": "true",
503+
},
490504
},
505+
AutomountServiceAccountToken: pointer.Bool(false),
491506
}
492507

493508
if dryRun {
@@ -508,6 +523,43 @@ func createServiceAccount(clusterClientset kubeclient.Interface, namespace,
508523
default:
509524
return saName, nil
510525
}
526+
} // createServiceAccount creates a service account in the cluster associated
527+
// with clusterClientset with credentials that will be used by the host cluster
528+
// to access its API server.
529+
func createServiceAccountTokenSecret(saName string, clusterClientset kubeclient.Interface, namespace,
530+
joiningClusterName, hostClusterName string, dryRun, errorOnExisting bool) (string, error) {
531+
saTokenSecretName := util.ClusterServiceAccountTokenSecretName(joiningClusterName, hostClusterName)
532+
saTokenSecret := &corev1.Secret{
533+
ObjectMeta: metav1.ObjectMeta{
534+
Name: saTokenSecretName,
535+
Namespace: namespace,
536+
Annotations: map[string]string{
537+
"kubernetes.io/service-account.name": saName,
538+
},
539+
},
540+
Type: corev1.SecretTypeServiceAccountToken,
541+
}
542+
543+
if dryRun {
544+
return saName, nil
545+
}
546+
547+
// Create a new service account.
548+
_, err := clusterClientset.CoreV1().Secrets(namespace).Create(
549+
context.Background(), saTokenSecret, metav1.CreateOptions{},
550+
)
551+
switch {
552+
case apierrors.IsAlreadyExists(err) && errorOnExisting:
553+
klog.V(2).Infof("Service account token secret %s/%s already exists in target cluster %s",
554+
namespace, saName, joiningClusterName)
555+
return "", err
556+
case err != nil && !apierrors.IsAlreadyExists(err):
557+
klog.V(2).Infof("Could not create service account token secret %s/%s in target cluster %s due to: %v",
558+
namespace, saName, joiningClusterName, err)
559+
return "", err
560+
default:
561+
return saTokenSecretName, nil
562+
}
511563
}
512564

513565
func bindingSubjects(saName, namespace string) []rbacv1.Subject {
@@ -841,32 +893,20 @@ func populateSecretInHostCluster(clusterClientset, hostClientset kubeclient.Inte
841893
// Get the secret from the joining cluster.
842894
var secret *corev1.Secret
843895
err := wait.PollImmediate(1*time.Second, serviceAccountSecretTimeout, func() (bool, error) {
844-
sa, err := clusterClientset.CoreV1().ServiceAccounts(joiningNamespace).Get(
896+
joiningClusterSASecret, err := clusterClientset.CoreV1().Secrets(joiningNamespace).Get(
845897
context.Background(), saName, metav1.GetOptions{},
846898
)
847899
if err != nil {
848900
return false, nil
849901
}
850902

851-
for _, objReference := range sa.Secrets {
852-
saSecretName := objReference.Name
853-
var err error
854-
secret, err = clusterClientset.CoreV1().Secrets(joiningNamespace).Get(
855-
context.Background(), saSecretName, metav1.GetOptions{},
856-
)
857-
if err != nil {
858-
return false, nil
859-
}
860-
if secret.Type == corev1.SecretTypeServiceAccountToken {
861-
klog.V(2).Infof("Using secret named: %s", secret.Name)
862-
return true, nil
863-
}
864-
}
865-
return false, nil
903+
secret = joiningClusterSASecret
904+
905+
return true, nil
866906
})
867907

868908
if err != nil {
869-
klog.V(2).Infof("Could not get service account secret from joining cluster: %v", err)
909+
klog.V(2).Infof("Could not get service account token secret from joining cluster: %v", err)
870910
return nil, nil, err
871911
}
872912

pkg/kubefedctl/util/util.go

+6
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,12 @@ func ClusterServiceAccountName(joiningClusterName, hostClusterName string) strin
107107
return fmt.Sprintf("%s-%s", joiningClusterName, hostClusterName)
108108
}
109109

110+
// ClusterServiceAccountTokenName returns the name of a service account token secret whose
111+
// credentials are used by the host cluster to access the client cluster.
112+
func ClusterServiceAccountTokenSecretName(joiningClusterName, hostClusterName string) string {
113+
return fmt.Sprintf("%s-%s", joiningClusterName, hostClusterName)
114+
}
115+
110116
// RoleName returns the name of a Role or ClusterRole and its
111117
// associated RoleBinding or ClusterRoleBinding that are used to allow
112118
// the service account to access necessary resources on the cluster.

scripts/create-clusters.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ set -o pipefail
2525
source "${BASH_SOURCE%/*}/util.sh"
2626
NUM_CLUSTERS="${NUM_CLUSTERS:-2}"
2727
KIND_IMAGE="${KIND_IMAGE:-}"
28-
KIND_TAG="${KIND_TAG:-v1.21.1@sha256:69860bda5563ac81e3c0057d654b5253219618a22ec3a346306239bba8cfa1a6}"
28+
KIND_TAG="${KIND_TAG:-v1.24.2@sha256:1f0cee2282f43150b52dc7933183ed96abdcfc8d293f30ec07082495874876f1}"
2929
OS="$(uname)"
3030

3131
function create-clusters() {

scripts/download-binaries.sh

+4-7
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,11 @@ mkdir -p "${dest_dir}"
4343

4444
platform=$(uname -s|tr A-Z a-z)
4545

46-
kb_version="2.3.1"
47-
kb_tgz="kubebuilder_${kb_version}_${platform}_amd64.tar.gz"
48-
kb_url="https://github.com/kubernetes-sigs/kubebuilder/releases/download/v${kb_version}/${kb_tgz}"
49-
curl "${curl_args}" "${kb_url}" \
50-
| tar xzP -C "${dest_dir}" --strip-components=2
46+
go install sigs.k8s.io/controller-runtime/tools/setup-envtest@latest
5147

52-
export KUBEBUILDER_ASSETS="${dest_dir}"
53-
echo "Setting to KUBEBUILDER_ASSETS ${dest_dir}"
48+
source <(setup-envtest use -i -p env 1.24.x)
49+
50+
echo "KUBEBUILDER_ASSETS is set to KUBEBUILDER_ASSETS"
5451

5552
helm_version="3.6.0"
5653
helm_tgz="helm-v${helm_version}-${platform}-amd64.tar.gz"

scripts/download-e2e-binaries.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ mkdir -p "${dest_dir}"
3636

3737
# kind
3838
platform="$(uname -s|tr A-Z a-z)"
39-
kind_version="v0.11.1"
39+
kind_version="v0.14.0"
4040
kind_path="${dest_dir}/kind"
4141
kind_url="https://github.com/kubernetes-sigs/kind/releases/download/${kind_version}/kind-${platform}-amd64"
4242
curl -fLo "${kind_path}" "${kind_url}" && chmod +x "${kind_path}"

scripts/pre-commit.sh

+2-2
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ function download-dependencies() {
5757
}
5858

5959
function run-unit-tests() {
60-
KUBEBUILDER_ASSETS=${ROOT_DIR}/bin ${MAKE_CMD} test
60+
${MAKE_CMD} test
6161
}
6262

6363
function run-e2e-tests() {
@@ -188,7 +188,7 @@ run-unit-tests
188188
echo "Downloading e2e test dependencies"
189189
./scripts/download-e2e-binaries.sh
190190

191-
KIND_TAG="v1.21.1@sha256:69860bda5563ac81e3c0057d654b5253219618a22ec3a346306239bba8cfa1a6" ./scripts/create-clusters.sh
191+
KIND_TAG="v1.24.2@sha256:1f0cee2282f43150b52dc7933183ed96abdcfc8d293f30ec07082495874876f1" ./scripts/create-clusters.sh
192192

193193
declare -a join_cluster_list=()
194194
if [[ -z "${JOIN_CLUSTERS}" ]]; then

0 commit comments

Comments
 (0)