Skip to content

Commit 0050a5d

Browse files
committed
auth: add support for token-based authentication with Swift
Previously, authentication with Swift supported application credentials, username/password or the legacy ApiKey. This commit adds support for authenticating using Keystone tokens via the token-based authentication method.
1 parent 85ac017 commit 0050a5d

File tree

2 files changed

+127
-18
lines changed

2 files changed

+127
-18
lines changed

pkg/storage/swift/swift.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ type Swift struct {
4747
ApplicationCredentialID string
4848
ApplicationCredentialName string
4949
ApplicationCredentialSecret string
50+
Token string
5051
}
5152

5253
type driver struct {
@@ -132,6 +133,7 @@ func GetConfig(listers *regopclient.StorageListers) (*Swift, error) {
132133
cfg.ApplicationCredentialID = cloud.AuthInfo.ApplicationCredentialID
133134
cfg.ApplicationCredentialName = cloud.AuthInfo.ApplicationCredentialName
134135
cfg.ApplicationCredentialSecret = cloud.AuthInfo.ApplicationCredentialSecret
136+
cfg.Token = cloud.AuthInfo.Token
135137
cfg.Tenant = cloud.AuthInfo.ProjectName
136138
cfg.TenantID = cloud.AuthInfo.ProjectID
137139
cfg.Domain = cloud.AuthInfo.DomainName
@@ -158,11 +160,13 @@ func GetConfig(listers *regopclient.StorageListers) (*Swift, error) {
158160
cfg.ApplicationCredentialID, _ = util.GetValueFromSecret(sec, "REGISTRY_STORAGE_SWIFT_APPLICATIONCREDENTIALID")
159161
cfg.ApplicationCredentialName, _ = util.GetValueFromSecret(sec, "REGISTRY_STORAGE_SWIFT_APPLICATIONCREDENTIALNAME")
160162
cfg.ApplicationCredentialSecret, _ = util.GetValueFromSecret(sec, "REGISTRY_STORAGE_SWIFT_APPLICATIONCREDENTIALSECRET")
163+
cfg.Token, _ = util.GetValueFromSecret(sec, "REGISTRY_STORAGE_SWIFT_TOKENID")
161164
userPassValid := len(cfg.Username) > 0 && len(cfg.Password) > 0
162165
appCredsValid := len(cfg.ApplicationCredentialID) > 0 && len(cfg.ApplicationCredentialName) > 0 && len(cfg.ApplicationCredentialSecret) > 0
163-
if !userPassValid && !appCredsValid {
166+
tokenValid := len(cfg.Token) > 0
167+
if !userPassValid && !appCredsValid && !tokenValid {
164168
return nil, fmt.Errorf(
165-
"secret %q does not contain required keys 'REGISTRY_STORAGE_SWIFT_USERNAME' and 'REGISTRY_STORAGE_SWIFT_PASSWORD'; or 'REGISTRY_STORAGE_SWIFT_APPLICATIONCREDENTIALID', 'REGISTRY_STORAGE_SWIFT_APPLICATIONCREDENTIALNAME' and 'REGISTRY_STORAGE_SWIFT_APPLICATIONCREDENTIALSECRET'",
169+
"secret %q does not contain required keys 'REGISTRY_STORAGE_SWIFT_USERNAME' and 'REGISTRY_STORAGE_SWIFT_PASSWORD'; or 'REGISTRY_STORAGE_SWIFT_APPLICATIONCREDENTIALID', 'REGISTRY_STORAGE_SWIFT_APPLICATIONCREDENTIALNAME' and 'REGISTRY_STORAGE_SWIFT_APPLICATIONCREDENTIALSECRET'; or 'REGISTRY_STORAGE_SWIFT_TOKENID'",
166170
fmt.Sprintf("%s/%s", sec.Namespace, sec.Name),
167171
)
168172
}
@@ -236,6 +240,7 @@ func (d *driver) getSwiftClient() (*gophercloud.ServiceClient, error) {
236240
ApplicationCredentialID: cfg.ApplicationCredentialID,
237241
ApplicationCredentialName: cfg.ApplicationCredentialName,
238242
ApplicationCredentialSecret: cfg.ApplicationCredentialSecret,
243+
TokenID: cfg.Token,
239244
DomainID: domainID,
240245
DomainName: domain,
241246
TenantID: tenantID,
@@ -351,6 +356,7 @@ func (d *driver) ConfigEnv() (envs envvar.List, err error) {
351356
envvar.EnvVar{Name: "REGISTRY_STORAGE_SWIFT_AUTHURL", Value: authURL},
352357
envvar.EnvVar{Name: "REGISTRY_STORAGE_SWIFT_USERNAME", Value: cfg.Username, Secret: true},
353358
envvar.EnvVar{Name: "REGISTRY_STORAGE_SWIFT_PASSWORD", Value: cfg.Password, Secret: true},
359+
envvar.EnvVar{Name: "REGISTRY_STORAGE_SWIFT_TOKENID", Value: cfg.Token, Secret: true},
354360
envvar.EnvVar{Name: "REGISTRY_STORAGE_SWIFT_APPLICATIONCREDENTIALID", Value: cfg.ApplicationCredentialID, Secret: true},
355361
envvar.EnvVar{Name: "REGISTRY_STORAGE_SWIFT_APPLICATIONCREDENTIALNAME", Value: cfg.ApplicationCredentialName, Secret: true},
356362
envvar.EnvVar{Name: "REGISTRY_STORAGE_SWIFT_APPLICATIONCREDENTIALSECRET", Value: cfg.ApplicationCredentialSecret, Secret: true},

pkg/storage/swift/swift_test.go

Lines changed: 119 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ const (
3434
applicationCredentialID = "myId"
3535
applicationCredentialName = "myName"
3636
applicationCredentialSecret = "mySecret"
37+
TokenID = "myTokenID"
3738
container = "registry"
3839
domain = "Default"
3940
tenant = "openshift-registry"
@@ -58,6 +59,9 @@ var (
5859
"REGISTRY_STORAGE_SWIFT_APPLICATIONCREDENTIALNAME": []byte(applicationCredentialName),
5960
"REGISTRY_STORAGE_SWIFT_APPLICATIONCREDENTIALSECRET": []byte(applicationCredentialSecret),
6061
}
62+
fakeTokenSecretData = map[string][]byte{
63+
"REGISTRY_STORAGE_SWIFT_TOKENID": []byte(TokenID),
64+
}
6165
fakeCloudsYAML map[string][]byte
6266
fakeCloudProviderConfigMap map[string]string
6367
)
@@ -179,6 +183,34 @@ func (m MockConfigMapNamespaceLister) List(selector labels.Selector) ([]*corev1.
179183
}, nil
180184
}
181185

186+
type MockUPITokenSecretNamespaceLister struct{}
187+
188+
func (m MockUPITokenSecretNamespaceLister) Get(name string) (*corev1.Secret, error) {
189+
if name == upiSecretName {
190+
return &corev1.Secret{
191+
Data: fakeTokenSecretData,
192+
}, nil
193+
}
194+
195+
return nil, &k8serrors.StatusError{
196+
ErrStatus: metav1.Status{
197+
Status: metav1.StatusFailure,
198+
Code: http.StatusNotFound,
199+
Reason: metav1.StatusReasonNotFound,
200+
Details: &metav1.StatusDetails{},
201+
Message: fmt.Sprintf("No secret with name %v was found", name),
202+
},
203+
}
204+
}
205+
206+
func (m MockUPITokenSecretNamespaceLister) List(selector labels.Selector) ([]*corev1.Secret, error) {
207+
return []*corev1.Secret{
208+
{
209+
Data: fakeTokenSecretData,
210+
},
211+
}, nil
212+
}
213+
182214
func handleAuthentication(t *testing.T, endpointType string) {
183215
th.Mux.HandleFunc("/v3/auth/tokens", func(w http.ResponseWriter, r *http.Request) {
184216
th.TestMethod(t, r, "POST")
@@ -593,9 +625,10 @@ func TestSwiftSecretsAppCreds(t *testing.T) {
593625
th.AssertNoErr(t, err)
594626
res, err := configenv.SecretData()
595627
th.AssertNoErr(t, err)
596-
th.AssertEquals(t, 5, len(res))
628+
th.AssertEquals(t, 6, len(res))
597629
th.AssertEquals(t, `""`, res["REGISTRY_STORAGE_SWIFT_USERNAME"])
598630
th.AssertEquals(t, `""`, res["REGISTRY_STORAGE_SWIFT_PASSWORD"])
631+
th.AssertEquals(t, `""`, res["REGISTRY_STORAGE_SWIFT_TOKENID"])
599632
th.AssertEquals(t, applicationCredentialID, res["REGISTRY_STORAGE_SWIFT_APPLICATIONCREDENTIALID"])
600633
th.AssertEquals(t, applicationCredentialName, res["REGISTRY_STORAGE_SWIFT_APPLICATIONCREDENTIALNAME"])
601634
th.AssertEquals(t, applicationCredentialSecret, res["REGISTRY_STORAGE_SWIFT_APPLICATIONCREDENTIALSECRET"])
@@ -631,9 +664,10 @@ func TestSwiftSecretsAppCreds(t *testing.T) {
631664
th.AssertNoErr(t, err)
632665
res, err = configenv.SecretData()
633666
th.AssertNoErr(t, err)
634-
th.AssertEquals(t, 5, len(res))
667+
th.AssertEquals(t, 6, len(res))
635668
th.AssertEquals(t, `""`, res["REGISTRY_STORAGE_SWIFT_USERNAME"])
636669
th.AssertEquals(t, `""`, res["REGISTRY_STORAGE_SWIFT_PASSWORD"])
670+
th.AssertEquals(t, `""`, res["REGISTRY_STORAGE_SWIFT_TOKENID"])
637671
th.AssertEquals(t, applicationCredentialID, res["REGISTRY_STORAGE_SWIFT_APPLICATIONCREDENTIALID"])
638672
th.AssertEquals(t, applicationCredentialName, res["REGISTRY_STORAGE_SWIFT_APPLICATIONCREDENTIALNAME"])
639673
th.AssertEquals(t, applicationCredentialSecret, res["REGISTRY_STORAGE_SWIFT_APPLICATIONCREDENTIALSECRET"])
@@ -658,9 +692,10 @@ func TestSwiftSecretsUserPass(t *testing.T) {
658692
th.AssertNoErr(t, err)
659693
res, err := configenv.SecretData()
660694
th.AssertNoErr(t, err)
661-
th.AssertEquals(t, 5, len(res))
695+
th.AssertEquals(t, 6, len(res))
662696
th.AssertEquals(t, username, res["REGISTRY_STORAGE_SWIFT_USERNAME"])
663697
th.AssertEquals(t, password, res["REGISTRY_STORAGE_SWIFT_PASSWORD"])
698+
th.AssertEquals(t, `""`, res["REGISTRY_STORAGE_SWIFT_TOKENID"])
664699
th.AssertEquals(t, `""`, res["REGISTRY_STORAGE_SWIFT_APPLICATIONCREDENTIALID"])
665700
th.AssertEquals(t, `""`, res["REGISTRY_STORAGE_SWIFT_APPLICATIONCREDENTIALNAME"])
666701
th.AssertEquals(t, `""`, res["REGISTRY_STORAGE_SWIFT_APPLICATIONCREDENTIALSECRET"])
@@ -695,9 +730,76 @@ func TestSwiftSecretsUserPass(t *testing.T) {
695730
th.AssertNoErr(t, err)
696731
res, err = configenv.SecretData()
697732
th.AssertNoErr(t, err)
698-
th.AssertEquals(t, 5, len(res))
733+
th.AssertEquals(t, 6, len(res))
699734
th.AssertEquals(t, username, res["REGISTRY_STORAGE_SWIFT_USERNAME"])
700735
th.AssertEquals(t, password, res["REGISTRY_STORAGE_SWIFT_PASSWORD"])
736+
th.AssertEquals(t, `""`, res["REGISTRY_STORAGE_SWIFT_TOKENID"])
737+
th.AssertEquals(t, `""`, res["REGISTRY_STORAGE_SWIFT_APPLICATIONCREDENTIALID"])
738+
th.AssertEquals(t, `""`, res["REGISTRY_STORAGE_SWIFT_APPLICATIONCREDENTIALNAME"])
739+
th.AssertEquals(t, `""`, res["REGISTRY_STORAGE_SWIFT_APPLICATIONCREDENTIALSECRET"])
740+
}
741+
742+
func TestSwiftSecretsToken(t *testing.T) {
743+
config := imageregistryv1.ImageRegistryConfigStorageSwift{
744+
AuthURL: "http://localhost:5000/v3",
745+
Container: container,
746+
Domain: domain,
747+
Tenant: tenant,
748+
}
749+
d := driver{
750+
Listers: &regopclient.StorageListers{
751+
Secrets: MockUPITokenSecretNamespaceLister{},
752+
Infrastructures: fakeInfrastructureLister(cloudName),
753+
OpenShiftConfig: MockConfigMapNamespaceLister{},
754+
},
755+
Config: &config,
756+
}
757+
configenv, err := d.ConfigEnv()
758+
th.AssertNoErr(t, err)
759+
res, err := configenv.SecretData()
760+
fmt.Println(res)
761+
th.AssertNoErr(t, err)
762+
th.AssertEquals(t, 6, len(res))
763+
th.AssertEquals(t, `""`, res["REGISTRY_STORAGE_SWIFT_USERNAME"])
764+
th.AssertEquals(t, `""`, res["REGISTRY_STORAGE_SWIFT_PASSWORD"])
765+
th.AssertEquals(t, TokenID, res["REGISTRY_STORAGE_SWIFT_TOKENID"])
766+
th.AssertEquals(t, `""`, res["REGISTRY_STORAGE_SWIFT_APPLICATIONCREDENTIALID"])
767+
th.AssertEquals(t, `""`, res["REGISTRY_STORAGE_SWIFT_APPLICATIONCREDENTIALNAME"])
768+
th.AssertEquals(t, `""`, res["REGISTRY_STORAGE_SWIFT_APPLICATIONCREDENTIALSECRET"])
769+
770+
config = imageregistryv1.ImageRegistryConfigStorageSwift{
771+
Container: container,
772+
}
773+
// Support any cloud name provided by platform status
774+
customCloud := "myCloud"
775+
d = driver{
776+
Listers: &regopclient.StorageListers{
777+
Secrets: MockIPISecretNamespaceLister{},
778+
Infrastructures: fakeInfrastructureLister(customCloud),
779+
OpenShiftConfig: MockConfigMapNamespaceLister{},
780+
},
781+
Config: &config,
782+
}
783+
fakeCloudsYAMLData := []byte(`clouds:
784+
` + customCloud + `:
785+
auth:
786+
auth_url: "http://localhost:5000/v3"
787+
project_name: ` + tenant + `
788+
token: ` + TokenID + `
789+
domain_name: ` + domain + `
790+
region_name: RegionOne`)
791+
792+
fakeCloudsYAML = map[string][]byte{
793+
cloudSecretKey: fakeCloudsYAMLData,
794+
}
795+
configenv, err = d.ConfigEnv()
796+
th.AssertNoErr(t, err)
797+
res, err = configenv.SecretData()
798+
th.AssertNoErr(t, err)
799+
th.AssertEquals(t, 6, len(res))
800+
th.AssertEquals(t, `""`, res["REGISTRY_STORAGE_SWIFT_USERNAME"])
801+
th.AssertEquals(t, `""`, res["REGISTRY_STORAGE_SWIFT_PASSWORD"])
802+
th.AssertEquals(t, TokenID, res["REGISTRY_STORAGE_SWIFT_TOKENID"])
701803
th.AssertEquals(t, `""`, res["REGISTRY_STORAGE_SWIFT_APPLICATIONCREDENTIALID"])
702804
th.AssertEquals(t, `""`, res["REGISTRY_STORAGE_SWIFT_APPLICATIONCREDENTIALNAME"])
703805
th.AssertEquals(t, `""`, res["REGISTRY_STORAGE_SWIFT_APPLICATIONCREDENTIALSECRET"])
@@ -853,7 +955,6 @@ func TestSwiftConfigEnvCloudConfig(t *testing.T) {
853955
d, _ := mockConfig(false, "http://localhost:5000/v3", MockIPISecretNamespaceLister{}, false)
854956

855957
res, err := d.ConfigEnv()
856-
857958
th.AssertNoErr(t, err)
858959
th.AssertEquals(t, "REGISTRY_STORAGE", res[0].Name)
859960
th.AssertEquals(t, "swift", res[0].Value)
@@ -865,20 +966,22 @@ func TestSwiftConfigEnvCloudConfig(t *testing.T) {
865966
th.AssertEquals(t, true, res[3].Secret)
866967
th.AssertEquals(t, "REGISTRY_STORAGE_SWIFT_PASSWORD", res[4].Name)
867968
th.AssertEquals(t, true, res[4].Secret)
868-
th.AssertEquals(t, "REGISTRY_STORAGE_SWIFT_APPLICATIONCREDENTIALID", res[5].Name)
969+
th.AssertEquals(t, "REGISTRY_STORAGE_SWIFT_TOKENID", res[5].Name)
869970
th.AssertEquals(t, true, res[5].Secret)
870-
th.AssertEquals(t, "REGISTRY_STORAGE_SWIFT_APPLICATIONCREDENTIALNAME", res[6].Name)
971+
th.AssertEquals(t, "REGISTRY_STORAGE_SWIFT_APPLICATIONCREDENTIALID", res[6].Name)
871972
th.AssertEquals(t, true, res[6].Secret)
872-
th.AssertEquals(t, "REGISTRY_STORAGE_SWIFT_APPLICATIONCREDENTIALSECRET", res[7].Name)
973+
th.AssertEquals(t, "REGISTRY_STORAGE_SWIFT_APPLICATIONCREDENTIALNAME", res[7].Name)
873974
th.AssertEquals(t, true, res[7].Secret)
874-
th.AssertEquals(t, "REGISTRY_STORAGE_SWIFT_AUTHVERSION", res[8].Name)
875-
th.AssertEquals(t, 3, res[8].Value)
876-
th.AssertEquals(t, "REGISTRY_STORAGE_SWIFT_DOMAIN", res[9].Name)
877-
th.AssertEquals(t, domain, res[9].Value)
878-
th.AssertEquals(t, "REGISTRY_STORAGE_SWIFT_TENANT", res[10].Name)
879-
th.AssertEquals(t, tenant, res[10].Value)
880-
th.AssertEquals(t, "REGISTRY_STORAGE_SWIFT_REGION", res[11].Name)
881-
th.AssertEquals(t, "RegionOne", res[11].Value)
975+
th.AssertEquals(t, "REGISTRY_STORAGE_SWIFT_APPLICATIONCREDENTIALSECRET", res[8].Name)
976+
th.AssertEquals(t, true, res[8].Secret)
977+
th.AssertEquals(t, "REGISTRY_STORAGE_SWIFT_AUTHVERSION", res[9].Name)
978+
th.AssertEquals(t, 3, res[9].Value)
979+
th.AssertEquals(t, "REGISTRY_STORAGE_SWIFT_DOMAIN", res[10].Name)
980+
th.AssertEquals(t, domain, res[10].Value)
981+
th.AssertEquals(t, "REGISTRY_STORAGE_SWIFT_TENANT", res[11].Name)
982+
th.AssertEquals(t, tenant, res[11].Value)
983+
th.AssertEquals(t, "REGISTRY_STORAGE_SWIFT_REGION", res[12].Name)
984+
th.AssertEquals(t, "RegionOne", res[12].Value)
882985
}
883986

884987
func TestSwiftEnsureAuthURLHasAPIVersion(t *testing.T) {

0 commit comments

Comments
 (0)