Home > Blockchain >  GKE auth using application default credentials
GKE auth using application default credentials

Time:01-25

Hi i am trying to get cluster resource details using Application Default Credentials (ADC).


package main

import (
    "context"
    "encoding/base64"
    "flag"
    "fmt"
    "log"

    "google.golang.org/api/container/v1"
    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    "k8s.io/client-go/kubernetes"
    _ "k8s.io/client-go/plugin/pkg/client/auth/gcp" // register GCP auth provider
    "k8s.io/client-go/tools/clientcmd"
    "k8s.io/client-go/tools/clientcmd/api"
)

var fProjectId = flag.String("projectId", "", "specify a project id to examine")

func main() {
    flag.Parse()
    if *fProjectId == "" {
        log.Fatal("must specific -projectId")
    }

    if err := run(context.Background(), *fProjectId); err != nil {
        log.Fatal(err)
    }
}

func run(ctx context.Context, projectId string) error {
    kubeConfig, err := getK8sClusterConfigs(ctx, projectId)
    if err != nil {
        return err
    }

    // Just list all the namespaces found in the project to test the API.
    for clusterName := range kubeConfig.Clusters {
        cfg, err := clientcmd.NewNonInteractiveClientConfig(*kubeConfig, clusterName, &clientcmd.ConfigOverrides{CurrentContext: clusterName}, nil).ClientConfig()
        if err != nil {
            return fmt.Errorf("failed to create Kubernetes configuration cluster=%s: %w", clusterName, err)
        }

        k8s, err := kubernetes.NewForConfig(cfg)
        if err != nil {
            return fmt.Errorf("failed to create Kubernetes client cluster=%s: %w", clusterName, err)
        }

        ns, err := k8s.CoreV1().Namespaces().List(ctx, metav1.ListOptions{})
        if err != nil {
            return fmt.Errorf("failed to list namespaces cluster=%s: %w", clusterName, err)
        }

        log.Printf("Namespaces found in cluster=%s", clusterName)

        for _, item := range ns.Items {
            log.Println(item.Name)
        }
    }

    return nil
}

func getK8sClusterConfigs(ctx context.Context, projectId string) (*api.Config, error) {
    svc, err := container.NewService(ctx)
    if err != nil {
        return nil, fmt.Errorf("container.NewService: %w", err)
    }

    // Basic config structure
    ret := api.Config{
        APIVersion: "v1",
        Kind:       "Config",
        Clusters:   map[string]*api.Cluster{},  // Clusters is a map of referencable names to cluster configs
        AuthInfos:  map[string]*api.AuthInfo{}, // AuthInfos is a map of referencable names to user configs
        Contexts:   map[string]*api.Context{},  // Contexts is a map of referencable names to context configs
    }

    // Ask Google for a list of all kube clusters in the given project.
    resp, err := svc.Projects.Zones.Clusters.List(projectId, "-").Context(ctx).Do()
    if err != nil {
        return nil, fmt.Errorf("clusters list project=%s: %w", projectId, err)
    }

    for _, f := range resp.Clusters {
        name := fmt.Sprintf("gke_%s_%s_%s", projectId, f.Zone, f.Name)
        cert, err := base64.StdEncoding.DecodeString(f.MasterAuth.ClusterCaCertificate)
        if err != nil {
            return nil, fmt.Errorf("invalid certificate cluster=%s cert=%s: %w", name, f.MasterAuth.ClusterCaCertificate, err)
        }
        // example: gke_my-project_us-central1-b_cluster-1 => https://XX.XX.XX.XX
        ret.Clusters[name] = &api.Cluster{
            CertificateAuthorityData: cert,
            Server:                   "https://"   f.Endpoint,
        }
        // Just reuse the context name as an auth name.
        ret.Contexts[name] = &api.Context{
            Cluster:  name,
            AuthInfo: name,
        }
        // GCP specific configation; use cloud platform scope.
        ret.AuthInfos[name] = &api.AuthInfo{
            AuthProvider: &api.AuthProviderConfig{
                Name: "gcp",
                Config: map[string]string{
                    "scopes": "https://www.googleapis.com/auth/cloud-platform",
                },
            },
        }
    }

    return &ret, nil
}

It is giving me the error :

go run main.go -projectId=<Project-id>                                                              
2023/01/23 12:13:47 failed to create Kubernetes client cluster=<cluster-name>: The gcp auth plugin has been removed.
Please use the "gke-gcloud-auth-plugin" kubectl/client-go credential plugin instead.
See https://cloud.google.com/blog/products/containers-kubernetes/kubectl-auth-changes-in-gke for further details
exit status 1

It will be helpful for if you guys suggest me how to solve this issue.

CodePudding user response:

Since k8s 1.26 you need to install GKE auth plugin separately. So, depending on your operating system install google-cloud-sdk-gke-gcloud-auth-plugin and it should work. It's pretty well described here: https://cloud.google.com/blog/products/containers-kubernetes/kubectl-auth-changes-in-gke

CodePudding user response:

After downgrading the dependencies it is working fine

go get k8s.io/client-go/tools/[email protected]  
go get k8s.io/cloud-provider-gcp/pkg/clientauthplugin/gcp@bb1acae5826dc877953d48
  • Related