-
Notifications
You must be signed in to change notification settings - Fork 329
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #109 from opensds/development
Merge development to master branch to publish Capri Milestone-2
- Loading branch information
Showing
69 changed files
with
2,831 additions
and
365 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -60,4 +60,3 @@ func FilterFactory() restful.FilterFunction { | |
} | ||
return auth.Filter | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
// Copyright (c) 2019 Huawei Technologies Co., Ltd. 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 credentials | ||
|
||
import ( | ||
"sync" | ||
) | ||
|
||
// A Value is the OpenSDS multi-cloud credentials value. | ||
type Value struct { | ||
// OpenSDS multi-cloud Access key ID | ||
AccessKeyID string | ||
|
||
// OpenSDS multi-cloud Secret Access Key | ||
SecretAccessKey string | ||
|
||
// Provider used to get credentials | ||
ProviderName string | ||
} | ||
|
||
// A Provider is the interface to provide credentials Value. | ||
type Provider interface { | ||
// Retrieve returns credential value if it successfully retrieved the value, | ||
// otherwise returns Error. | ||
Retrieve() (Value, error) | ||
} | ||
|
||
// An ErrorProvider is a credentials provider that always returns an error | ||
type ErrorProvider struct { | ||
// The error to be returned from Retrieve | ||
Err error | ||
|
||
// The provider name to set on the Retrieved returned Value | ||
ProviderName string | ||
} | ||
|
||
// Retrieve will always return the error that the ErrorProvider was created with. | ||
func (p ErrorProvider) Retrieve() (Value, error) { | ||
return Value{ProviderName: p.ProviderName}, p.Err | ||
} | ||
|
||
// A Credentials provides concurrency safe retrieval of OpenSDS multi-cloud credentials Value. | ||
type Credentials struct { | ||
credentials Value | ||
|
||
m sync.RWMutex | ||
|
||
provider Provider | ||
} | ||
|
||
// NewCredentials returns a pointer to a new Credentials with the provider set. | ||
func NewCredentials(provider Provider) *Credentials { | ||
return &Credentials{ | ||
provider: provider, | ||
} | ||
} | ||
|
||
// Get returns the credentials value, or error on failed retrieval | ||
func (c *Credentials) Get() (Value, error) { | ||
|
||
c.m.RLock() | ||
credentials, err := c.provider.Retrieve() | ||
if err != nil { | ||
return Value{}, err | ||
} | ||
c.credentials = credentials | ||
c.m.RUnlock() | ||
|
||
return c.credentials, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
// Copyright (c) 2019 Huawei Technologies Co., Ltd. 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 credentials | ||
|
||
import ( | ||
"testing" | ||
) | ||
|
||
type mockProvider struct { | ||
credentials Value | ||
err error | ||
} | ||
|
||
func (m *mockProvider) Retrieve() (Value, error) { | ||
m.credentials.ProviderName = "mockProvider" | ||
return m.credentials, m.err | ||
} | ||
|
||
func TestCredentialsGet(t *testing.T) { | ||
c := NewCredentials(&mockProvider{ | ||
credentials: Value{ | ||
AccessKeyID: "access_key", | ||
SecretAccessKey: "secret_key", | ||
}, | ||
}) | ||
|
||
creds, err := c.Get() | ||
if err != nil { | ||
t.Errorf("Expected no error, got %v", err) | ||
} | ||
if e, a := "access_key", creds.AccessKeyID; e != a { | ||
t.Errorf("Expect access key ID to match, %v got %v", e, a) | ||
} | ||
if e, a := "secret_key", creds.SecretAccessKey; e != a { | ||
t.Errorf("Expect secret access key to match, %v got %v", e, a) | ||
} | ||
} | ||
|
||
func TestCredentialsGetWithProviderName(t *testing.T) { | ||
mock := &mockProvider{} | ||
|
||
c := NewCredentials(mock) | ||
|
||
credentials, err := c.Get() | ||
if err != nil { | ||
t.Errorf("Expected no error, got %v", err) | ||
} | ||
if e, a := credentials.ProviderName, "mockProvider"; e != a { | ||
t.Errorf("Expected provider name to match, %v got %v", e, a) | ||
} | ||
} | ||
|
||
func TestCredentialsGetWithError(t *testing.T) { | ||
mock := &mockProvider{} | ||
|
||
c := NewCredentials(mock) | ||
|
||
credentials, err := c.Get() | ||
if err != nil { | ||
t.Errorf("Expected no error, got %v", err) | ||
} | ||
if e, a := credentials.ProviderName, "mockProvider"; e != a { | ||
t.Errorf("Expected provider name to match, %v got %v", e, a) | ||
} | ||
} |
134 changes: 134 additions & 0 deletions
134
api/pkg/filters/signature/credentials/keystonecredentials/provider.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
// Copyright (c) 2019 Huawei Technologies Co., Ltd. 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 keystonecredentials provides support for retrieving credentials from keystone | ||
|
||
package keystonecredentials | ||
|
||
import ( | ||
"encoding/json" | ||
"strings" | ||
|
||
log "github.com/golang/glog" | ||
"github.com/gophercloud/gophercloud" | ||
creds "github.com/gophercloud/gophercloud/openstack/identity/v3/credentials" | ||
"github.com/opensds/multi-cloud/api/pkg/filters/auth" | ||
"github.com/opensds/multi-cloud/api/pkg/filters/signature/credentials" | ||
"github.com/opensds/multi-cloud/api/pkg/model" | ||
) | ||
|
||
// ProviderName is the name of the credentials provider. | ||
const ProviderName = `KeystoneProvider` | ||
|
||
// KeystoneProvider is a client to retrieve credentials from Keystone. | ||
type KeystoneProvider struct { | ||
// Requires a gopher cloud Client to make HTTP requests to the Keystone with. | ||
Identity *gophercloud.ServiceClient | ||
|
||
// Requires an AccessKeyID to filter the credentials request. | ||
AccessKeyID string | ||
} | ||
|
||
type Blob struct { | ||
Access string `json:"access"` | ||
Secret string `json:"secret"` | ||
} | ||
|
||
// NewProviderClient returns a credentials Provider for retrieving credentials | ||
func NewProviderClient(accessKeyID string, options ...func(*KeystoneProvider)) credentials.Provider { | ||
|
||
k := &auth.Keystone{} | ||
if err := k.SetUp(); err != nil { | ||
// If auth set up failed, raise panic. | ||
panic(err) | ||
} | ||
|
||
kp := &KeystoneProvider{ | ||
AccessKeyID: accessKeyID, | ||
} | ||
kp.Identity = auth.GetIdentity(k) | ||
|
||
log.V(4).Infof("Service Token Info: %s", kp.Identity.TokenID) | ||
|
||
return kp | ||
} | ||
|
||
// NewCredentialsClient returns a Credentials wrapper for retrieving credentials | ||
func NewCredentialsClient(accessKeyID string, options ...func(*KeystoneProvider)) *credentials.Credentials { | ||
return credentials.NewCredentials(NewProviderClient(accessKeyID,options...)) | ||
} | ||
|
||
|
||
// Retrieve will attempt to request the credentials from the Keystone | ||
// And error will be returned if the retrieval fails. | ||
func (p *KeystoneProvider) Retrieve() (credentials.Value, error) { | ||
resp, err := p.getCredentials(p.AccessKeyID) | ||
if err != nil { | ||
return credentials.Value{ProviderName: ProviderName}, err | ||
} | ||
|
||
return credentials.Value{ | ||
AccessKeyID: resp.AccessKeyID, | ||
SecretAccessKey: resp.SecretAccessKey, | ||
ProviderName: ProviderName, | ||
}, nil | ||
} | ||
|
||
type getCredentialsOutput struct { | ||
AccessKeyID string | ||
SecretAccessKey string | ||
} | ||
|
||
// Returns AccessKey and SecretKey Values, Retrieves Credentials | ||
// from Keystone And error will be returned if the retrieval fails. | ||
func (p *KeystoneProvider) getCredentials(accessKeyID string) (*getCredentialsOutput, error) { | ||
|
||
allPages, err := creds.List(p.Identity, nil).AllPages() | ||
|
||
credentials, err := creds.ExtractCredentials(allPages) | ||
log.V(4).Infof("Credentials: %s", credentials) | ||
|
||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
blob, err := getBlob(credentials, accessKeyID) | ||
|
||
if blob != nil{ | ||
return &getCredentialsOutput{ | ||
AccessKeyID: blob.Access, | ||
SecretAccessKey: blob.Secret, | ||
}, nil | ||
} | ||
return nil, err | ||
} | ||
|
||
// Returns a credential Blob for getting access and secret | ||
// And error will be returned if it fails. | ||
func getBlob(credentials []creds.Credential, accessKeyID string) (*Blob, error) { | ||
blob := &Blob{} | ||
for _, credential := range credentials{ | ||
var blobStr = credential.Blob | ||
b := strings.Replace(blobStr,"\\", "", -1 ) | ||
err := json.Unmarshal([]byte(b), blob) | ||
|
||
if err != nil { | ||
return nil, err | ||
} | ||
if blob.Access == accessKeyID { | ||
return blob, nil | ||
} | ||
} | ||
return nil, model.NewNotFoundError("credential is missing") | ||
} |
Oops, something went wrong.