Skip to content

Commit 2f5bfa8

Browse files
Vault: user_domain_id/name and project_domain_id/name implementation for dynamic users (#119)
Vault: user_domain_id/name and project_domain_id/name implementation for dynamic users Implementation of user_domain_id/name and project_domain_id/name for dynamic users. Changes include: path_roles.go path_roles_test.go api.md path_creds.go path_creds_test.go tests for new parameters Reviewed-by: Aloento Reviewed-by: Anton Sidelnikov Reviewed-by: Polina Gubina Reviewed-by: Artem Lifshits
1 parent c505d76 commit 2f5bfa8

File tree

9 files changed

+382
-86
lines changed

9 files changed

+382
-86
lines changed

acceptance/creds_test.go

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package acceptance
66
import (
77
"fmt"
88
"net/http"
9+
"os"
910
"testing"
1011

1112
"github.com/opentelekomcloud/vault-plugin-secrets-openstack/openstack"
@@ -15,18 +16,22 @@ import (
1516
)
1617

1718
type testCase struct {
18-
Cloud string
19-
ProjectID string
20-
DomainID string
21-
Root bool
22-
SecretType string
23-
UserRoles []string
24-
Extensions map[string]interface{}
19+
Cloud string
20+
ProjectID string
21+
DomainID string
22+
UserDomainID string
23+
UserDomainName string
24+
Root bool
25+
SecretType string
26+
UserRoles []string
27+
UserGroups []string
28+
Extensions map[string]interface{}
2529
}
2630

2731
func (p *PluginTest) TestCredsLifecycle() {
2832
t := p.T()
2933

34+
userDomainID := os.Getenv("USER_DOMAIN_ID")
3035
cloud := openstackCloudConfig(t)
3136
require.NotEmpty(t, cloud)
3237

@@ -45,7 +50,7 @@ func (p *PluginTest) TestCredsLifecycle() {
4550
DomainID: aux.DomainID,
4651
Root: false,
4752
SecretType: "token",
48-
UserRoles: []string{"member"},
53+
UserGroups: []string{"mygroup"},
4954
Extensions: map[string]interface{}{
5055
"identity_api_version": "3",
5156
},
@@ -60,6 +65,17 @@ func (p *PluginTest) TestCredsLifecycle() {
6065
"object_store_endpoint_override": "https://swift.example.com",
6166
},
6267
},
68+
"user_domain_id_token": {
69+
Cloud: cloud.Name,
70+
ProjectID: aux.ProjectID,
71+
UserDomainID: userDomainID,
72+
Root: false,
73+
SecretType: "token",
74+
UserRoles: []string{"member"},
75+
Extensions: map[string]interface{}{
76+
"identity_api_version": "3",
77+
},
78+
},
6379
}
6480

6581
for name, data := range cases {
@@ -154,12 +170,15 @@ func cloudToCloudMap(cloud *openstack.OsCloud) map[string]interface{} {
154170

155171
func cloudToRoleMap(data testCase) map[string]interface{} {
156172
return fixtures.SanitizedMap(map[string]interface{}{
157-
"cloud": data.Cloud,
158-
"project_id": data.ProjectID,
159-
"domain_id": data.DomainID,
160-
"root": data.Root,
161-
"secret_type": data.SecretType,
162-
"user_roles": data.UserRoles,
163-
"extensions": data.Extensions,
173+
"cloud": data.Cloud,
174+
"project_id": data.ProjectID,
175+
"user_domain_id": data.UserDomainID,
176+
"user_domain_name": data.UserDomainName,
177+
"domain_id": data.DomainID,
178+
"root": data.Root,
179+
"secret_type": data.SecretType,
180+
"user_roles": data.UserRoles,
181+
"user_groups": data.UserGroups,
182+
"extensions": data.Extensions,
164183
})
165184
}

acceptance/roles_test.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ func extractRoleData(t *testing.T, resp *http.Response) *roleData {
4040

4141
func (p *PluginTest) TestRoleLifecycle() {
4242
t := p.T()
43-
4443
cloud := openstackCloudConfig(t)
4544
require.NotEmpty(t, cloud)
4645

doc/source/api.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,8 @@ created. If the role exists, it will be updated with the new attributes.
154154
If set to `true`, `user_groups` value is ignored.
155155
if set to `true`, `user_roles` value is ignored.
156156
If set to `true`, `ttl` value is ignored.
157+
if set to `true`, `user_domain_id` value is ignored.
158+
If set to `true`, `user_domain_name` value is ignored.
157159

158160
- `ttl` `(string: "1h")` - Specifies TTL value for the dynamically created users as a
159161
string duration with time suffix.
@@ -179,7 +181,19 @@ created. If the role exists, it will be updated with the new attributes.
179181
- `domain_name` `(string: <optional>)` - Create a domain-scoped role with given domain name. Mutually exclusive with
180182
`domain_id`.
181183

182-
When none of `project_name` or `project_id` is set, created role will have a project scope.
184+
- `user_domain_id` `(string: <optional>)` - Specifies domain where user will be created with given domain id.
185+
Mutually exclusive with `user_project_name`.
186+
187+
- `user_domain_name` `(string: <optional>)` - Specifies domain where user will be created with given domain name.
188+
Mutually exclusive with `user_project_id`.
189+
190+
- `project_domain_id` `(string: <optional>)` - Specifies domain for project-scoped role with given domain id.
191+
If one of `project_id` / `project_name` is not set `project_domain_id` value is ignored.
192+
193+
- `project_domain_name` `(string: <optional>)` - Specifies domain for project-scoped role with given domain name.
194+
If one of `project_id` / `project_name` is not set `project_domain_name` value is ignored.
195+
196+
When one of `project_name` or `project_id` is set, created role will have a project scope.
183197

184198
- `extensions` `(list: [])` - A list of strings representing a key/value pair to be used as extensions to the cloud
185199
configuration (e.g. `volume_api_version` or endpoint overrides). Format is a key and value

openstack/common/gopher_api.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package common
2+
3+
import (
4+
"github.com/gophercloud/gophercloud"
5+
"github.com/gophercloud/gophercloud/openstack/identity/v3/domains"
6+
"github.com/gophercloud/gophercloud/pagination"
7+
)
8+
9+
func listAvailableURL(client *gophercloud.ServiceClient) string {
10+
return client.ServiceURL("auth", "domains")
11+
}
12+
13+
func ListAvailable(client *gophercloud.ServiceClient) pagination.Pager {
14+
url := listAvailableURL(client)
15+
return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page {
16+
return domains.DomainPage{LinkedPageBase: pagination.LinkedPageBase{PageResult: r}}
17+
})
18+
}

openstack/fixtures/helpers.go

Lines changed: 131 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -92,11 +92,73 @@ func handleGetToken(t *testing.T, w http.ResponseWriter, r *http.Request, userID
9292
w.WriteHeader(http.StatusOK)
9393
_, _ = fmt.Fprintf(w, `
9494
{
95-
"token": {
96-
"user": {
97-
"id": "%s"
95+
"token": {
96+
"methods": [
97+
"password"
98+
],
99+
"user": {
100+
"domain": {
101+
"id": "28c40f683607401da09214d373785a2d",
102+
"name": "mydomain"
103+
},
104+
"id": "%s",
105+
"name": "admin",
106+
"password_expires_at": null
107+
},
108+
"audit_ids": [
109+
"79uOElBBQguxhPHVLlCiIQ"
110+
],
111+
"expires_at": "2022-11-19T01:54:23.000000Z",
112+
"issued_at": "2022-11-18T13:54:23.000000Z",
113+
"domain": {
114+
"id": "52af04aec5f84182b06959d2775d2000",
115+
"name": "mydomain"
116+
},
117+
"roles": [
118+
{
119+
"id": "7d7d81cdaad4475e96d34817f1632eca",
120+
"name": "reader"
121+
},
122+
{
123+
"id": "72badea89a5d4d9cb97a4d13e8d8c486",
124+
"name": "member"
125+
},
126+
{
127+
"id": "60e69bd42e12450b925f763d574d6125",
128+
"name": "admin"
129+
}
130+
],
131+
"catalog": [
132+
{
133+
"endpoints": [
134+
{
135+
"id": "333f811aeff140768a59c9d1d9b43087",
136+
"interface": "internal",
137+
"region_id": "RegionOne",
138+
"url": "http://example.com",
139+
"region": "RegionOne"
140+
},
141+
{
142+
"id": "96207c76a6154aaaa017214cd0a27810",
143+
"interface": "admin",
144+
"region_id": "RegionOne",
145+
"url": "http://example.com",
146+
"region": "RegionOne"
147+
},
148+
{
149+
"id": "b3861966f62349d6ae73bf113eacb2cc",
150+
"interface": "public",
151+
"region_id": "RegionOne",
152+
"url": "http://example.com",
153+
"region": "RegionOne"
154+
}
155+
],
156+
"id": "b2724497bfac49a68578e11fa7c34292",
157+
"type": "identity",
158+
"name": "keystone"
159+
}
160+
]
98161
}
99-
}
100162
}
101163
`, userID)
102164
}
@@ -303,18 +365,61 @@ func handleProjectList(t *testing.T, w http.ResponseWriter, r *http.Request, pro
303365
`, projectName)
304366
}
305367

368+
func handleDomainList(t *testing.T, w http.ResponseWriter, r *http.Request, projectName string) {
369+
t.Helper()
370+
371+
th.TestHeader(t, r, "Accept", "application/json")
372+
th.TestMethod(t, r, "GET")
373+
374+
w.Header().Add("Content-Type", "application/json")
375+
376+
_, _ = fmt.Fprintf(w, `
377+
{
378+
"domains": [
379+
{
380+
"id": "test-id",
381+
"name": "%s",
382+
"description": "",
383+
"enabled": true,
384+
"tags": [],
385+
"options": {},
386+
"links": {
387+
"self": "https://example.com/v3/domains/test-id"
388+
}
389+
},
390+
{
391+
"id": "default",
392+
"name": "Default",
393+
"description": "The default domain",
394+
"enabled": true,
395+
"tags": [],
396+
"options": {},
397+
"links": {
398+
"self": "https://example.com/v3/domains/default"
399+
}
400+
}
401+
],
402+
"links": {
403+
"next": null,
404+
"self": "https://example.com/v3/domains",
405+
"previous": null
406+
}
407+
}`, projectName)
408+
}
409+
306410
type EnabledMocks struct {
307-
TokenPost bool
308-
TokenGet bool
309-
TokenDelete bool
310-
PasswordChange bool
311-
ProjectList bool
312-
UserPost bool
313-
UserPatch bool
314-
UserList bool
315-
UserDelete bool
316-
UserGet bool
317-
GroupList bool
411+
TokenPost bool
412+
TokenGet bool
413+
TokenDelete bool
414+
PasswordChange bool
415+
ProjectList bool
416+
UserPost bool
417+
UserPatch bool
418+
UserList bool
419+
UserDelete bool
420+
UserGet bool
421+
GroupList bool
422+
AvailDomainList bool
318423
}
319424

320425
func SetupKeystoneMock(t *testing.T, userID, projectName string, enabled EnabledMocks) {
@@ -410,4 +515,15 @@ func SetupKeystoneMock(t *testing.T, userID, projectName string, enabled Enabled
410515
w.WriteHeader(404)
411516
}
412517
})
518+
519+
th.Mux.HandleFunc("/v3/auth/domains", func(w http.ResponseWriter, r *http.Request) {
520+
switch r.Method {
521+
case "GET":
522+
if enabled.AvailDomainList {
523+
handleDomainList(t, w, r, projectName)
524+
}
525+
default:
526+
w.WriteHeader(404)
527+
}
528+
})
413529
}

0 commit comments

Comments
 (0)