diff --git a/pkg/credentials/common/constants.go b/pkg/credentials/common/constants.go new file mode 100644 index 00000000000..69f31c79018 --- /dev/null +++ b/pkg/credentials/common/constants.go @@ -0,0 +1,19 @@ +package common + +// Secret key constants used in credential files, +// so as to avoid reliance on corev1.Secret. +const ( + BasicAuthUsernameKey = "username" + BasicAuthPasswordKey = "password" + SSHAuthPrivateKey = "ssh-privatekey" + DockerConfigKey = ".dockercfg" + DockerConfigJsonKey = ".dockerconfigjson" + SecretTypeBasicAuth = "kubernetes.io/basic-auth" + SecretTypeSSHAuth = "kubernetes.io/ssh-auth" + SecretTypeDockerConfigJson = "kubernetes.io/dockerconfigjson" + SecretTypeDockercfg = "kubernetes.io/dockercfg" + SecretTypeServiceAccountToken = "kubernetes.io/service-account-token" + SecretTypeOpaque = "kubernetes.io/opaque" + SecretTypeTLS = "kubernetes.io/tls" + SecretTypeBootstrapToken = "kubernetes.io/bootstrap-token" +) diff --git a/pkg/credentials/dockercreds/creds.go b/pkg/credentials/dockercreds/creds.go index 5b7a6b9ec30..f7d535109a0 100644 --- a/pkg/credentials/dockercreds/creds.go +++ b/pkg/credentials/dockercreds/creds.go @@ -25,9 +25,9 @@ import ( "path/filepath" "strings" + "github.com/tektoncd/pipeline/pkg/credentials/common" credmatcher "github.com/tektoncd/pipeline/pkg/credentials/matcher" credwriter "github.com/tektoncd/pipeline/pkg/credentials/writer" - corev1 "k8s.io/api/core/v1" ) const annotationPrefix = "tekton.dev/docker-" @@ -120,13 +120,13 @@ type entry struct { func newEntry(secret string) (*entry, error) { secretPath := credmatcher.VolumeName(secret) - ub, err := os.ReadFile(filepath.Join(secretPath, corev1.BasicAuthUsernameKey)) + ub, err := os.ReadFile(filepath.Join(secretPath, common.BasicAuthUsernameKey)) if err != nil { return nil, err } username := string(ub) - pb, err := os.ReadFile(filepath.Join(secretPath, corev1.BasicAuthPasswordKey)) + pb, err := os.ReadFile(filepath.Join(secretPath, common.BasicAuthPasswordKey)) if err != nil { return nil, err } @@ -154,20 +154,20 @@ func NewBuilder() interface { // MatchingAnnotations extracts flags for the credential helper // from the supplied secret and returns a slice (of length 0 or // greater) of applicable domains. -func (*basicDockerBuilder) MatchingAnnotations(secret *corev1.Secret) []string { +func (*basicDockerBuilder) MatchingAnnotations(secret credmatcher.Secret) []string { var flags []string - switch secret.Type { - case corev1.SecretTypeBasicAuth: - for _, v := range credwriter.SortAnnotations(secret.Annotations, annotationPrefix) { - flags = append(flags, fmt.Sprintf("-basic-docker=%s=%s", secret.Name, v)) + switch credmatcher.GetSecretType(secret) { + case common.SecretTypeBasicAuth: + for _, v := range credwriter.SortAnnotations(secret.GetAnnotations(), annotationPrefix) { + flags = append(flags, fmt.Sprintf("-basic-docker=%s=%s", secret.GetName(), v)) } - case corev1.SecretTypeDockerConfigJson: - flags = append(flags, "-docker-config="+secret.Name) - case corev1.SecretTypeDockercfg: - flags = append(flags, "-docker-cfg="+secret.Name) + case common.SecretTypeDockerConfigJson: + flags = append(flags, "-docker-config="+secret.GetName()) + case common.SecretTypeDockercfg: + flags = append(flags, "-docker-cfg="+secret.GetName()) - case corev1.SecretTypeOpaque, corev1.SecretTypeServiceAccountToken, corev1.SecretTypeSSHAuth, corev1.SecretTypeTLS, corev1.SecretTypeBootstrapToken: - return flags + case common.SecretTypeOpaque, common.SecretTypeServiceAccountToken, common.SecretTypeSSHAuth, common.SecretTypeTLS, common.SecretTypeBootstrapToken: + fallthrough default: return flags @@ -226,7 +226,7 @@ func (*basicDockerBuilder) Write(directory string) error { func authsFromDockerCfg(secret string) (map[string]entry, error) { secretPath := credmatcher.VolumeName(secret) m := make(map[string]entry) - data, err := os.ReadFile(filepath.Join(secretPath, corev1.DockerConfigKey)) + data, err := os.ReadFile(filepath.Join(secretPath, common.DockerConfigKey)) if err != nil { return m, err } @@ -238,7 +238,7 @@ func authsFromDockerConfig(secret string) (map[string]entry, error) { secretPath := credmatcher.VolumeName(secret) m := make(map[string]entry) c := configFile{} - data, err := os.ReadFile(filepath.Join(secretPath, corev1.DockerConfigJsonKey)) + data, err := os.ReadFile(filepath.Join(secretPath, common.DockerConfigJsonKey)) if err != nil { return m, err } diff --git a/pkg/credentials/gitcreds/basic.go b/pkg/credentials/gitcreds/basic.go index 746c7b02eab..7c56d137633 100644 --- a/pkg/credentials/gitcreds/basic.go +++ b/pkg/credentials/gitcreds/basic.go @@ -23,8 +23,8 @@ import ( "path/filepath" "strings" + "github.com/tektoncd/pipeline/pkg/credentials/common" credmatcher "github.com/tektoncd/pipeline/pkg/credentials/matcher" - corev1 "k8s.io/api/core/v1" ) // As the flag is read, this status is populated. @@ -123,13 +123,13 @@ func (be *basicEntry) escapedUsername() string { func newBasicEntry(u, secret string) (*basicEntry, error) { secretPath := credmatcher.VolumeName(secret) - ub, err := os.ReadFile(filepath.Join(secretPath, corev1.BasicAuthUsernameKey)) + ub, err := os.ReadFile(filepath.Join(secretPath, common.BasicAuthUsernameKey)) if err != nil { return nil, err } username := string(ub) - pb, err := os.ReadFile(filepath.Join(secretPath, corev1.BasicAuthPasswordKey)) + pb, err := os.ReadFile(filepath.Join(secretPath, common.BasicAuthPasswordKey)) if err != nil { return nil, err } diff --git a/pkg/credentials/gitcreds/creds.go b/pkg/credentials/gitcreds/creds.go index 6f1ceb4b44f..13c9bd109f4 100644 --- a/pkg/credentials/gitcreds/creds.go +++ b/pkg/credentials/gitcreds/creds.go @@ -19,10 +19,9 @@ package gitcreds import ( "flag" "fmt" - + "github.com/tektoncd/pipeline/pkg/credentials/common" credmatcher "github.com/tektoncd/pipeline/pkg/credentials/matcher" credwriter "github.com/tektoncd/pipeline/pkg/credentials/writer" - corev1 "k8s.io/api/core/v1" ) const ( @@ -42,10 +41,15 @@ func AddFlags(flagSet *flag.FlagSet) { } func flags(fs *flag.FlagSet) { - basicConfig = basicGitConfig{entries: make(map[string]basicEntry)} + basicConfig = basicGitConfig{ + entries: make(map[string]basicEntry), + order: []string{}, + } + sshConfig = sshGitConfig{ + entries: make(map[string][]sshEntry), + order: []string{}, + } fs.Var(&basicConfig, basicAuthFlag, "List of secret=url pairs.") - - sshConfig = sshGitConfig{entries: make(map[string][]sshEntry)} fs.Var(&sshConfig, sshFlag, "List of secret=url pairs.") } @@ -62,28 +66,28 @@ func NewBuilder() interface { // MatchingAnnotations extracts flags for the credential helper // from the supplied secret and returns a slice (of length 0 or // greater) of applicable domains. -func (*gitBuilder) MatchingAnnotations(secret *corev1.Secret) []string { +func (*gitBuilder) MatchingAnnotations(secret credmatcher.Secret) []string { + var flagName string var flags []string - switch secret.Type { - case corev1.SecretTypeBasicAuth: - for _, v := range credwriter.SortAnnotations(secret.Annotations, annotationPrefix) { - flags = append(flags, fmt.Sprintf("-%s=%s=%s", basicAuthFlag, secret.Name, v)) - } - - case corev1.SecretTypeSSHAuth: - for _, v := range credwriter.SortAnnotations(secret.Annotations, annotationPrefix) { - flags = append(flags, fmt.Sprintf("-%s=%s=%s", sshFlag, secret.Name, v)) - } - - case corev1.SecretTypeOpaque, corev1.SecretTypeServiceAccountToken, corev1.SecretTypeDockercfg, corev1.SecretTypeDockerConfigJson, corev1.SecretTypeTLS, corev1.SecretTypeBootstrapToken: - return flags - + switch credmatcher.GetSecretType(secret) { + case common.SecretTypeBasicAuth: + flagName = basicAuthFlag + case common.SecretTypeSSHAuth: + flagName = sshFlag + case common.SecretTypeOpaque, common.SecretTypeServiceAccountToken, common.SecretTypeDockercfg, common.SecretTypeDockerConfigJson, common.SecretTypeTLS, common.SecretTypeBootstrapToken: + fallthrough default: return flags } + + for _, v := range credwriter.SortAnnotations(secret.GetAnnotations(), annotationPrefix) { + flags = append(flags, fmt.Sprintf("-%s=%s=%s", flagName, secret.GetName(), v)) + } + return flags } +// Write writes the credentials to the provided directory. func (*gitBuilder) Write(directory string) error { if err := basicConfig.Write(directory); err != nil { return err diff --git a/pkg/credentials/gitcreds/ssh.go b/pkg/credentials/gitcreds/ssh.go index 95cc8802654..01a1b758cbf 100644 --- a/pkg/credentials/gitcreds/ssh.go +++ b/pkg/credentials/gitcreds/ssh.go @@ -23,8 +23,8 @@ import ( "path/filepath" "strings" + "github.com/tektoncd/pipeline/pkg/credentials/common" credmatcher "github.com/tektoncd/pipeline/pkg/credentials/matcher" - corev1 "k8s.io/api/core/v1" ) const sshKnownHosts = "known_hosts" @@ -142,7 +142,7 @@ func (be *sshEntry) Write(sshDir string) error { func newSSHEntry(url, secretName string) (*sshEntry, error) { secretPath := credmatcher.VolumeName(secretName) - pk, err := os.ReadFile(filepath.Join(secretPath, corev1.SSHAuthPrivateKey)) + pk, err := os.ReadFile(filepath.Join(secretPath, common.SSHAuthPrivateKey)) if err != nil { return nil, err } diff --git a/pkg/credentials/matcher/matcher.go b/pkg/credentials/matcher/matcher.go index ae319b164ca..94cad31015d 100644 --- a/pkg/credentials/matcher/matcher.go +++ b/pkg/credentials/matcher/matcher.go @@ -18,23 +18,43 @@ package matcher import ( "fmt" - - corev1 "k8s.io/api/core/v1" + "reflect" ) // VolumePath is the path where build secrets are written. // It is mutable and exported for testing. var VolumePath = "/tekton/creds-secrets" +// Secret is the minimal interface needed for credential matching +type Secret interface { + GetName() string + GetAnnotations() map[string]string +} + // Matcher is the interface for a credential initializer of any type. type Matcher interface { // MatchingAnnotations extracts flags for the credential // helper from the supplied secret and returns a slice (of // length 0 or greater) of applicable domains. - MatchingAnnotations(secret *corev1.Secret) []string + MatchingAnnotations(secret Secret) []string } // VolumeName returns the full path to the secret, inside the VolumePath. func VolumeName(secretName string) string { return fmt.Sprintf("%s/%s", VolumePath, secretName) } + +// GetSecretType returns secret type from secret interface using reflection +func GetSecretType(secret Secret) string { + v := reflect.ValueOf(secret) + // If it's a pointer, unwrap it + if v.Kind() == reflect.Ptr { + v = v.Elem() + } + // Grab the field by name + f := v.FieldByName("Type") + if !f.IsValid() || !f.CanInterface() { + return "" + } + return fmt.Sprintf("%v", f.Interface()) +}