Created
May 22, 2018 17:21
-
-
Save ahmetb/548059cdbf12fb571e4e2f1e29c48997 to your computer and use it in GitHub Desktop.
Authenticating to GKE cluster with client-go, IAM service account and a Google auth plugin written from scratch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"context" | |
"fmt" | |
"log" | |
"net/http" | |
"golang.org/x/oauth2" | |
"golang.org/x/oauth2/google" | |
"k8s.io/client-go/rest" | |
) | |
var ( | |
googleScopes = []string{ | |
"https://www.googleapis.com/auth/cloud-platform", | |
"https://www.googleapis.com/auth/userinfo.email"} | |
) | |
const ( | |
googleAuthPlugin = "google" // so that this is different than "gcp" that's already in client-go tree. | |
) | |
func init() { | |
if err := rest.RegisterAuthProviderPlugin(googleAuthPlugin, newGoogleAuthProvider); err != nil { | |
log.Fatalf("Failed to register %s auth plugin: %v", googleAuthPlugin, err) | |
} | |
} | |
var _ rest.AuthProvider = &googleAuthProvider{} | |
type googleAuthProvider struct { | |
tokenSource oauth2.TokenSource | |
} | |
func (g *googleAuthProvider) WrapTransport(rt http.RoundTripper) http.RoundTripper { | |
return &oauth2.Transport{ | |
Base: rt, | |
Source: g.tokenSource, | |
} | |
} | |
func (g *googleAuthProvider) Login() error { return nil } | |
func newGoogleAuthProvider(addr string, config map[string]string, persister rest.AuthProviderConfigPersister) (rest.AuthProvider, error) { | |
ts, err := google.DefaultTokenSource(context.TODO(), googleScopes...) | |
if err != nil { | |
return nil, fmt.Errorf("failed to create google token source: %+v", err) | |
} | |
return &googleAuthProvider{tokenSource: ts}, nil | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// TODO: set GOOGLE_APPLICATION_CREDENTIALS to json key file of your | |
// service account: | |
// - You don't need to give IAM permissions to this service account. | |
// - You can just give the email address of the service accouunt RBAC | |
// [cluster-]rolebindings in the cluster. | |
package main | |
import ( | |
"context" | |
"io/ioutil" | |
"log" | |
"time" | |
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | |
"k8s.io/client-go/kubernetes" | |
"k8s.io/client-go/rest" | |
clientcmdapi "k8s.io/client-go/tools/clientcmd/api" | |
) | |
func main() { | |
ctx := context.Background() | |
ca, err := ioutil.ReadFile("ca.pem") // TODO set your cluster CA cert here (in PEM file) | |
if err != nil { | |
panic(err) | |
} | |
config := &rest.Config{ | |
TLSClientConfig: rest.TLSClientConfig{ | |
CAData: ca, | |
}, | |
Host: "https://35.x.x.x", // TODO set your master IP here | |
AuthProvider: &clientcmdapi.AuthProviderConfig{Name: googleAuthPlugin}} | |
clientset, err := kubernetes.NewForConfig(config) | |
if err != nil { | |
panic(err.Error()) | |
} | |
for { | |
svcs, err := clientset.CoreV1().Services("").List(metav1.ListOptions{}) | |
if err != nil { | |
panic(err) | |
} | |
log.Printf("There are %d servicesin the cluster", len(svcs.Items)) | |
time.Sleep(10 * time.Second) | |
} | |
} |
Awesome snippet 🙇♂️
There should a library that does this!
Thanks for sharing!
How does this work with option.WithCredentialsJson
, so we don't need that env anymore, instead, we can have a flexible credjson to be used to connect to different clusters in one go.
@riveryc
you can get token by your self like this:
# gcpauth.go
# line 45
gcpServiceAccountKey := "my gcp service account key json string"
ts, err := google.JWTAccessTokenSourceWithScope([]byte(gcpServiceAccountKey), googleScopes...)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
It's awesome not having to use the
BearerToken
, thanks @ahmetb 👍