Skip to content

Commit c5b8d35

Browse files
authored
Restructure response of creds path (#79)
Restructure response of `creds` path Description Make response of creds path in clouds.yaml like style Resolves: #78 Acceptance tests Running acceptance tests... === RUN TestPlugin === RUN TestPlugin/TestCloudLifecycle === RUN TestPlugin/TestCloudLifecycle/WriteCloud === RUN TestPlugin/TestCloudLifecycle/ReadCloud === RUN TestPlugin/TestCloudLifecycle/ListClouds === RUN TestPlugin/TestCloudLifecycle/ListClouds/method-LIST === PAUSE TestPlugin/TestCloudLifecycle/ListClouds/method-LIST === RUN TestPlugin/TestCloudLifecycle/ListClouds/method-GET === PAUSE TestPlugin/TestCloudLifecycle/ListClouds/method-GET === CONT TestPlugin/TestCloudLifecycle/ListClouds/method-LIST === CONT TestPlugin/TestCloudLifecycle/ListClouds/method-GET === RUN TestPlugin/TestCloudLifecycle/DeleteCloud === RUN TestPlugin/TestCredsLifecycle === RUN TestPlugin/TestCredsLifecycle/user_token === RUN TestPlugin/TestCredsLifecycle/user_password === RUN TestPlugin/TestCredsLifecycle/root_token === RUN TestPlugin/TestInfo === RUN TestPlugin/TestRoleLifecycle roles_test.go:53: Cloud with name `9u8zkyv1eq` was created === RUN TestPlugin/TestRoleLifecycle/WriteRole === RUN TestPlugin/TestRoleLifecycle/ReadRole === RUN TestPlugin/TestRoleLifecycle/ListRoles === RUN TestPlugin/TestRoleLifecycle/ListRoles/method-LIST === PAUSE TestPlugin/TestRoleLifecycle/ListRoles/method-LIST === RUN TestPlugin/TestRoleLifecycle/ListRoles/method-GET === PAUSE TestPlugin/TestRoleLifecycle/ListRoles/method-GET === CONT TestPlugin/TestRoleLifecycle/ListRoles/method-LIST === CONT TestPlugin/TestRoleLifecycle/ListRoles/method-GET === RUN TestPlugin/TestRoleLifecycle/DeleteRole === CONT TestPlugin/TestRoleLifecycle plugin_test.go:337: Cloud with name `9u8zkyv1eq` has been removed === RUN TestPlugin/TestRootRotate rotate_test.go:65: Cloud with name `default1` was created rotate_test.go:68: Cloud with name `5yai` was created plugin_test.go:337: Cloud with name `5yai` has been removed plugin_test.go:337: Cloud with name `default1` has been removed --- PASS: TestPlugin (11.26s) --- PASS: TestPlugin/TestCloudLifecycle (0.44s) --- PASS: TestPlugin/TestCloudLifecycle/WriteCloud (0.43s) --- PASS: TestPlugin/TestCloudLifecycle/ReadCloud (0.00s) --- PASS: TestPlugin/TestCloudLifecycle/ListClouds (0.00s) --- PASS: TestPlugin/TestCloudLifecycle/ListClouds/method-LIST (0.00s) --- PASS: TestPlugin/TestCloudLifecycle/ListClouds/method-GET (0.00s) --- PASS: TestPlugin/TestCloudLifecycle/DeleteCloud (0.00s) --- PASS: TestPlugin/TestCredsLifecycle (4.77s) --- PASS: TestPlugin/TestCredsLifecycle/user_token (2.52s) --- PASS: TestPlugin/TestCredsLifecycle/user_password (0.79s) --- PASS: TestPlugin/TestCredsLifecycle/root_token (0.58s) --- PASS: TestPlugin/TestInfo (0.00s) --- PASS: TestPlugin/TestRoleLifecycle (0.01s) --- PASS: TestPlugin/TestRoleLifecycle/WriteRole (0.00s) --- PASS: TestPlugin/TestRoleLifecycle/ReadRole (0.00s) --- PASS: TestPlugin/TestRoleLifecycle/ListRoles (0.00s) --- PASS: TestPlugin/TestRoleLifecycle/ListRoles/method-LIST (0.00s) --- PASS: TestPlugin/TestRoleLifecycle/ListRoles/method-GET (0.00s) --- PASS: TestPlugin/TestRoleLifecycle/DeleteRole (0.00s) --- PASS: TestPlugin/TestRootRotate (4.42s) PASS ok github.com/opentelekomcloud/vault-plugin-secrets-openstack/acceptance 11.264s Unit tests === RUN TestBackend_sharedCloud --- PASS: TestBackend_sharedCloud (0.00s) === RUN TestBackend_sharedCloud/existing --- PASS: TestBackend_sharedCloud/existing (0.00s) === RUN TestBackend_sharedCloud/non-existing --- PASS: TestBackend_sharedCloud/non-existing (0.00s) === RUN TestSharedCloud_client --- PASS: TestSharedCloud_client (0.00s) === RUN TestSharedCloud_client/existing-client --- PASS: TestSharedCloud_client/existing-client (0.00s) === RUN TestSharedCloud_client/new-client --- PASS: TestSharedCloud_client/new-client (0.00s) === RUN TestCloudCreate --- PASS: TestCloudCreate (0.00s) === RUN TestCloudCreate/EmptyConfig --- PASS: TestCloudCreate/EmptyConfig (0.00s) === RUN TestCloudCreate/Create --- PASS: TestCloudCreate/Create (0.00s) === RUN TestCloudCreate/Update --- PASS: TestCloudCreate/Update (0.00s) === RUN TestCloudCreate/Read --- PASS: TestCloudCreate/Read (0.00s) === RUN TestCloudCreate/Delete --- PASS: TestCloudCreate/Delete (0.00s) === RUN TestCloudCreate/List --- PASS: TestCloudCreate/List (0.00s) === RUN TestCredentialsRead_ok --- PASS: TestCredentialsRead_ok (0.01s) === RUN TestCredentialsRead_ok/root_token --- PASS: TestCredentialsRead_ok/root_token (0.00s) === RUN TestCredentialsRead_ok/user_token --- PASS: TestCredentialsRead_ok/user_token (0.00s) === RUN TestCredentialsRead_ok/user_password --- PASS: TestCredentialsRead_ok/user_password (0.00s) === RUN TestCredentialsRead_ok/token_revoke --- PASS: TestCredentialsRead_ok/token_revoke (0.00s) === RUN TestCredentialsRead_ok/user_password_revoke --- PASS: TestCredentialsRead_ok/user_password_revoke (0.00s) === RUN TestCredentialsRead_error --- PASS: TestCredentialsRead_error (0.00s) === RUN TestCredentialsRead_error/read-fail --- PASS: TestCredentialsRead_error/read-fail (0.00s) === RUN TestCredentialsRead_error/no-users-token-post --- PASS: TestCredentialsRead_error/no-users-token-post (0.00s) === RUN TestCredentialsRead_error/no-user-post --- PASS: TestCredentialsRead_error/no-user-post (0.00s) === RUN TestCredentialsRevoke_error --- PASS: TestCredentialsRevoke_error (0.00s) === RUN TestCredentialsRevoke_error/no-token-delete --- PASS: TestCredentialsRevoke_error/no-token-delete (0.00s) === RUN TestCredentialsRevoke_error/no-user-delete --- PASS: TestCredentialsRevoke_error/no-user-delete (0.00s) === RUN TestInfoRead === PAUSE TestInfoRead === CONT TestInfoRead --- PASS: TestInfoRead (0.00s) === RUN TestRoleStoragePath --- PASS: TestRoleStoragePath (0.00s) === RUN TestRoleGet === PAUSE TestRoleGet === CONT TestRoleGet --- PASS: TestRoleGet (0.00s) === RUN TestRoleGet/existing === PAUSE TestRoleGet/existing === CONT TestRoleGet/existing --- PASS: TestRoleGet/existing (0.00s) === RUN TestRoleGet/not-existing === PAUSE TestRoleGet/not-existing === CONT TestRoleGet/not-existing --- PASS: TestRoleGet/not-existing (0.00s) === RUN TestRoleGet/get-err === PAUSE TestRoleGet/get-err === CONT TestRoleGet/get-err --- PASS: TestRoleGet/get-err (0.00s) === RUN TestRoleExistence === PAUSE TestRoleExistence === CONT TestRoleExistence --- PASS: TestRoleExistence (0.00s) === RUN TestRoleExistence/existing === PAUSE TestRoleExistence/existing === CONT TestRoleExistence/existing --- PASS: TestRoleExistence/existing (0.00s) === RUN TestRoleExistence/not-existing === PAUSE TestRoleExistence/not-existing === CONT TestRoleExistence/not-existing --- PASS: TestRoleExistence/not-existing (0.00s) === RUN TestRoleExistence/get-err === PAUSE TestRoleExistence/get-err === CONT TestRoleExistence/get-err --- PASS: TestRoleExistence/get-err (0.00s) === RUN TestRoleList === PAUSE TestRoleList === CONT TestRoleList --- PASS: TestRoleList (0.00s) === RUN TestRoleList/ok --- PASS: TestRoleList/ok (0.00s) === RUN TestRoleList/error === PAUSE TestRoleList/error === CONT TestRoleList/error --- PASS: TestRoleList/error (0.00s) === RUN TestRoleList/filter === PAUSE TestRoleList/filter === CONT TestRoleList/filter --- PASS: TestRoleList/filter (0.00s) === RUN TestRoleList/filter-get-err === PAUSE TestRoleList/filter-get-err === CONT TestRoleList/filter-get-err --- PASS: TestRoleList/filter-get-err (0.00s) === RUN TestRoleDelete === PAUSE TestRoleDelete === CONT TestRoleDelete --- PASS: TestRoleDelete (0.00s) === RUN TestRoleDelete/existing === PAUSE TestRoleDelete/existing === CONT TestRoleDelete/existing --- PASS: TestRoleDelete/existing (0.00s) === RUN TestRoleDelete/not-existing === PAUSE TestRoleDelete/not-existing === CONT TestRoleDelete/not-existing --- PASS: TestRoleDelete/not-existing (0.00s) === RUN TestRoleDelete/error === PAUSE TestRoleDelete/error === CONT TestRoleDelete/error --- PASS: TestRoleDelete/error (0.00s) === RUN TestRoleDelete/error-get === PAUSE TestRoleDelete/error-get === CONT TestRoleDelete/error-get --- PASS: TestRoleDelete/error-get (0.00s) === RUN TestRoleCreate === PAUSE TestRoleCreate === CONT TestRoleCreate --- PASS: TestRoleCreate (0.01s) === RUN TestRoleCreate/ok --- PASS: TestRoleCreate/ok (0.00s) === RUN TestRoleCreate/ok/token === PAUSE TestRoleCreate/ok/token === CONT TestRoleCreate/ok/token --- PASS: TestRoleCreate/ok/token (0.00s) === RUN TestRoleCreate/ok/password === PAUSE TestRoleCreate/ok/password === CONT TestRoleCreate/ok/password --- PASS: TestRoleCreate/ok/password (0.00s) === RUN TestRoleCreate/ok/ttl === PAUSE TestRoleCreate/ok/ttl === CONT TestRoleCreate/ok/ttl --- PASS: TestRoleCreate/ok/ttl (0.00s) === RUN TestRoleCreate/ok/endpoint-override === PAUSE TestRoleCreate/ok/endpoint-override === CONT TestRoleCreate/ok/endpoint-override --- PASS: TestRoleCreate/ok/endpoint-override (0.00s) === RUN TestRoleCreate/ok/admin === PAUSE TestRoleCreate/ok/admin === CONT TestRoleCreate/ok/admin --- PASS: TestRoleCreate/ok/admin (0.00s) === RUN TestRoleCreate/error --- PASS: TestRoleCreate/error (0.00s) === RUN TestRoleCreate/error/root-password === PAUSE TestRoleCreate/error/root-password === CONT TestRoleCreate/error/root-password --- PASS: TestRoleCreate/error/root-password (0.00s) === RUN TestRoleCreate/error/root-user-groups === PAUSE TestRoleCreate/error/root-user-groups === CONT TestRoleCreate/error/root-user-groups --- PASS: TestRoleCreate/error/root-user-groups (0.00s) === RUN TestRoleCreate/error/root-user-roles === PAUSE TestRoleCreate/error/root-user-roles === CONT TestRoleCreate/error/root-user-roles --- PASS: TestRoleCreate/error/root-user-roles (0.00s) === RUN TestRoleCreate/error/without-cloud === PAUSE TestRoleCreate/error/without-cloud === CONT TestRoleCreate/error/without-cloud --- PASS: TestRoleCreate/error/without-cloud (0.00s) === RUN TestRoleCreate/error/root-ttl === PAUSE TestRoleCreate/error/root-ttl === CONT TestRoleCreate/error/root-ttl --- PASS: TestRoleCreate/error/root-ttl (0.00s) === RUN TestRoleCreate/not-existing-cloud === PAUSE TestRoleCreate/not-existing-cloud === CONT TestRoleCreate/not-existing-cloud --- PASS: TestRoleCreate/not-existing-cloud (0.00s) === RUN TestRoleCreate/save-store-err === PAUSE TestRoleCreate/save-store-err === CONT TestRoleCreate/save-store-err --- PASS: TestRoleCreate/save-store-err (0.00s) === RUN TestRoleUpdate === PAUSE TestRoleUpdate === CONT TestRoleUpdate --- PASS: TestRoleUpdate (0.00s) === RUN TestRoleUpdate/ok --- PASS: TestRoleUpdate/ok (0.00s) === RUN TestRoleUpdate/not-existing --- PASS: TestRoleUpdate/not-existing (0.00s) === RUN TestRotateRootCredentials_ok --- PASS: TestRotateRootCredentials_ok (0.00s) === RUN TestRotateRootCredentials_error === PAUSE TestRotateRootCredentials_error === CONT TestRotateRootCredentials_error --- PASS: TestRotateRootCredentials_error (0.01s) === RUN TestRotateRootCredentials_error/read-fail --- PASS: TestRotateRootCredentials_error/read-fail (0.00s) === RUN TestRotateRootCredentials_error/no-post --- PASS: TestRotateRootCredentials_error/no-post (0.00s) === RUN TestRotateRootCredentials_error/no-get --- PASS: TestRotateRootCredentials_error/no-get (0.00s) === RUN TestRotateRootCredentials_error/no-change --- PASS: TestRotateRootCredentials_error/no-change (0.00s) PASS ok github.com/opentelekomcloud/vault-plugin-secrets-openstack/openstack (cached) ? github.com/opentelekomcloud/vault-plugin-secrets-openstack/openstack/fixtures [no test files] Process finished with the exit code 0 Reviewed-by: Vladimir Vshivkov <None> Reviewed-by: Anton Sidelnikov <None>
1 parent 5c9cc39 commit c5b8d35

File tree

3 files changed

+85
-31
lines changed

3 files changed

+85
-31
lines changed

acceptance/creds_test.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ func (p *PluginTest) TestCredsLifecycle() {
2929
Root bool
3030
SecretType string
3131
UserRoles []string
32+
Extensions map[string]interface{}
3233
}
3334

3435
cases := map[string]testCase{
@@ -45,13 +46,19 @@ func (p *PluginTest) TestCredsLifecycle() {
4546
Root: false,
4647
SecretType: "token",
4748
UserRoles: []string{"member"},
49+
Extensions: map[string]interface{}{
50+
"identity_api_version": "3",
51+
},
4852
},
4953
"user_password": {
5054
Cloud: cloud.Name,
5155
ProjectID: aux.ProjectID,
5256
DomainID: aux.DomainID,
5357
Root: false,
5458
SecretType: "password",
59+
Extensions: map[string]interface{}{
60+
"object_store_endpoint_override": "https://swift.example.com",
61+
},
5562
},
5663
}
5764

@@ -81,7 +88,7 @@ func (p *PluginTest) TestCredsLifecycle() {
8188
resp, err = p.vaultDo(
8289
http.MethodPost,
8390
roleURL(roleName),
84-
cloudToRoleMap(data.Root, data.Cloud, data.ProjectID, data.DomainID, data.SecretType, data.UserRoles),
91+
cloudToRoleMap(data.Root, data.Cloud, data.ProjectID, data.DomainID, data.SecretType, data.UserRoles, data.Extensions),
8592
)
8693
require.NoError(t, err)
8794
assert.Equal(t, http.StatusNoContent, resp.StatusCode, readJSONResponse(t, resp))
@@ -137,13 +144,14 @@ func cloudToCloudMap(cloud *openstack.OsCloud) map[string]interface{} {
137144
}
138145
}
139146

140-
func cloudToRoleMap(root bool, cloud, projectID, domainID, secretType string, userRoles []string) map[string]interface{} {
147+
func cloudToRoleMap(root bool, cloud, projectID, domainID, secretType string, userRoles []string, extensions map[string]interface{}) map[string]interface{} {
141148
return fixtures.SanitizedMap(map[string]interface{}{
142149
"cloud": cloud,
143150
"project_id": projectID,
144151
"domain_id": domainID,
145152
"root": root,
146153
"secret_type": secretType,
147154
"user_roles": userRoles,
155+
"extensions": extensions,
148156
})
149157
}

openstack/path_creds.go

Lines changed: 70 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,14 @@ func secretToken(b *backend) *framework.Secret {
3939
return &framework.Secret{
4040
Type: backendSecretTypeToken,
4141
Fields: map[string]*framework.FieldSchema{
42-
"token": {
43-
Type: framework.TypeString,
44-
Description: "OpenStack Token.",
45-
},
4642
"cloud": {
4743
Type: framework.TypeString,
4844
Description: "Used cloud.",
4945
},
46+
"auth": {
47+
Type: framework.TypeMap,
48+
Description: "Auth entry for OpenStack clouds.yaml",
49+
},
5050
},
5151
Revoke: b.tokenRevoke,
5252
}
@@ -106,9 +106,12 @@ func getRootCredentials(client *gophercloud.ServiceClient, opts *credsOpts) (*lo
106106
}
107107

108108
data := map[string]interface{}{
109-
"auth_url": opts.Config.AuthURL,
110-
"token": token.ID,
111-
"expires_at": token.ExpiresAt.String(),
109+
"auth": map[string]interface{}{
110+
"auth_url": opts.Config.AuthURL,
111+
"token": token.ID,
112+
"user_domain_name": opts.Config.UserDomainName,
113+
},
114+
"auth_type": "token",
112115
}
113116
secret := &logical.Secret{
114117
LeaseOptions: logical.LeaseOptions{
@@ -118,6 +121,7 @@ func getRootCredentials(client *gophercloud.ServiceClient, opts *credsOpts) (*lo
118121
InternalData: map[string]interface{}{
119122
"secret_type": backendSecretTypeToken,
120123
"cloud": opts.Config.Name,
124+
"expires_at": token.ExpiresAt.String(),
121125
},
122126
}
123127
return &logical.Response{Data: data, Secret: secret}, nil
@@ -156,30 +160,33 @@ func getTmpUserCredentials(client *gophercloud.ServiceClient, opts *credsOpts) (
156160
}
157161

158162
data = map[string]interface{}{
159-
"auth_url": opts.Config.AuthURL,
160-
"token": token.ID,
161-
"expires_at": token.ExpiresAt.String(),
163+
"auth": formAuthResponse(
164+
opts.Role,
165+
"",
166+
"",
167+
token.ID,
168+
opts.Config.AuthURL,
169+
user.DomainID,
170+
),
171+
"auth_type": "token",
162172
}
163173
secretInternal = map[string]interface{}{
164174
"secret_type": backendSecretTypeUser,
165175
"user_id": user.ID,
166176
"cloud": opts.Config.Name,
177+
"expires_at": token.ExpiresAt.String(),
167178
}
168179
case SecretPassword:
169180
data = map[string]interface{}{
170-
"auth_url": opts.Config.AuthURL,
171-
"username": user.Name,
172-
"password": password,
173-
}
174-
switch {
175-
case opts.Role.ProjectID != "":
176-
data["project_id"] = opts.Role.ProjectID
177-
data["project_domain_id"] = user.DomainID
178-
case opts.Role.ProjectName != "":
179-
data["project_name"] = opts.Role.ProjectName
180-
data["project_domain_id"] = user.DomainID
181-
default:
182-
data["user_domain_id"] = user.DomainID
181+
"auth": formAuthResponse(
182+
opts.Role,
183+
user.Name,
184+
password,
185+
"",
186+
opts.Config.AuthURL,
187+
user.DomainID,
188+
),
189+
"auth_type": "password",
183190
}
184191

185192
secretInternal = map[string]interface{}{
@@ -191,6 +198,10 @@ func getTmpUserCredentials(client *gophercloud.ServiceClient, opts *credsOpts) (
191198
return nil, fmt.Errorf("invalid secret type: %s", r)
192199
}
193200

201+
for extensionKey, extensionValue := range opts.Role.Extensions {
202+
data[extensionKey] = extensionValue
203+
}
204+
194205
return &logical.Response{
195206
Data: data,
196207
Secret: &logical.Secret{
@@ -236,12 +247,13 @@ func (b *backend) pathCredsRead(ctx context.Context, r *logical.Request, d *fram
236247
}
237248

238249
func (b *backend) tokenRevoke(ctx context.Context, r *logical.Request, d *framework.FieldData) (*logical.Response, error) {
239-
tokenRaw, ok := d.GetOk("token")
250+
authInfoRaw, ok := d.GetOk("auth")
240251
if !ok {
241-
return nil, errors.New("data 'token' not found")
252+
return nil, errors.New("data 'auth' not found")
242253
}
243254

244-
token := tokenRaw.(string)
255+
authInfo := authInfoRaw.(map[string]interface{})
256+
token := authInfo["token"].(string)
245257

246258
cloudNameRaw, ok := r.Secret.InternalData["cloud"]
247259
if !ok {
@@ -452,3 +464,35 @@ func getScopeFromRole(role *roleEntry) tokens.Scope {
452464
}
453465
return scope
454466
}
467+
468+
func formAuthResponse(role *roleEntry, username, password, token, authURL, domainID string) map[string]interface{} {
469+
var auth map[string]interface{}
470+
471+
switch {
472+
case role.ProjectID != "":
473+
auth = map[string]interface{}{
474+
"project_id": role.ProjectID,
475+
"project_domain_id": domainID,
476+
}
477+
case role.ProjectName != "":
478+
auth = map[string]interface{}{
479+
"project_id": role.ProjectName,
480+
"project_domain_id": domainID,
481+
}
482+
default:
483+
auth = map[string]interface{}{
484+
"user_domain_id": domainID,
485+
}
486+
}
487+
488+
if token != "" {
489+
auth["token"] = token
490+
} else {
491+
auth["username"] = username
492+
auth["password"] = password
493+
}
494+
495+
auth["auth_url"] = authURL
496+
497+
return auth
498+
}

openstack/path_creds_test.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ func TestCredentialsRead_ok(t *testing.T) {
5757
})
5858
require.NoError(t, err)
5959
require.NotEmpty(t, res.Data)
60-
assert.NotEmpty(t, res.Data["expires_at"])
60+
assert.NotEmpty(t, res.Data["auth"])
6161
})
6262
t.Run("user_token", func(t *testing.T) {
6363
require.NoError(t, s.Put(context.Background(), cloudEntry))
@@ -97,7 +97,9 @@ func TestCredentialsRead_ok(t *testing.T) {
9797
})
9898
require.NoError(t, err)
9999
require.NotEmpty(t, res.Data)
100-
require.Equal(t, res.Data["token"], testClient.TokenID)
100+
require.NotEmpty(t, res.Data["auth"])
101+
authInfo := res.Data["auth"].(map[string]interface{})
102+
require.Equal(t, authInfo["token"], testClient.TokenID)
101103

102104
_, err = b.HandleRequest(context.Background(), &logical.Request{
103105
Operation: logical.RevokeOperation,
@@ -120,7 +122,7 @@ func TestCredentialsRead_ok(t *testing.T) {
120122
require.NoError(t, err)
121123
require.False(t, res.IsError(), res.Error())
122124
require.NotEmpty(t, res.Data)
123-
require.NotEmpty(t, res.Data["password"])
125+
require.NotEmpty(t, res.Data["auth"])
124126
require.NotEmpty(t, res.Secret.InternalData["user_id"])
125127

126128
_, err = b.HandleRequest(context.Background(), &logical.Request{

0 commit comments

Comments
 (0)