From eb3385be580bf29c7319ffb2ee5d36016735719c Mon Sep 17 00:00:00 2001 From: jackgr Date: Sun, 20 Mar 2016 19:25:03 -0700 Subject: [PATCH] Add file based credential provider --- pkg/repo/filebased_credential_provider.go | 82 +++++++++++++++++++ .../filebased_credential_provider_test.go | 57 +++++++++++++ pkg/repo/testdata/test_credentials_file.yaml | 6 ++ 3 files changed, 145 insertions(+) create mode 100644 pkg/repo/filebased_credential_provider.go create mode 100644 pkg/repo/filebased_credential_provider_test.go create mode 100644 pkg/repo/testdata/test_credentials_file.yaml diff --git a/pkg/repo/filebased_credential_provider.go b/pkg/repo/filebased_credential_provider.go new file mode 100644 index 000000000..834511d1a --- /dev/null +++ b/pkg/repo/filebased_credential_provider.go @@ -0,0 +1,82 @@ +/* +Copyright 2015 The Kubernetes Authors All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package repo + +import ( + "github.com/ghodss/yaml" + + "fmt" + "io/ioutil" + "log" +) + +// FilebasedCredentialProvider provides credentials for registries. +type FilebasedCredentialProvider struct { + // Actual backing store + backingCredentialProvider CredentialProvider +} + +// NamedRepoCredential associates a name with a RepoCredential. +type NamedRepoCredential struct { + Name string `json:"name,omitempty"` + RepoCredential +} + +// NewFilebasedCredentialProvider creates a file based credential provider. +func NewFilebasedCredentialProvider(filename string) (CredentialProvider, error) { + icp := NewInmemCredentialProvider() + log.Printf("Using credentials file %s", filename) + c, err := readCredentialsFile(filename) + if err != nil { + return nil, err + } + + for _, nc := range c { + log.Printf("Loading credential named %s", nc.Name) + icp.SetCredential(nc.Name, &nc.RepoCredential) + } + + return &FilebasedCredentialProvider{icp}, nil +} + +func readCredentialsFile(filename string) ([]NamedRepoCredential, error) { + bytes, err := ioutil.ReadFile(filename) + if err != nil { + return nil, err + } + + return parseCredentials(bytes) +} + +func parseCredentials(bytes []byte) ([]NamedRepoCredential, error) { + r := []NamedRepoCredential{} + if err := yaml.Unmarshal(bytes, &r); err != nil { + return nil, fmt.Errorf("cannot unmarshal credentials file (%#v)", err) + } + + return r, nil +} + +// GetCredential returns a credential by name. +func (fcp *FilebasedCredentialProvider) GetCredential(name string) (*RepoCredential, error) { + return fcp.backingCredentialProvider.GetCredential(name) +} + +// SetCredential sets a credential by name. +func (fcp *FilebasedCredentialProvider) SetCredential(name string, credential *RepoCredential) error { + return fmt.Errorf("SetCredential operation not supported with FilebasedCredentialProvider") +} diff --git a/pkg/repo/filebased_credential_provider_test.go b/pkg/repo/filebased_credential_provider_test.go new file mode 100644 index 000000000..e10347b20 --- /dev/null +++ b/pkg/repo/filebased_credential_provider_test.go @@ -0,0 +1,57 @@ +/* +Copyright 2015 The Kubernetes Authors All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package repo + +import ( + "testing" +) + +var filename = "./testdata/test_credentials_file.yaml" + +type filebasedTestCase struct { + name string + exp *RepoCredential + expErr error +} + +func TestNotExistFilebased(t *testing.T) { + cp := getProvider(t) + tc := &testCase{"nonexistent", nil, createMissingError("nonexistent")} + testGetCredential(t, cp, tc) +} + +func TestGetApiTokenFilebased(t *testing.T) { + cp := getProvider(t) + tc := &testCase{"test1", &RepoCredential{APIToken: "token"}, nil} + testGetCredential(t, cp, tc) +} + +func TestSetAndGetBasicAuthFilebased(t *testing.T) { + cp := getProvider(t) + ba := BasicAuthCredential{Username: "user", Password: "password"} + tc := &testCase{"test2", &RepoCredential{BasicAuth: ba}, nil} + testGetCredential(t, cp, tc) +} + +func getProvider(t *testing.T) CredentialProvider { + cp, err := NewFilebasedCredentialProvider(filename) + if err != nil { + t.Fatalf("cannot create a new provider from file %s: %s", filename, err) + } + + return cp +} diff --git a/pkg/repo/testdata/test_credentials_file.yaml b/pkg/repo/testdata/test_credentials_file.yaml new file mode 100644 index 000000000..8ada52807 --- /dev/null +++ b/pkg/repo/testdata/test_credentials_file.yaml @@ -0,0 +1,6 @@ +- name: test1 + apitoken: token +- name: test2 + basicauth: + username: user + password: password