From 7744dd7e2ae96d44e68c8efaaff2756ce5cd3e20 Mon Sep 17 00:00:00 2001 From: Edmund Ochieng Date: Thu, 12 Sep 2024 10:43:11 -0500 Subject: [PATCH] fix: call TokenRequest API when service account token secret is missing (#3377) * fix: call TokenRequest API when service account token secret is missing Beyond Kubernetes 1.22, the service account token secret is not automatically, created. Therefore, when OLM is not able to find the service account token secret, it should request one from the k8s api server. Ref: https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/#manual-secret-management-for-serviceaccounts Signed-off-by: Edmund Ochieng * fix: return error Signed-off-by: Edmund Ochieng * handle error when creating sa token from TokenRequest API fails Signed-off-by: Edmund Ochieng * move return from inner loop Move the return to line 48. This will ensure a value is returned whether we successully create a service account token from the TokenRequest API or get an error Signed-off-by: Edmund Ochieng --------- Signed-off-by: Edmund Ochieng Upstream-repository: operator-lifecycle-manager Upstream-commit: e20778cbb590f82dbe9cba500e98e7317222e5b5 --- .../pkg/lib/scoped/token_retriever.go | 24 ++++++++++++++++++- .../pkg/lib/scoped/token_retriever.go | 24 ++++++++++++++++++- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/staging/operator-lifecycle-manager/pkg/lib/scoped/token_retriever.go b/staging/operator-lifecycle-manager/pkg/lib/scoped/token_retriever.go index d3dbcee5db..86511e9a8c 100644 --- a/staging/operator-lifecycle-manager/pkg/lib/scoped/token_retriever.go +++ b/staging/operator-lifecycle-manager/pkg/lib/scoped/token_retriever.go @@ -6,6 +6,7 @@ import ( "github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorclient" "github.com/sirupsen/logrus" + authv1 "k8s.io/api/authentication/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -36,7 +37,14 @@ func (r *BearerTokenRetriever) Retrieve(reference *corev1.ObjectReference) (toke } if secret == nil { - err = fmt.Errorf("the service account does not have any API secret sa=%s/%s", sa.GetNamespace(), sa.GetName()) + token, err = requestSAToken(r.kubeclient, sa) + if err != nil { + err = fmt.Errorf("creating service account token from TokenRequest API for sa=%s/%s; %v", + sa.GetNamespace(), + sa.GetName(), + err, + ) + } return } @@ -48,6 +56,20 @@ func (r *BearerTokenRetriever) Retrieve(reference *corev1.ObjectReference) (toke return } +// requestSAToken requests for a service account token from the Kubernetes API server whenever the Operator +// Lifecycle manager is unable to find a service account token secret +func requestSAToken(kubeclient operatorclient.ClientInterface, sa *corev1.ServiceAccount) (string, error) { + req := new(authv1.TokenRequest) + req, err := kubeclient.KubernetesInterface(). + CoreV1().ServiceAccounts(sa.GetNamespace()). + CreateToken(context.Background(), sa.GetName(), req, metav1.CreateOptions{}) + if err != nil { + return "", err + } + + return req.Status.Token, nil +} + func getAPISecret(logger logrus.FieldLogger, kubeclient operatorclient.ClientInterface, sa *corev1.ServiceAccount) (APISecret *corev1.Secret, err error) { seList, err := kubeclient.KubernetesInterface().CoreV1().Secrets(sa.GetNamespace()).List(context.TODO(), metav1.ListOptions{}) if err != nil { diff --git a/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/scoped/token_retriever.go b/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/scoped/token_retriever.go index d3dbcee5db..86511e9a8c 100644 --- a/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/scoped/token_retriever.go +++ b/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/scoped/token_retriever.go @@ -6,6 +6,7 @@ import ( "github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorclient" "github.com/sirupsen/logrus" + authv1 "k8s.io/api/authentication/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -36,7 +37,14 @@ func (r *BearerTokenRetriever) Retrieve(reference *corev1.ObjectReference) (toke } if secret == nil { - err = fmt.Errorf("the service account does not have any API secret sa=%s/%s", sa.GetNamespace(), sa.GetName()) + token, err = requestSAToken(r.kubeclient, sa) + if err != nil { + err = fmt.Errorf("creating service account token from TokenRequest API for sa=%s/%s; %v", + sa.GetNamespace(), + sa.GetName(), + err, + ) + } return } @@ -48,6 +56,20 @@ func (r *BearerTokenRetriever) Retrieve(reference *corev1.ObjectReference) (toke return } +// requestSAToken requests for a service account token from the Kubernetes API server whenever the Operator +// Lifecycle manager is unable to find a service account token secret +func requestSAToken(kubeclient operatorclient.ClientInterface, sa *corev1.ServiceAccount) (string, error) { + req := new(authv1.TokenRequest) + req, err := kubeclient.KubernetesInterface(). + CoreV1().ServiceAccounts(sa.GetNamespace()). + CreateToken(context.Background(), sa.GetName(), req, metav1.CreateOptions{}) + if err != nil { + return "", err + } + + return req.Status.Token, nil +} + func getAPISecret(logger logrus.FieldLogger, kubeclient operatorclient.ClientInterface, sa *corev1.ServiceAccount) (APISecret *corev1.Secret, err error) { seList, err := kubeclient.KubernetesInterface().CoreV1().Secrets(sa.GetNamespace()).List(context.TODO(), metav1.ListOptions{}) if err != nil {