add rancher credential provider

pull/6/head
wlan0 2017-03-06 16:24:14 -08:00
parent f14618a56b
commit 38988fec78
7 changed files with 284 additions and 0 deletions

View File

@ -48,6 +48,7 @@ go_library(
"//pkg/credentialprovider/aws:go_default_library",
"//pkg/credentialprovider/azure:go_default_library",
"//pkg/credentialprovider/gcp:go_default_library",
"//pkg/credentialprovider/rancher:go_default_library",
"//pkg/features:go_default_library",
"//pkg/kubelet:go_default_library",
"//pkg/kubelet/cadvisor:go_default_library",

View File

@ -22,6 +22,7 @@ import (
_ "k8s.io/kubernetes/pkg/credentialprovider/aws"
_ "k8s.io/kubernetes/pkg/credentialprovider/azure"
_ "k8s.io/kubernetes/pkg/credentialprovider/gcp"
_ "k8s.io/kubernetes/pkg/credentialprovider/rancher"
// Network plugins
"k8s.io/kubernetes/pkg/kubelet/network"
"k8s.io/kubernetes/pkg/kubelet/network/cni"

View File

@ -51,6 +51,7 @@ filegroup(
"//pkg/credentialprovider/aws:all-srcs",
"//pkg/credentialprovider/azure:all-srcs",
"//pkg/credentialprovider/gcp:all-srcs",
"//pkg/credentialprovider/rancher:all-srcs",
],
tags = ["automanaged"],
)

View File

@ -0,0 +1,47 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_test(
name = "go_default_test",
srcs = ["rancher_registry_credentials_test.go"],
library = ":go_default_library",
tags = ["automanaged"],
deps = [
"//pkg/credentialprovider:go_default_library",
"//vendor:github.com/rancher/go-rancher/client",
],
)
go_library(
name = "go_default_library",
srcs = [
"doc.go",
"rancher_registry_credentials.go",
],
tags = ["automanaged"],
deps = [
"//pkg/credentialprovider:go_default_library",
"//vendor:github.com/golang/glog",
"//vendor:github.com/rancher/go-rancher/client",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)

View File

@ -0,0 +1 @@
package rancher_credentials

View File

@ -0,0 +1,129 @@
package rancher_credentials
import (
"os"
"time"
"github.com/golang/glog"
"github.com/rancher/go-rancher/client"
"k8s.io/kubernetes/pkg/credentialprovider"
)
// rancher provider
type rancherProvider struct {
credGetter credentialsGetter
}
// credentials getter from Rancher private registry
type rancherCredentialsGetter struct {
client *client.RancherClient
}
type rConfig struct {
Global configGlobal
}
// An interface for testing purposes.
type credentialsGetter interface {
getCredentials() []registryCredential
}
type configGlobal struct {
CattleURL string `gcfg:"cattle-url"`
CattleAccessKey string `gcfg:"cattle-access-key"`
CattleSecretKey string `gcfg:"cattle-secret-key"`
}
type registryCredential struct {
credential *client.RegistryCredential
serverIP string
}
var rancherGetter = &rancherCredentialsGetter{}
func init() {
credentialprovider.RegisterCredentialProvider("rancher-registry-creds",
&credentialprovider.CachingDockerConfigProvider{
Provider: &rancherProvider{rancherGetter},
Lifetime: 30 * time.Second,
})
}
func (p *rancherProvider) Enabled() bool {
client, err := getRancherClient()
if err != nil {
return false
}
if client == nil {
return false
}
rancherGetter.client = client
return true
}
// LazyProvide implements DockerConfigProvider. Should never be called.
func (p *rancherProvider) LazyProvide() *credentialprovider.DockerConfigEntry {
return nil
}
// Provide implements DockerConfigProvider.Provide, refreshing Rancher tokens on demand
func (p *rancherProvider) Provide() credentialprovider.DockerConfig {
cfg := credentialprovider.DockerConfig{}
for _, cred := range p.credGetter.getCredentials() {
entry := credentialprovider.DockerConfigEntry{
Username: cred.credential.PublicValue,
Password: cred.credential.SecretValue,
Email: cred.credential.Email,
}
cfg[cred.serverIP] = entry
}
return cfg
}
func (g *rancherCredentialsGetter) getCredentials() []registryCredential {
var registryCreds []registryCredential
credColl, err := g.client.RegistryCredential.List(client.NewListOpts())
if err != nil {
glog.Errorf("Failed to pull registry credentials from rancher %v", err)
return registryCreds
}
for _, cred := range credColl.Data {
registry := &client.Registry{}
if err = g.client.GetLink(cred.Resource, "registry", registry); err != nil {
glog.Errorf("Failed to pull registry from rancher %v", err)
return registryCreds
}
registryCred := registryCredential{
credential: &cred,
serverIP: registry.ServerAddress,
}
registryCreds = append(registryCreds, registryCred)
}
return registryCreds
}
func getRancherClient() (*client.RancherClient, error) {
url := os.Getenv("CATTLE_URL")
accessKey := os.Getenv("CATTLE_ACCESS_KEY")
secretKey := os.Getenv("CATTLE_SECRET_KEY")
if url == "" || accessKey == "" || secretKey == "" {
return nil, nil
}
conf := rConfig{
Global: configGlobal{
CattleURL: url,
CattleAccessKey: accessKey,
CattleSecretKey: secretKey,
},
}
return client.NewRancherClient(&client.ClientOpts{
Url: conf.Global.CattleURL,
AccessKey: conf.Global.CattleAccessKey,
SecretKey: conf.Global.CattleSecretKey,
})
}

View File

@ -0,0 +1,104 @@
package rancher_credentials
import (
"path"
"testing"
"github.com/rancher/go-rancher/client"
"k8s.io/kubernetes/pkg/credentialprovider"
)
const username = "foo"
const password = "qwerty"
const email = "foo@bar.baz"
var serverAddresses = []string{"quay.io", "192.168.5.0"}
type testCredentialsGetter struct {
client *client.RancherClient
}
func (p *testCredentialsGetter) getCredentials() []registryCredential {
var registryCreds []registryCredential
for _, serverAddress := range serverAddresses {
cred := &client.RegistryCredential{
PublicValue: username,
SecretValue: password,
Email: email,
}
registryCred := registryCredential{
credential: cred,
serverIP: serverAddress,
}
registryCreds = append(registryCreds, registryCred)
}
return registryCreds
}
func TestRancherCredentialsProvide(t *testing.T) {
image := "foo/bar"
url := "http://localhost:8080"
accessKey := "B481F55E0C48C546E094"
secretKey := "dND2fBcytWWvCRJ8LvqnYcjyNfEkaikvfVxk2C5r"
conf := rConfig{
Global: configGlobal{
CattleURL: url,
CattleAccessKey: accessKey,
CattleSecretKey: secretKey,
},
}
rancherClient, _ := client.NewRancherClient(&client.ClientOpts{
Url: conf.Global.CattleURL,
AccessKey: conf.Global.CattleAccessKey,
SecretKey: conf.Global.CattleSecretKey,
})
testGetter := &testCredentialsGetter{
client: rancherClient,
}
provider := &rancherProvider{
credGetter: testGetter,
}
keyring := &credentialprovider.BasicDockerKeyring{}
keyring.Add(provider.Provide())
for _, registry := range serverAddresses {
fullImagePath := path.Join(registry, image)
creds, ok := keyring.Lookup(fullImagePath)
if !ok {
t.Errorf("Didn't find expected image: %s", fullImagePath)
return
}
if len(creds) > 1 {
t.Errorf("Expected 1 result, received %v", len(creds))
}
val := creds[0]
if username != val.Username {
t.Errorf("Unexpected username value, want: %s, got: %s", username, val.Username)
}
if password != val.Password {
t.Errorf("Unexpected password value, want: %s, got: %s", password, val.Password)
}
if email != val.Email {
t.Errorf("Unexpected email value, want: %s, got: %s", email, val.Email)
}
}
// try to fetch non-existing registry
fullImagePath := path.Join("1.1.1.1", image)
_, ok := keyring.Lookup(fullImagePath)
if ok {
t.Errorf("Found non-existing image: %s", fullImagePath)
}
return
}