mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-17 23:57:49 +00:00
credentialprovider: track kube secrets as creds sources in DockerKeyrings
This commit is contained in:
parent
e549eeb796
commit
09284d926c
@ -17,6 +17,9 @@ limitations under the License.
|
|||||||
package credentialprovider
|
package credentialprovider
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/sha256"
|
||||||
|
"encoding/hex"
|
||||||
|
"encoding/json"
|
||||||
"net"
|
"net"
|
||||||
"net/url"
|
"net/url"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@ -24,7 +27,9 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
|
"k8s.io/kubernetes/pkg/features"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DockerKeyring tracks a set of docker registry credentials, maintaining a
|
// DockerKeyring tracks a set of docker registry credentials, maintaining a
|
||||||
@ -35,13 +40,13 @@ import (
|
|||||||
// most specific match for a given image
|
// most specific match for a given image
|
||||||
// - iterating a map does not yield predictable results
|
// - iterating a map does not yield predictable results
|
||||||
type DockerKeyring interface {
|
type DockerKeyring interface {
|
||||||
Lookup(image string) ([]AuthConfig, bool)
|
Lookup(image string) ([]TrackedAuthConfig, bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
// BasicDockerKeyring is a trivial map-backed implementation of DockerKeyring
|
// BasicDockerKeyring is a trivial map-backed implementation of DockerKeyring
|
||||||
type BasicDockerKeyring struct {
|
type BasicDockerKeyring struct {
|
||||||
index []string
|
index []string
|
||||||
creds map[string][]AuthConfig
|
creds map[string][]TrackedAuthConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
// providersDockerKeyring is an implementation of DockerKeyring that
|
// providersDockerKeyring is an implementation of DockerKeyring that
|
||||||
@ -50,6 +55,47 @@ type providersDockerKeyring struct {
|
|||||||
Providers []DockerConfigProvider
|
Providers []DockerConfigProvider
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TrackedAuthConfig wraps the AuthConfig and adds information about the source
|
||||||
|
// of the credentials.
|
||||||
|
type TrackedAuthConfig struct {
|
||||||
|
AuthConfig
|
||||||
|
AuthConfigHash string
|
||||||
|
|
||||||
|
Source *CredentialSource
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewTrackedAuthConfig initializes the TrackedAuthConfig structure by adding
|
||||||
|
// the source information to the supplied AuthConfig. It also counts a hash of the
|
||||||
|
// AuthConfig and keeps it in the returned structure.
|
||||||
|
//
|
||||||
|
// The supplied CredentialSource is only used when the "KubeletEnsureSecretPulledImages"
|
||||||
|
// is enabled, the same applies for counting the hash.
|
||||||
|
func NewTrackedAuthConfig(c *AuthConfig, src *CredentialSource) *TrackedAuthConfig {
|
||||||
|
if c == nil {
|
||||||
|
panic("cannot construct TrackedAuthConfig with a nil AuthConfig")
|
||||||
|
}
|
||||||
|
|
||||||
|
authConfig := &TrackedAuthConfig{
|
||||||
|
AuthConfig: *c,
|
||||||
|
}
|
||||||
|
|
||||||
|
if utilfeature.DefaultFeatureGate.Enabled(features.KubeletEnsureSecretPulledImages) {
|
||||||
|
authConfig.Source = src
|
||||||
|
authConfig.AuthConfigHash = hashAuthConfig(c)
|
||||||
|
}
|
||||||
|
return authConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
type CredentialSource struct {
|
||||||
|
Secret SecretCoordinates
|
||||||
|
}
|
||||||
|
|
||||||
|
type SecretCoordinates struct {
|
||||||
|
UID string
|
||||||
|
Namespace string
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
// AuthConfig contains authorization information for connecting to a Registry
|
// AuthConfig contains authorization information for connecting to a Registry
|
||||||
// This type mirrors "github.com/docker/docker/api/types.AuthConfig"
|
// This type mirrors "github.com/docker/docker/api/types.AuthConfig"
|
||||||
type AuthConfig struct {
|
type AuthConfig struct {
|
||||||
@ -72,11 +118,13 @@ type AuthConfig struct {
|
|||||||
RegistryToken string `json:"registrytoken,omitempty"`
|
RegistryToken string `json:"registrytoken,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add add some docker config in basic docker keyring
|
// Add inserts the docker config `cfg` into the basic docker keyring. It attaches
|
||||||
func (dk *BasicDockerKeyring) Add(cfg DockerConfig) {
|
// the `src` information that describes where the docker config `cfg` comes from.
|
||||||
|
// `src` is nil if the docker config is globally available on the node.
|
||||||
|
func (dk *BasicDockerKeyring) Add(src *CredentialSource, cfg DockerConfig) {
|
||||||
if dk.index == nil {
|
if dk.index == nil {
|
||||||
dk.index = make([]string, 0)
|
dk.index = make([]string, 0)
|
||||||
dk.creds = make(map[string][]AuthConfig)
|
dk.creds = make(map[string][]TrackedAuthConfig)
|
||||||
}
|
}
|
||||||
for loc, ident := range cfg {
|
for loc, ident := range cfg {
|
||||||
creds := AuthConfig{
|
creds := AuthConfig{
|
||||||
@ -111,7 +159,9 @@ func (dk *BasicDockerKeyring) Add(cfg DockerConfig) {
|
|||||||
} else {
|
} else {
|
||||||
key = parsed.Host
|
key = parsed.Host
|
||||||
}
|
}
|
||||||
dk.creds[key] = append(dk.creds[key], creds)
|
trackedCreds := NewTrackedAuthConfig(&creds, src)
|
||||||
|
|
||||||
|
dk.creds[key] = append(dk.creds[key], *trackedCreds)
|
||||||
dk.index = append(dk.index, key)
|
dk.index = append(dk.index, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -235,9 +285,9 @@ func URLsMatch(globURL *url.URL, targetURL *url.URL) (bool, error) {
|
|||||||
// Lookup implements the DockerKeyring method for fetching credentials based on image name.
|
// Lookup implements the DockerKeyring method for fetching credentials based on image name.
|
||||||
// Multiple credentials may be returned if there are multiple potentially valid credentials
|
// Multiple credentials may be returned if there are multiple potentially valid credentials
|
||||||
// available. This allows for rotation.
|
// available. This allows for rotation.
|
||||||
func (dk *BasicDockerKeyring) Lookup(image string) ([]AuthConfig, bool) {
|
func (dk *BasicDockerKeyring) Lookup(image string) ([]TrackedAuthConfig, bool) {
|
||||||
// range over the index as iterating over a map does not provide a predictable ordering
|
// range over the index as iterating over a map does not provide a predictable ordering
|
||||||
ret := []AuthConfig{}
|
ret := []TrackedAuthConfig{}
|
||||||
for _, k := range dk.index {
|
for _, k := range dk.index {
|
||||||
// both k and image are schemeless URLs because even though schemes are allowed
|
// both k and image are schemeless URLs because even though schemes are allowed
|
||||||
// in the credential configurations, we remove them in Add.
|
// in the credential configurations, we remove them in Add.
|
||||||
@ -257,16 +307,18 @@ func (dk *BasicDockerKeyring) Lookup(image string) ([]AuthConfig, bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return []AuthConfig{}, false
|
return []TrackedAuthConfig{}, false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lookup implements the DockerKeyring method for fetching credentials
|
// Lookup implements the DockerKeyring method for fetching credentials
|
||||||
// based on image name.
|
// based on image name.
|
||||||
func (dk *providersDockerKeyring) Lookup(image string) ([]AuthConfig, bool) {
|
func (dk *providersDockerKeyring) Lookup(image string) ([]TrackedAuthConfig, bool) {
|
||||||
keyring := &BasicDockerKeyring{}
|
keyring := &BasicDockerKeyring{}
|
||||||
|
|
||||||
for _, p := range dk.Providers {
|
for _, p := range dk.Providers {
|
||||||
keyring.Add(p.Provide(image))
|
// TODO: the source should probably change once we depend on service accounts (KEP-4412).
|
||||||
|
// Perhaps `Provide()` should return the source modified to accommodate this?
|
||||||
|
keyring.Add(nil, p.Provide(image))
|
||||||
}
|
}
|
||||||
|
|
||||||
return keyring.Lookup(image)
|
return keyring.Lookup(image)
|
||||||
@ -274,13 +326,13 @@ func (dk *providersDockerKeyring) Lookup(image string) ([]AuthConfig, bool) {
|
|||||||
|
|
||||||
// FakeKeyring a fake config credentials
|
// FakeKeyring a fake config credentials
|
||||||
type FakeKeyring struct {
|
type FakeKeyring struct {
|
||||||
auth []AuthConfig
|
auth []TrackedAuthConfig
|
||||||
ok bool
|
ok bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lookup implements the DockerKeyring method for fetching credentials based on image name
|
// Lookup implements the DockerKeyring method for fetching credentials based on image name
|
||||||
// return fake auth and ok
|
// return fake auth and ok
|
||||||
func (f *FakeKeyring) Lookup(image string) ([]AuthConfig, bool) {
|
func (f *FakeKeyring) Lookup(image string) ([]TrackedAuthConfig, bool) {
|
||||||
return f.auth, f.ok
|
return f.auth, f.ok
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -289,8 +341,8 @@ type UnionDockerKeyring []DockerKeyring
|
|||||||
|
|
||||||
// Lookup implements the DockerKeyring method for fetching credentials based on image name.
|
// Lookup implements the DockerKeyring method for fetching credentials based on image name.
|
||||||
// return each credentials
|
// return each credentials
|
||||||
func (k UnionDockerKeyring) Lookup(image string) ([]AuthConfig, bool) {
|
func (k UnionDockerKeyring) Lookup(image string) ([]TrackedAuthConfig, bool) {
|
||||||
authConfigs := []AuthConfig{}
|
authConfigs := []TrackedAuthConfig{}
|
||||||
for _, subKeyring := range k {
|
for _, subKeyring := range k {
|
||||||
if subKeyring == nil {
|
if subKeyring == nil {
|
||||||
continue
|
continue
|
||||||
@ -302,3 +354,14 @@ func (k UnionDockerKeyring) Lookup(image string) ([]AuthConfig, bool) {
|
|||||||
|
|
||||||
return authConfigs, (len(authConfigs) > 0)
|
return authConfigs, (len(authConfigs) > 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func hashAuthConfig(creds *AuthConfig) string {
|
||||||
|
credBytes, err := json.Marshal(creds)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
hash := sha256.New()
|
||||||
|
hash.Write([]byte(credBytes))
|
||||||
|
return hex.EncodeToString(hash.Sum(nil))
|
||||||
|
}
|
||||||
|
@ -21,6 +21,10 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
|
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||||
|
"k8s.io/kubernetes/pkg/features"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestURLsMatch(t *testing.T) {
|
func TestURLsMatch(t *testing.T) {
|
||||||
@ -222,7 +226,7 @@ func TestDockerKeyringForGlob(t *testing.T) {
|
|||||||
if cfg, err := ReadDockerConfigFileFromBytes([]byte(sampleDockerConfig)); err != nil {
|
if cfg, err := ReadDockerConfigFileFromBytes([]byte(sampleDockerConfig)); err != nil {
|
||||||
t.Errorf("Error processing json blob %q, %v", sampleDockerConfig, err)
|
t.Errorf("Error processing json blob %q, %v", sampleDockerConfig, err)
|
||||||
} else {
|
} else {
|
||||||
keyring.Add(cfg)
|
keyring.Add(nil, cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
creds, ok := keyring.Lookup(test.targetURL + "/foo/bar")
|
creds, ok := keyring.Lookup(test.targetURL + "/foo/bar")
|
||||||
@ -290,7 +294,7 @@ func TestKeyringMiss(t *testing.T) {
|
|||||||
if cfg, err := ReadDockerConfigFileFromBytes([]byte(sampleDockerConfig)); err != nil {
|
if cfg, err := ReadDockerConfigFileFromBytes([]byte(sampleDockerConfig)); err != nil {
|
||||||
t.Errorf("Error processing json blob %q, %v", sampleDockerConfig, err)
|
t.Errorf("Error processing json blob %q, %v", sampleDockerConfig, err)
|
||||||
} else {
|
} else {
|
||||||
keyring.Add(cfg)
|
keyring.Add(nil, cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, ok := keyring.Lookup(test.lookupURL + "/foo/bar")
|
_, ok := keyring.Lookup(test.lookupURL + "/foo/bar")
|
||||||
@ -318,7 +322,7 @@ func TestKeyringMissWithDockerHubCredentials(t *testing.T) {
|
|||||||
if cfg, err := ReadDockerConfigFileFromBytes([]byte(sampleDockerConfig)); err != nil {
|
if cfg, err := ReadDockerConfigFileFromBytes([]byte(sampleDockerConfig)); err != nil {
|
||||||
t.Errorf("Error processing json blob %q, %v", sampleDockerConfig, err)
|
t.Errorf("Error processing json blob %q, %v", sampleDockerConfig, err)
|
||||||
} else {
|
} else {
|
||||||
keyring.Add(cfg)
|
keyring.Add(nil, cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
val, ok := keyring.Lookup("world.mesos.org/foo/bar")
|
val, ok := keyring.Lookup("world.mesos.org/foo/bar")
|
||||||
@ -344,7 +348,7 @@ func TestKeyringHitWithUnqualifiedDockerHub(t *testing.T) {
|
|||||||
if cfg, err := ReadDockerConfigFileFromBytes([]byte(sampleDockerConfig)); err != nil {
|
if cfg, err := ReadDockerConfigFileFromBytes([]byte(sampleDockerConfig)); err != nil {
|
||||||
t.Errorf("Error processing json blob %q, %v", sampleDockerConfig, err)
|
t.Errorf("Error processing json blob %q, %v", sampleDockerConfig, err)
|
||||||
} else {
|
} else {
|
||||||
keyring.Add(cfg)
|
keyring.Add(nil, cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
creds, ok := keyring.Lookup("google/docker-registry")
|
creds, ok := keyring.Lookup("google/docker-registry")
|
||||||
@ -353,7 +357,7 @@ func TestKeyringHitWithUnqualifiedDockerHub(t *testing.T) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if len(creds) > 1 {
|
if len(creds) > 1 {
|
||||||
t.Errorf("Got more hits than expected: %s", creds)
|
t.Errorf("Got more hits than expected: %v", creds)
|
||||||
}
|
}
|
||||||
val := creds[0]
|
val := creds[0]
|
||||||
|
|
||||||
@ -385,7 +389,7 @@ func TestKeyringHitWithUnqualifiedLibraryDockerHub(t *testing.T) {
|
|||||||
if cfg, err := ReadDockerConfigFileFromBytes([]byte(sampleDockerConfig)); err != nil {
|
if cfg, err := ReadDockerConfigFileFromBytes([]byte(sampleDockerConfig)); err != nil {
|
||||||
t.Errorf("Error processing json blob %q, %v", sampleDockerConfig, err)
|
t.Errorf("Error processing json blob %q, %v", sampleDockerConfig, err)
|
||||||
} else {
|
} else {
|
||||||
keyring.Add(cfg)
|
keyring.Add(nil, cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
creds, ok := keyring.Lookup("jenkins")
|
creds, ok := keyring.Lookup("jenkins")
|
||||||
@ -394,7 +398,7 @@ func TestKeyringHitWithUnqualifiedLibraryDockerHub(t *testing.T) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if len(creds) > 1 {
|
if len(creds) > 1 {
|
||||||
t.Errorf("Got more hits than expected: %s", creds)
|
t.Errorf("Got more hits than expected: %v", creds)
|
||||||
}
|
}
|
||||||
val := creds[0]
|
val := creds[0]
|
||||||
|
|
||||||
@ -426,7 +430,7 @@ func TestKeyringHitWithQualifiedDockerHub(t *testing.T) {
|
|||||||
if cfg, err := ReadDockerConfigFileFromBytes([]byte(sampleDockerConfig)); err != nil {
|
if cfg, err := ReadDockerConfigFileFromBytes([]byte(sampleDockerConfig)); err != nil {
|
||||||
t.Errorf("Error processing json blob %q, %v", sampleDockerConfig, err)
|
t.Errorf("Error processing json blob %q, %v", sampleDockerConfig, err)
|
||||||
} else {
|
} else {
|
||||||
keyring.Add(cfg)
|
keyring.Add(nil, cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
creds, ok := keyring.Lookup(url + "/google/docker-registry")
|
creds, ok := keyring.Lookup(url + "/google/docker-registry")
|
||||||
@ -435,7 +439,7 @@ func TestKeyringHitWithQualifiedDockerHub(t *testing.T) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if len(creds) > 2 {
|
if len(creds) > 2 {
|
||||||
t.Errorf("Got more hits than expected: %s", creds)
|
t.Errorf("Got more hits than expected: %v", creds)
|
||||||
}
|
}
|
||||||
val := creds[0]
|
val := creds[0]
|
||||||
|
|
||||||
@ -498,20 +502,24 @@ func TestProvidersDockerKeyring(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestDockerKeyringLookup(t *testing.T) {
|
func TestDockerKeyringLookup(t *testing.T) {
|
||||||
|
// turn on the ensure secret pulled images feature to get the hashes with the creds
|
||||||
|
featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.KubeletEnsureSecretPulledImages, true)
|
||||||
ada := AuthConfig{
|
ada := AuthConfig{
|
||||||
Username: "ada",
|
Username: "ada",
|
||||||
Password: "smash", // Fake value for testing.
|
Password: "smash", // Fake value for testing.
|
||||||
Email: "ada@example.com",
|
Email: "ada@example.com",
|
||||||
}
|
}
|
||||||
|
adaHash := "353258b53f5e9a57b059eab3f05312fc35bbeb874f08ce101e7bf0bf46977423"
|
||||||
|
|
||||||
grace := AuthConfig{
|
grace := AuthConfig{
|
||||||
Username: "grace",
|
Username: "grace",
|
||||||
Password: "squash", // Fake value for testing.
|
Password: "squash", // Fake value for testing.
|
||||||
Email: "grace@example.com",
|
Email: "grace@example.com",
|
||||||
}
|
}
|
||||||
|
graceHash := "f949b3837a1eb733a951b6aeda0b3327c09ec50c917de9ca35818e8fbf567e29"
|
||||||
|
|
||||||
dk := &BasicDockerKeyring{}
|
dk := &BasicDockerKeyring{}
|
||||||
dk.Add(DockerConfig{
|
dk.Add(nil, DockerConfig{
|
||||||
"bar.example.com/pong": DockerConfigEntry{
|
"bar.example.com/pong": DockerConfigEntry{
|
||||||
Username: grace.Username,
|
Username: grace.Username,
|
||||||
Password: grace.Password,
|
Password: grace.Password,
|
||||||
@ -526,27 +534,27 @@ func TestDockerKeyringLookup(t *testing.T) {
|
|||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
image string
|
image string
|
||||||
match []AuthConfig
|
match []TrackedAuthConfig
|
||||||
ok bool
|
ok bool
|
||||||
}{
|
}{
|
||||||
// direct match
|
// direct match
|
||||||
{"bar.example.com", []AuthConfig{ada}, true},
|
{"bar.example.com", []TrackedAuthConfig{{AuthConfig: ada, AuthConfigHash: adaHash}}, true},
|
||||||
|
|
||||||
// direct match deeper than other possible matches
|
// direct match deeper than other possible matches
|
||||||
{"bar.example.com/pong", []AuthConfig{grace, ada}, true},
|
{"bar.example.com/pong", []TrackedAuthConfig{{AuthConfig: grace, AuthConfigHash: graceHash}, {AuthConfig: ada, AuthConfigHash: adaHash}}, true},
|
||||||
|
|
||||||
// no direct match, deeper path ignored
|
// no direct match, deeper path ignored
|
||||||
{"bar.example.com/ping", []AuthConfig{ada}, true},
|
{"bar.example.com/ping", []TrackedAuthConfig{{AuthConfig: ada, AuthConfigHash: adaHash}}, true},
|
||||||
|
|
||||||
// match first part of path token
|
// match first part of path token
|
||||||
{"bar.example.com/pongz", []AuthConfig{grace, ada}, true},
|
{"bar.example.com/pongz", []TrackedAuthConfig{{AuthConfig: grace, AuthConfigHash: graceHash}, {AuthConfig: ada, AuthConfigHash: adaHash}}, true},
|
||||||
|
|
||||||
// match regardless of sub-path
|
// match regardless of sub-path
|
||||||
{"bar.example.com/pong/pang", []AuthConfig{grace, ada}, true},
|
{"bar.example.com/pong/pang", []TrackedAuthConfig{{AuthConfig: grace, AuthConfigHash: graceHash}, {AuthConfig: ada, AuthConfigHash: adaHash}}, true},
|
||||||
|
|
||||||
// no host match
|
// no host match
|
||||||
{"example.com", []AuthConfig{}, false},
|
{"example.com", []TrackedAuthConfig{}, false},
|
||||||
{"foo.example.com", []AuthConfig{}, false},
|
{"foo.example.com", []TrackedAuthConfig{}, false},
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, tt := range tests {
|
for i, tt := range tests {
|
||||||
@ -565,14 +573,17 @@ func TestDockerKeyringLookup(t *testing.T) {
|
|||||||
// by images that only match the hostname.
|
// by images that only match the hostname.
|
||||||
// NOTE: the above covers the case of a more specific match trumping just hostname.
|
// NOTE: the above covers the case of a more specific match trumping just hostname.
|
||||||
func TestIssue3797(t *testing.T) {
|
func TestIssue3797(t *testing.T) {
|
||||||
|
// turn on the ensure secret pulled images feature to get the hashes with the creds
|
||||||
|
featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.KubeletEnsureSecretPulledImages, true)
|
||||||
rex := AuthConfig{
|
rex := AuthConfig{
|
||||||
Username: "rex",
|
Username: "rex",
|
||||||
Password: "tiny arms", // Fake value for testing.
|
Password: "tiny arms", // Fake value for testing.
|
||||||
Email: "rex@example.com",
|
Email: "rex@example.com",
|
||||||
}
|
}
|
||||||
|
rexHash := "899748fec74c8dd761845fca727f4249b05be275ff24026676fcd4351f656363"
|
||||||
|
|
||||||
dk := &BasicDockerKeyring{}
|
dk := &BasicDockerKeyring{}
|
||||||
dk.Add(DockerConfig{
|
dk.Add(nil, DockerConfig{
|
||||||
"https://quay.io/v1/": DockerConfigEntry{
|
"https://quay.io/v1/": DockerConfigEntry{
|
||||||
Username: rex.Username,
|
Username: rex.Username,
|
||||||
Password: rex.Password,
|
Password: rex.Password,
|
||||||
@ -582,15 +593,15 @@ func TestIssue3797(t *testing.T) {
|
|||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
image string
|
image string
|
||||||
match []AuthConfig
|
match []TrackedAuthConfig
|
||||||
ok bool
|
ok bool
|
||||||
}{
|
}{
|
||||||
// direct match
|
// direct match
|
||||||
{"quay.io", []AuthConfig{rex}, true},
|
{"quay.io", []TrackedAuthConfig{{AuthConfig: rex, AuthConfigHash: rexHash}}, true},
|
||||||
|
|
||||||
// partial matches
|
// partial matches
|
||||||
{"quay.io/foo", []AuthConfig{rex}, true},
|
{"quay.io/foo", []TrackedAuthConfig{{AuthConfig: rex, AuthConfigHash: rexHash}}, true},
|
||||||
{"quay.io/foo/bar", []AuthConfig{rex}, true},
|
{"quay.io/foo/bar", []TrackedAuthConfig{{AuthConfig: rex, AuthConfigHash: rexHash}}, true},
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, tt := range tests {
|
for i, tt := range tests {
|
||||||
|
@ -27,32 +27,52 @@ import (
|
|||||||
// then a DockerKeyring is built based on every hit and unioned with the defaultKeyring.
|
// then a DockerKeyring is built based on every hit and unioned with the defaultKeyring.
|
||||||
// If they do not, then the default keyring is returned
|
// If they do not, then the default keyring is returned
|
||||||
func MakeDockerKeyring(passedSecrets []v1.Secret, defaultKeyring credentialprovider.DockerKeyring) (credentialprovider.DockerKeyring, error) {
|
func MakeDockerKeyring(passedSecrets []v1.Secret, defaultKeyring credentialprovider.DockerKeyring) (credentialprovider.DockerKeyring, error) {
|
||||||
passedCredentials := []credentialprovider.DockerConfig{}
|
providerFromSecrets, err := secretsToTrackedDockerConfigs(passedSecrets)
|
||||||
for _, passedSecret := range passedSecrets {
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if providerFromSecrets == nil {
|
||||||
|
return defaultKeyring, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return credentialprovider.UnionDockerKeyring{providerFromSecrets, defaultKeyring}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func secretsToTrackedDockerConfigs(secrets []v1.Secret) (credentialprovider.DockerKeyring, error) {
|
||||||
|
provider := &credentialprovider.BasicDockerKeyring{}
|
||||||
|
validSecretsFound := 0
|
||||||
|
for _, passedSecret := range secrets {
|
||||||
if dockerConfigJSONBytes, dockerConfigJSONExists := passedSecret.Data[v1.DockerConfigJsonKey]; (passedSecret.Type == v1.SecretTypeDockerConfigJson) && dockerConfigJSONExists && (len(dockerConfigJSONBytes) > 0) {
|
if dockerConfigJSONBytes, dockerConfigJSONExists := passedSecret.Data[v1.DockerConfigJsonKey]; (passedSecret.Type == v1.SecretTypeDockerConfigJson) && dockerConfigJSONExists && (len(dockerConfigJSONBytes) > 0) {
|
||||||
dockerConfigJSON := credentialprovider.DockerConfigJSON{}
|
dockerConfigJSON := credentialprovider.DockerConfigJSON{}
|
||||||
if err := json.Unmarshal(dockerConfigJSONBytes, &dockerConfigJSON); err != nil {
|
if err := json.Unmarshal(dockerConfigJSONBytes, &dockerConfigJSON); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
passedCredentials = append(passedCredentials, dockerConfigJSON.Auths)
|
coords := credentialprovider.SecretCoordinates{
|
||||||
|
UID: string(passedSecret.UID),
|
||||||
|
Namespace: passedSecret.Namespace,
|
||||||
|
Name: passedSecret.Name}
|
||||||
|
|
||||||
|
provider.Add(&credentialprovider.CredentialSource{Secret: coords}, dockerConfigJSON.Auths)
|
||||||
|
validSecretsFound++
|
||||||
} else if dockercfgBytes, dockercfgExists := passedSecret.Data[v1.DockerConfigKey]; (passedSecret.Type == v1.SecretTypeDockercfg) && dockercfgExists && (len(dockercfgBytes) > 0) {
|
} else if dockercfgBytes, dockercfgExists := passedSecret.Data[v1.DockerConfigKey]; (passedSecret.Type == v1.SecretTypeDockercfg) && dockercfgExists && (len(dockercfgBytes) > 0) {
|
||||||
dockercfg := credentialprovider.DockerConfig{}
|
dockercfg := credentialprovider.DockerConfig{}
|
||||||
if err := json.Unmarshal(dockercfgBytes, &dockercfg); err != nil {
|
if err := json.Unmarshal(dockercfgBytes, &dockercfg); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
passedCredentials = append(passedCredentials, dockercfg)
|
coords := credentialprovider.SecretCoordinates{
|
||||||
|
UID: string(passedSecret.UID),
|
||||||
|
Namespace: passedSecret.Namespace,
|
||||||
|
Name: passedSecret.Name}
|
||||||
|
provider.Add(&credentialprovider.CredentialSource{Secret: coords}, dockercfg)
|
||||||
|
validSecretsFound++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(passedCredentials) > 0 {
|
if validSecretsFound == 0 {
|
||||||
basicKeyring := &credentialprovider.BasicDockerKeyring{}
|
return nil, nil
|
||||||
for _, currCredentials := range passedCredentials {
|
|
||||||
basicKeyring.Add(currCredentials)
|
|
||||||
}
|
}
|
||||||
return credentialprovider.UnionDockerKeyring{basicKeyring, defaultKeyring}, nil
|
return provider, nil
|
||||||
}
|
|
||||||
|
|
||||||
return defaultKeyring, nil
|
|
||||||
}
|
}
|
||||||
|
@ -20,243 +20,316 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
|
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||||
"k8s.io/kubernetes/pkg/credentialprovider"
|
"k8s.io/kubernetes/pkg/credentialprovider"
|
||||||
|
"k8s.io/kubernetes/pkg/features"
|
||||||
)
|
)
|
||||||
|
|
||||||
// fakeKeyring is a fake docker auth config keyring
|
// FakeKeyring a fake config credentials
|
||||||
type fakeKeyring struct {
|
type FakeKeyring struct {
|
||||||
auth []credentialprovider.AuthConfig
|
auth []credentialprovider.TrackedAuthConfig
|
||||||
ok bool
|
ok bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lookup implements the DockerKeyring method for fetching credentials based on image name.
|
// Lookup implements the DockerKeyring method for fetching credentials based on image name
|
||||||
// Returns fake results based on the auth and ok fields in fakeKeyring
|
// return fake auth and ok
|
||||||
func (f *fakeKeyring) Lookup(image string) ([]credentialprovider.AuthConfig, bool) {
|
func (f *FakeKeyring) Lookup(image string) ([]credentialprovider.TrackedAuthConfig, bool) {
|
||||||
return f.auth, f.ok
|
return f.auth, f.ok
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_MakeDockerKeyring(t *testing.T) {
|
func Test_MakeDockerKeyring(t *testing.T) {
|
||||||
|
featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.KubeletEnsureSecretPulledImages, true)
|
||||||
|
|
||||||
testcases := []struct {
|
testcases := []struct {
|
||||||
name string
|
name string
|
||||||
image string
|
image string
|
||||||
defaultKeyring credentialprovider.DockerKeyring
|
defaultKeyring credentialprovider.DockerKeyring
|
||||||
pullSecrets []v1.Secret
|
pullSecrets []v1.Secret
|
||||||
authConfigs []credentialprovider.AuthConfig
|
expectedAuthConfigs []credentialprovider.TrackedAuthConfig
|
||||||
found bool
|
found bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "with .dockerconfigjson and auth field",
|
name: "with .dockerconfigjson and auth field",
|
||||||
image: "test.registry.io",
|
image: "test.registry.io",
|
||||||
defaultKeyring: &fakeKeyring{},
|
|
||||||
pullSecrets: []v1.Secret{
|
pullSecrets: []v1.Secret{
|
||||||
{
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "s1", Namespace: "ns1", UID: "uid1"},
|
||||||
Type: v1.SecretTypeDockerConfigJson,
|
Type: v1.SecretTypeDockerConfigJson,
|
||||||
Data: map[string][]byte{
|
Data: map[string][]byte{
|
||||||
v1.DockerConfigJsonKey: []byte(`{"auths": {"test.registry.io": {"auth": "dXNlcjpwYXNzd29yZA=="}}}`),
|
v1.DockerConfigJsonKey: []byte(`{"auths": {"test.registry.io": {"auth": "dXNlcjpwYXNzd29yZA=="}}}`),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
authConfigs: []credentialprovider.AuthConfig{
|
expectedAuthConfigs: []credentialprovider.TrackedAuthConfig{
|
||||||
{
|
{
|
||||||
|
Source: &credentialprovider.CredentialSource{
|
||||||
|
Secret: credentialprovider.SecretCoordinates{
|
||||||
|
Name: "s1", Namespace: "ns1", UID: "uid1"},
|
||||||
|
},
|
||||||
|
AuthConfig: credentialprovider.AuthConfig{
|
||||||
Username: "user",
|
Username: "user",
|
||||||
Password: "password",
|
Password: "password",
|
||||||
},
|
},
|
||||||
|
AuthConfigHash: "a55436fc140d516560d072c5fe8700385ce9f41629abf65c1edcbcb39fac691d",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
found: true,
|
found: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "with .dockerconfig and auth field",
|
name: "with .dockerconfig and auth field",
|
||||||
image: "test.registry.io",
|
image: "test.registry.io",
|
||||||
defaultKeyring: &fakeKeyring{},
|
|
||||||
pullSecrets: []v1.Secret{
|
pullSecrets: []v1.Secret{
|
||||||
{
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "s1", Namespace: "ns1", UID: "uid1"},
|
||||||
Type: v1.SecretTypeDockercfg,
|
Type: v1.SecretTypeDockercfg,
|
||||||
Data: map[string][]byte{
|
Data: map[string][]byte{
|
||||||
v1.DockerConfigKey: []byte(`{"test.registry.io": {"auth": "dXNlcjpwYXNzd29yZA=="}}`),
|
v1.DockerConfigKey: []byte(`{"test.registry.io": {"auth": "dXNlcjpwYXNzd29yZA=="}}`),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
authConfigs: []credentialprovider.AuthConfig{
|
expectedAuthConfigs: []credentialprovider.TrackedAuthConfig{
|
||||||
{
|
{
|
||||||
|
Source: &credentialprovider.CredentialSource{
|
||||||
|
Secret: credentialprovider.SecretCoordinates{
|
||||||
|
Name: "s1", Namespace: "ns1", UID: "uid1"},
|
||||||
|
},
|
||||||
|
AuthConfig: credentialprovider.AuthConfig{
|
||||||
Username: "user",
|
Username: "user",
|
||||||
Password: "password",
|
Password: "password",
|
||||||
},
|
},
|
||||||
|
AuthConfigHash: "a55436fc140d516560d072c5fe8700385ce9f41629abf65c1edcbcb39fac691d",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
found: true,
|
found: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "with .dockerconfigjson and username/password fields",
|
name: "with .dockerconfigjson and username/password fields",
|
||||||
image: "test.registry.io",
|
image: "test.registry.io",
|
||||||
defaultKeyring: &fakeKeyring{},
|
|
||||||
pullSecrets: []v1.Secret{
|
pullSecrets: []v1.Secret{
|
||||||
{
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "s1", Namespace: "ns1", UID: "uid1"},
|
||||||
Type: v1.SecretTypeDockerConfigJson,
|
Type: v1.SecretTypeDockerConfigJson,
|
||||||
Data: map[string][]byte{
|
Data: map[string][]byte{
|
||||||
v1.DockerConfigJsonKey: []byte(`{"auths": {"test.registry.io": {"username": "user", "password": "password"}}}`),
|
v1.DockerConfigJsonKey: []byte(`{"auths": {"test.registry.io": {"username": "user", "password": "password"}}}`),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
authConfigs: []credentialprovider.AuthConfig{
|
expectedAuthConfigs: []credentialprovider.TrackedAuthConfig{
|
||||||
{
|
{
|
||||||
|
Source: &credentialprovider.CredentialSource{
|
||||||
|
Secret: credentialprovider.SecretCoordinates{
|
||||||
|
Name: "s1", Namespace: "ns1", UID: "uid1"},
|
||||||
|
},
|
||||||
|
AuthConfig: credentialprovider.AuthConfig{
|
||||||
Username: "user",
|
Username: "user",
|
||||||
Password: "password",
|
Password: "password",
|
||||||
},
|
},
|
||||||
|
AuthConfigHash: "a55436fc140d516560d072c5fe8700385ce9f41629abf65c1edcbcb39fac691d",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
found: true,
|
found: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "with .dockerconfig and username/password fields",
|
name: "with .dockerconfig and username/password fields",
|
||||||
image: "test.registry.io",
|
image: "test.registry.io",
|
||||||
defaultKeyring: &fakeKeyring{},
|
|
||||||
pullSecrets: []v1.Secret{
|
pullSecrets: []v1.Secret{
|
||||||
{
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "s1", Namespace: "ns1", UID: "uid1"},
|
||||||
Type: v1.SecretTypeDockercfg,
|
Type: v1.SecretTypeDockercfg,
|
||||||
Data: map[string][]byte{
|
Data: map[string][]byte{
|
||||||
v1.DockerConfigKey: []byte(`{"test.registry.io": {"username": "user", "password": "password"}}`),
|
v1.DockerConfigKey: []byte(`{"test.registry.io": {"username": "user", "password": "password"}}`),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
authConfigs: []credentialprovider.AuthConfig{
|
expectedAuthConfigs: []credentialprovider.TrackedAuthConfig{
|
||||||
{
|
{
|
||||||
|
Source: &credentialprovider.CredentialSource{
|
||||||
|
Secret: credentialprovider.SecretCoordinates{
|
||||||
|
Name: "s1", Namespace: "ns1", UID: "uid1"},
|
||||||
|
},
|
||||||
|
AuthConfig: credentialprovider.AuthConfig{
|
||||||
Username: "user",
|
Username: "user",
|
||||||
Password: "password",
|
Password: "password",
|
||||||
},
|
},
|
||||||
|
AuthConfigHash: "a55436fc140d516560d072c5fe8700385ce9f41629abf65c1edcbcb39fac691d",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
found: true,
|
found: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "with .dockerconfigjson but with wrong Secret Type",
|
name: "with .dockerconfigjson but with wrong Secret Type",
|
||||||
image: "test.registry.io",
|
image: "test.registry.io",
|
||||||
defaultKeyring: &fakeKeyring{},
|
defaultKeyring: &FakeKeyring{},
|
||||||
pullSecrets: []v1.Secret{
|
pullSecrets: []v1.Secret{
|
||||||
{
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "s1", Namespace: "ns1", UID: "uid1"},
|
||||||
Type: v1.SecretTypeDockercfg,
|
Type: v1.SecretTypeDockercfg,
|
||||||
Data: map[string][]byte{
|
Data: map[string][]byte{
|
||||||
v1.DockerConfigJsonKey: []byte(`{"auths": {"test.registry.io": {"auth": "dXNlcjpwYXNzd29yZA=="}}}`),
|
v1.DockerConfigJsonKey: []byte(`{"auths": {"test.registry.io": {"auth": "dXNlcjpwYXNzd29yZA=="}}}`),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
authConfigs: nil,
|
|
||||||
found: false,
|
found: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "with .dockerconfig but with wrong Secret Type",
|
name: "with .dockerconfig but with wrong Secret Type",
|
||||||
image: "test.registry.io",
|
image: "test.registry.io",
|
||||||
defaultKeyring: &fakeKeyring{},
|
defaultKeyring: &FakeKeyring{},
|
||||||
pullSecrets: []v1.Secret{
|
pullSecrets: []v1.Secret{
|
||||||
{
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "s1", Namespace: "ns1", UID: "uid1"},
|
||||||
Type: v1.SecretTypeDockerConfigJson,
|
Type: v1.SecretTypeDockerConfigJson,
|
||||||
Data: map[string][]byte{
|
Data: map[string][]byte{
|
||||||
v1.DockerConfigKey: []byte(`{"test.registry.io": {"auth": "dXNlcjpwYXNzd29yZA=="}}`),
|
v1.DockerConfigKey: []byte(`{"test.registry.io": {"auth": "dXNlcjpwYXNzd29yZA=="}}`),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
authConfigs: nil,
|
|
||||||
found: false,
|
found: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "with not matcing .dockerconfigjson and default keyring",
|
name: "with not matcing .dockerconfigjson and default keyring",
|
||||||
image: "test.registry.io",
|
image: "test.registry.io",
|
||||||
defaultKeyring: &fakeKeyring{
|
defaultKeyring: &FakeKeyring{
|
||||||
auth: []credentialprovider.AuthConfig{
|
auth: []credentialprovider.TrackedAuthConfig{
|
||||||
{
|
{
|
||||||
|
AuthConfig: credentialprovider.AuthConfig{
|
||||||
Username: "default-user",
|
Username: "default-user",
|
||||||
Password: "default-password",
|
Password: "default-password",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
pullSecrets: []v1.Secret{
|
pullSecrets: []v1.Secret{
|
||||||
{
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "s1", Namespace: "ns1", UID: "uid1"},
|
||||||
Type: v1.SecretTypeDockerConfigJson,
|
Type: v1.SecretTypeDockerConfigJson,
|
||||||
Data: map[string][]byte{
|
Data: map[string][]byte{
|
||||||
v1.DockerConfigJsonKey: []byte(`{"auths": {"foobar.io": {"auth": "dXNlcjpwYXNzd29yZA=="}}}`),
|
v1.DockerConfigJsonKey: []byte(`{"auths": {"foobar.io": {"auth": "dXNlcjpwYXNzd29yZA=="}}}`),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
authConfigs: []credentialprovider.AuthConfig{
|
expectedAuthConfigs: []credentialprovider.TrackedAuthConfig{
|
||||||
{
|
{
|
||||||
|
AuthConfig: credentialprovider.AuthConfig{
|
||||||
Username: "default-user",
|
Username: "default-user",
|
||||||
Password: "default-password",
|
Password: "default-password",
|
||||||
},
|
},
|
||||||
|
AuthConfigHash: "",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
found: true,
|
found: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "with not matching .dockerconfig and default keyring",
|
name: "with not matching .dockerconfig and default keyring",
|
||||||
image: "test.registry.io",
|
image: "test.registry.io",
|
||||||
defaultKeyring: &fakeKeyring{
|
defaultKeyring: &FakeKeyring{
|
||||||
auth: []credentialprovider.AuthConfig{
|
auth: []credentialprovider.TrackedAuthConfig{
|
||||||
{
|
{
|
||||||
|
AuthConfig: credentialprovider.AuthConfig{
|
||||||
Username: "default-user",
|
Username: "default-user",
|
||||||
Password: "default-password",
|
Password: "default-password",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
pullSecrets: []v1.Secret{
|
pullSecrets: []v1.Secret{
|
||||||
{
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "s1", Namespace: "ns1", UID: "uid1"},
|
||||||
Type: v1.SecretTypeDockercfg,
|
Type: v1.SecretTypeDockercfg,
|
||||||
Data: map[string][]byte{
|
Data: map[string][]byte{
|
||||||
v1.DockerConfigKey: []byte(`{"foobar.io": {"auth": "dXNlcjpwYXNzd29yZA=="}}`),
|
v1.DockerConfigKey: []byte(`{"foobar.io": {"auth": "dXNlcjpwYXNzd29yZA=="}}`),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
authConfigs: []credentialprovider.AuthConfig{
|
expectedAuthConfigs: []credentialprovider.TrackedAuthConfig{
|
||||||
{
|
{
|
||||||
|
AuthConfig: credentialprovider.AuthConfig{
|
||||||
Username: "default-user",
|
Username: "default-user",
|
||||||
Password: "default-password",
|
Password: "default-password",
|
||||||
},
|
},
|
||||||
|
AuthConfigHash: "",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
found: true,
|
found: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "with no pull secrets but has default keyring",
|
name: "with no pull secrets but has default keyring",
|
||||||
image: "test.registry.io",
|
image: "test.registry.io",
|
||||||
defaultKeyring: &fakeKeyring{
|
defaultKeyring: &FakeKeyring{
|
||||||
auth: []credentialprovider.AuthConfig{
|
auth: []credentialprovider.TrackedAuthConfig{
|
||||||
{
|
{
|
||||||
|
AuthConfig: credentialprovider.AuthConfig{
|
||||||
Username: "default-user",
|
Username: "default-user",
|
||||||
Password: "default-password",
|
Password: "default-password",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
pullSecrets: []v1.Secret{},
|
pullSecrets: []v1.Secret{},
|
||||||
authConfigs: []credentialprovider.AuthConfig{
|
expectedAuthConfigs: []credentialprovider.TrackedAuthConfig{
|
||||||
{
|
{
|
||||||
|
AuthConfig: credentialprovider.AuthConfig{
|
||||||
Username: "default-user",
|
Username: "default-user",
|
||||||
Password: "default-password",
|
Password: "default-password",
|
||||||
},
|
},
|
||||||
|
AuthConfigHash: "",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
found: false,
|
found: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "with pull secrets and has default keyring",
|
name: "with pull secrets and has default keyring",
|
||||||
image: "test.registry.io",
|
image: "test.registry.io",
|
||||||
defaultKeyring: &fakeKeyring{
|
defaultKeyring: &FakeKeyring{
|
||||||
auth: []credentialprovider.AuthConfig{
|
auth: []credentialprovider.TrackedAuthConfig{
|
||||||
{
|
{
|
||||||
|
AuthConfig: credentialprovider.AuthConfig{
|
||||||
Username: "default-user",
|
Username: "default-user",
|
||||||
Password: "default-password",
|
Password: "default-password",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
pullSecrets: []v1.Secret{
|
pullSecrets: []v1.Secret{
|
||||||
{
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "s1", Namespace: "ns1", UID: "uid1"},
|
||||||
Type: v1.SecretTypeDockerConfigJson,
|
Type: v1.SecretTypeDockerConfigJson,
|
||||||
Data: map[string][]byte{
|
Data: map[string][]byte{
|
||||||
v1.DockerConfigJsonKey: []byte(`{"auths": {"test.registry.io": {"auth": "dXNlcjpwYXNzd29yZA=="}}}`),
|
v1.DockerConfigJsonKey: []byte(`{"auths": {"test.registry.io": {"auth": "dXNlcjpwYXNzd29yZA=="}}}`),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
authConfigs: []credentialprovider.AuthConfig{
|
expectedAuthConfigs: []credentialprovider.TrackedAuthConfig{
|
||||||
{
|
{
|
||||||
|
Source: &credentialprovider.CredentialSource{
|
||||||
|
Secret: credentialprovider.SecretCoordinates{
|
||||||
|
Name: "s1", Namespace: "ns1", UID: "uid1"},
|
||||||
|
},
|
||||||
|
AuthConfig: credentialprovider.AuthConfig{
|
||||||
Username: "user",
|
Username: "user",
|
||||||
Password: "password",
|
Password: "password",
|
||||||
},
|
},
|
||||||
|
AuthConfigHash: "a55436fc140d516560d072c5fe8700385ce9f41629abf65c1edcbcb39fac691d",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
|
AuthConfig: credentialprovider.AuthConfig{
|
||||||
Username: "default-user",
|
Username: "default-user",
|
||||||
Password: "default-password",
|
Password: "default-password",
|
||||||
},
|
},
|
||||||
|
AuthConfigHash: "",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
found: true,
|
found: true,
|
||||||
},
|
},
|
||||||
@ -276,9 +349,9 @@ func Test_MakeDockerKeyring(t *testing.T) {
|
|||||||
t.Errorf("unexpected lookup for image: %s", testcase.image)
|
t.Errorf("unexpected lookup for image: %s", testcase.image)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !reflect.DeepEqual(authConfigs, testcase.authConfigs) {
|
if !reflect.DeepEqual(authConfigs, testcase.expectedAuthConfigs) { // TODO: we may need better comparison as the result is unordered
|
||||||
t.Logf("actual auth configs: %#v", authConfigs)
|
t.Logf("actual auth configs: %#v", authConfigs)
|
||||||
t.Logf("expected auth configs: %#v", testcase.authConfigs)
|
t.Logf("expected auth configs: %#v", testcase.expectedAuthConfigs)
|
||||||
t.Error("auth configs did not match")
|
t.Error("auth configs did not match")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -320,7 +320,7 @@ func TestPullWithSecrets(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for description, test := range tests {
|
for description, test := range tests {
|
||||||
builtInKeyRing := &credentialprovider.BasicDockerKeyring{}
|
builtInKeyRing := &credentialprovider.BasicDockerKeyring{}
|
||||||
builtInKeyRing.Add(test.builtInDockerConfig)
|
builtInKeyRing.Add(nil, test.builtInDockerConfig)
|
||||||
_, fakeImageService, fakeManager, err := customTestRuntimeManager(builtInKeyRing)
|
_, fakeImageService, fakeManager, err := customTestRuntimeManager(builtInKeyRing)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user