Skip to content

Commit 384f556

Browse files
Vault: static-creds implementation (#99)
Vault: ``static-creds`` implementation This PR add static-creds read path and relevant acceptance/unit tests, api documentation. static-roles logic was also updated. Acceptance tests (failing on unrelated info test): 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/root_token === RUN TestPlugin/TestCredsLifecycle/user_token === RUN TestPlugin/TestCredsLifecycle/user_password === RUN TestPlugin/TestInfo info_test.go:42: Error Trace: info_test.go:42 Error: Should NOT be empty, but was &{ } Test: TestPlugin/TestInfo === RUN TestPlugin/TestRoleLifecycle roles_test.go:53: Cloud with name sjz3x3v53l 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 sjz3x3v53l has been removed === RUN TestPlugin/TestRootRotate rotate_test.go:65: Cloud with name default1 was created rotate_test.go:68: Cloud with name 9jy7 was created plugin_test.go:337: Cloud with name 9jy7 has been removed plugin_test.go:337: Cloud with name default1 has been removed === RUN TestPlugin/TestStaticCredsLifecycle === RUN TestPlugin/TestStaticCredsLifecycle/user_password === RUN TestPlugin/TestStaticCredsLifecycle/user_token === RUN TestPlugin/TestStaticRoleLifecycle === RUN TestPlugin/TestStaticRoleLifecycle/WriteRole === RUN TestPlugin/TestStaticRoleLifecycle/ReadRole === RUN TestPlugin/TestStaticRoleLifecycle/ListRoles === RUN TestPlugin/TestStaticRoleLifecycle/ListRoles/method-LIST === PAUSE TestPlugin/TestStaticRoleLifecycle/ListRoles/method-LIST === RUN TestPlugin/TestStaticRoleLifecycle/ListRoles/method-GET === PAUSE TestPlugin/TestStaticRoleLifecycle/ListRoles/method-GET === CONT TestPlugin/TestStaticRoleLifecycle/ListRoles/method-LIST === CONT TestPlugin/TestStaticRoleLifecycle/ListRoles/method-GET === RUN TestPlugin/TestStaticRoleLifecycle/DeleteRole --- FAIL: TestPlugin (21.57s) --- PASS: TestPlugin/TestCloudLifecycle (0.09s) --- PASS: TestPlugin/TestCloudLifecycle/WriteCloud (0.08s) --- 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 (6.18s) --- PASS: TestPlugin/TestCredsLifecycle/root_token (1.95s) --- PASS: TestPlugin/TestCredsLifecycle/user_token (2.19s) --- PASS: TestPlugin/TestCredsLifecycle/user_password (0.98s) --- FAIL: 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 (5.21s) --- PASS: TestPlugin/TestStaticCredsLifecycle (6.76s) --- PASS: TestPlugin/TestStaticCredsLifecycle/user_password (2.87s) --- PASS: TestPlugin/TestStaticCredsLifecycle/user_token (3.06s) --- PASS: TestPlugin/TestStaticRoleLifecycle (3.17s) --- PASS: TestPlugin/TestStaticRoleLifecycle/WriteRole (1.23s) --- PASS: TestPlugin/TestStaticRoleLifecycle/ReadRole (0.01s) --- PASS: TestPlugin/TestStaticRoleLifecycle/ListRoles (0.00s) --- PASS: TestPlugin/TestStaticRoleLifecycle/ListRoles/method-LIST (0.00s) --- PASS: TestPlugin/TestStaticRoleLifecycle/ListRoles/method-GET (0.00s) --- PASS: TestPlugin/TestStaticRoleLifecycle/DeleteRole (0.00s) FAIL FAIL github.com/opentelekomcloud/vault-plugin-secrets-openstack/acceptance 22.159s FAIL make: *** [functional] Error 1 Unit tests: === RUN TestBackend_sharedCloud === RUN TestBackend_sharedCloud/existing === RUN TestBackend_sharedCloud/non-existing --- PASS: TestBackend_sharedCloud (0.00s) --- PASS: TestBackend_sharedCloud/existing (0.00s) --- PASS: TestBackend_sharedCloud/non-existing (0.00s) === RUN TestSharedCloud_client === RUN TestSharedCloud_client/existing-client === RUN TestSharedCloud_client/new-client --- PASS: TestSharedCloud_client (0.00s) --- PASS: TestSharedCloud_client/existing-client (0.00s) --- PASS: TestSharedCloud_client/new-client (0.00s) === RUN TestCloudCreate === RUN TestCloudCreate/EmptyConfig === RUN TestCloudCreate/Create === RUN TestCloudCreate/Update === RUN TestCloudCreate/Read === RUN TestCloudCreate/Delete === RUN TestCloudCreate/List --- PASS: TestCloudCreate (0.00s) --- PASS: TestCloudCreate/EmptyConfig (0.00s) --- PASS: TestCloudCreate/Create (0.00s) --- PASS: TestCloudCreate/Update (0.00s) --- PASS: TestCloudCreate/Read (0.00s) --- PASS: TestCloudCreate/Delete (0.00s) --- PASS: TestCloudCreate/List (0.00s) === RUN TestCredentialsRead_ok === RUN TestCredentialsRead_ok/root_token === RUN TestCredentialsRead_ok/user_token === RUN TestCredentialsRead_ok/user_password === RUN TestCredentialsRead_ok/token_revoke === RUN TestCredentialsRead_ok/user_password_revoke --- PASS: TestCredentialsRead_ok (0.01s) --- PASS: TestCredentialsRead_ok/root_token (0.00s) --- PASS: TestCredentialsRead_ok/user_token (0.00s) --- PASS: TestCredentialsRead_ok/user_password (0.00s) --- PASS: TestCredentialsRead_ok/token_revoke (0.00s) --- PASS: TestCredentialsRead_ok/user_password_revoke (0.00s) === RUN TestCredentialsRead_error === RUN TestCredentialsRead_error/read-fail === RUN TestCredentialsRead_error/no-user-post === RUN TestCredentialsRead_error/no-users-token-post --- PASS: TestCredentialsRead_error (0.00s) --- PASS: TestCredentialsRead_error/read-fail (0.00s) --- PASS: TestCredentialsRead_error/no-user-post (0.00s) --- PASS: TestCredentialsRead_error/no-users-token-post (0.00s) === RUN TestCredentialsRevoke_error === RUN TestCredentialsRevoke_error/no-token-delete === RUN TestCredentialsRevoke_error/no-user-delete --- PASS: TestCredentialsRevoke_error (0.00s) --- PASS: TestCredentialsRevoke_error/no-token-delete (0.00s) --- PASS: TestCredentialsRevoke_error/no-user-delete (0.00s) === RUN TestInfoRead === PAUSE TestInfoRead === RUN TestRoleStoragePath --- PASS: TestRoleStoragePath (0.00s) === RUN TestRoleGet === PAUSE TestRoleGet === RUN TestRoleExistence === PAUSE TestRoleExistence === RUN TestRoleList === PAUSE TestRoleList === RUN TestRoleDelete === PAUSE TestRoleDelete === RUN TestRoleCreate === PAUSE TestRoleCreate === RUN TestRoleUpdate === PAUSE TestRoleUpdate === RUN TestRotateRootCredentials_ok --- PASS: TestRotateRootCredentials_ok (0.00s) === RUN TestRotateRootCredentials_error === PAUSE TestRotateRootCredentials_error === RUN TestStaticCredentialsRead_ok === RUN TestStaticCredentialsRead_ok/user_token === RUN TestStaticCredentialsRead_ok/user_password --- PASS: TestStaticCredentialsRead_ok (0.00s) --- PASS: TestStaticCredentialsRead_ok/user_token (0.00s) --- PASS: TestStaticCredentialsRead_ok/user_password (0.00s) === RUN TestStaticCredentialsRead_error === RUN TestStaticCredentialsRead_error/read-fail === RUN TestStaticCredentialsRead_error/no-token-post === RUN TestStaticCredentialsRead_error/no-token-get --- PASS: TestStaticCredentialsRead_error (0.00s) --- PASS: TestStaticCredentialsRead_error/read-fail (0.00s) --- PASS: TestStaticCredentialsRead_error/no-token-post (0.00s) --- PASS: TestStaticCredentialsRead_error/no-token-get (0.00s) === RUN TestStaticRoleStoragePath --- PASS: TestStaticRoleStoragePath (0.00s) === RUN TestStaticRoleGet === PAUSE TestStaticRoleGet === RUN TestStaticRoleExistence === PAUSE TestStaticRoleExistence === RUN TestStaticRoleList === PAUSE TestStaticRoleList === RUN TestStaticRoleDelete === PAUSE TestStaticRoleDelete === RUN TestStaticRoleCreate === PAUSE TestStaticRoleCreate === RUN TestStaticRoleUpdate === PAUSE TestStaticRoleUpdate === CONT TestInfoRead === CONT TestRotateRootCredentials_error === RUN TestRotateRootCredentials_error/read-fail === CONT TestStaticRoleDelete === CONT TestStaticRoleUpdate === CONT TestRoleDelete === RUN TestRoleDelete/existing === CONT TestStaticRoleExistence === CONT TestRoleCreate === CONT TestStaticRoleGet === PAUSE TestRoleDelete/existing === RUN TestRoleDelete/not-existing === CONT TestStaticRoleCreate === RUN TestStaticRoleCreate/ok === PAUSE TestRoleDelete/not-existing === RUN TestStaticRoleExistence/existing === RUN TestStaticRoleCreate/ok/token === PAUSE TestStaticRoleCreate/ok/token === RUN TestStaticRoleCreate/ok/password === PAUSE TestStaticRoleExistence/existing === RUN TestStaticRoleExistence/not-existing === RUN TestStaticRoleUpdate/ok === RUN TestStaticRoleDelete/existing === PAUSE TestStaticRoleDelete/existing === RUN TestRoleCreate/ok --- PASS: TestInfoRead (0.00s) === CONT TestRoleExistence === RUN TestRoleExistence/existing === PAUSE TestRoleExistence/existing === RUN TestRoleExistence/not-existing === PAUSE TestRoleExistence/not-existing === RUN TestRoleExistence/get-err === PAUSE TestRoleExistence/get-err === RUN TestRotateRootCredentials_error/no-change === CONT TestRoleList === RUN TestRoleList/ok === RUN TestStaticRoleGet/existing === RUN TestRoleDelete/error === RUN TestStaticRoleDelete/not-existing === CONT TestRoleUpdate === RUN TestRoleCreate/ok/admin === PAUSE TestRoleCreate/ok/admin === RUN TestRoleCreate/ok/token === PAUSE TestRoleCreate/ok/token === RUN TestRoleCreate/ok/password === PAUSE TestRoleCreate/ok/password === PAUSE TestStaticRoleCreate/ok/password === RUN TestRoleUpdate/ok === RUN TestStaticRoleCreate/ok/rotation_duration === PAUSE TestStaticRoleCreate/ok/rotation_duration === RUN TestStaticRoleCreate/ok/endpoint-override === PAUSE TestStaticRoleCreate/ok/endpoint-override === PAUSE TestStaticRoleExistence/not-existing === RUN TestStaticRoleExistence/get-err === PAUSE TestStaticRoleExistence/get-err === CONT TestRoleGet === RUN TestRoleGet/existing === PAUSE TestRoleGet/existing === RUN TestRoleGet/not-existing === PAUSE TestRoleGet/not-existing === RUN TestRoleGet/get-err === PAUSE TestRoleGet/get-err === PAUSE TestStaticRoleGet/existing === RUN TestStaticRoleGet/not-existing === PAUSE TestStaticRoleGet/not-existing === RUN TestRoleList/error === CONT TestRoleExistence/existing === PAUSE TestRoleList/error === RUN TestRoleList/filter === PAUSE TestRoleList/filter === RUN TestRoleList/filter-get-err === PAUSE TestRoleList/filter-get-err === RUN TestStaticRoleGet/get-err === PAUSE TestStaticRoleGet/get-err === CONT TestRoleExistence/get-err === RUN TestStaticRoleUpdate/not-existing === CONT TestStaticRoleCreate/ok/token === PAUSE TestStaticRoleDelete/not-existing === RUN TestStaticRoleDelete/error === PAUSE TestStaticRoleDelete/error === RUN TestStaticRoleDelete/error-get === RUN TestRoleUpdate/not-existing === RUN TestRoleCreate/ok/ttl === PAUSE TestRoleCreate/ok/ttl === RUN TestRoleCreate/ok/endpoint-override === PAUSE TestRoleCreate/ok/endpoint-override === CONT TestRoleGet/existing === CONT TestRoleExistence/not-existing === PAUSE TestRoleDelete/error === RUN TestRoleDelete/error-get === PAUSE TestRoleDelete/error-get --- PASS: TestStaticRoleUpdate (0.00s) --- PASS: TestStaticRoleUpdate/ok (0.00s) --- PASS: TestStaticRoleUpdate/not-existing (0.00s) === CONT TestStaticRoleCreate/ok/rotation_duration --- PASS: TestRoleUpdate (0.00s) --- PASS: TestRoleUpdate/ok (0.00s) --- PASS: TestRoleUpdate/not-existing (0.00s) === CONT TestStaticRoleExistence/not-existing --- PASS: TestRoleExistence (0.00s) --- PASS: TestRoleExistence/get-err (0.00s) --- PASS: TestRoleExistence/existing (0.00s) --- PASS: TestRoleExistence/not-existing (0.00s) === CONT TestRoleList/error === CONT TestStaticRoleExistence/get-err === CONT TestStaticRoleGet/existing === CONT TestStaticRoleExistence/existing === CONT TestRoleGet/get-err === CONT TestStaticRoleList === CONT TestStaticRoleCreate/ok/password === CONT TestStaticRoleCreate/ok/endpoint-override === CONT TestRoleGet/not-existing === RUN TestStaticRoleList/ok === CONT TestRoleCreate/ok/admin === CONT TestRoleList/filter-get-err === RUN TestStaticRoleList/error === PAUSE TestStaticRoleList/error === RUN TestStaticRoleList/filter === PAUSE TestStaticRoleList/filter === RUN TestStaticRoleList/filter-get-err === PAUSE TestStaticRoleList/filter-get-err === CONT TestRoleList/filter --- PASS: TestStaticRoleExistence (0.00s) --- PASS: TestStaticRoleExistence/not-existing (0.00s) --- PASS: TestStaticRoleExistence/get-err (0.00s) --- PASS: TestStaticRoleExistence/existing (0.00s) === CONT TestStaticRoleGet/not-existing === CONT TestStaticRoleGet/get-err === CONT TestRoleCreate/ok/ttl === CONT TestRoleCreate/ok/endpoint-override --- PASS: TestRoleList (0.00s) --- PASS: TestRoleList/ok (0.00s) --- PASS: TestRoleList/error (0.00s) --- PASS: TestRoleList/filter-get-err (0.00s) --- PASS: TestRoleList/filter (0.00s) === CONT TestRoleCreate/ok/password === CONT TestRoleCreate/ok/token === CONT TestRoleDelete/existing --- PASS: TestStaticRoleGet (0.00s) --- PASS: TestStaticRoleGet/existing (0.00s) --- PASS: TestStaticRoleGet/get-err (0.00s) --- PASS: TestStaticRoleGet/not-existing (0.00s) === CONT TestStaticRoleDelete/existing === CONT TestRoleDelete/error === CONT TestRoleDelete/not-existing === CONT TestStaticRoleDelete/not-existing === CONT TestRoleDelete/error-get === CONT TestStaticRoleDelete/error --- PASS: TestRoleGet (0.00s) --- PASS: TestRoleGet/existing (0.00s) --- PASS: TestRoleGet/get-err (0.00s) --- PASS: TestRoleGet/not-existing (0.00s) === CONT TestStaticRoleList/error === CONT TestStaticRoleList/filter-get-err === CONT TestStaticRoleList/filter === RUN TestRoleCreate/error --- PASS: TestRoleDelete (0.00s) --- PASS: TestRoleDelete/existing (0.00s) --- PASS: TestRoleDelete/error (0.00s) --- PASS: TestRoleDelete/error-get (0.00s) --- PASS: TestRoleDelete/not-existing (0.00s) === RUN TestRoleCreate/error/root-ttl --- PASS: TestStaticRoleDelete (0.00s) --- PASS: TestStaticRoleDelete/error-get (0.00s) --- PASS: TestStaticRoleDelete/existing (0.00s) --- PASS: TestStaticRoleDelete/not-existing (0.00s) --- PASS: TestStaticRoleDelete/error (0.00s) === PAUSE TestRoleCreate/error/root-ttl === RUN TestRoleCreate/error/root-password === PAUSE TestRoleCreate/error/root-password === RUN TestRoleCreate/error/root-user-groups === PAUSE TestRoleCreate/error/root-user-groups === RUN TestRoleCreate/error/root-user-roles === PAUSE TestRoleCreate/error/root-user-roles === RUN TestRoleCreate/error/without-cloud === PAUSE TestRoleCreate/error/without-cloud === CONT TestRoleCreate/error/root-ttl === CONT TestRoleCreate/error/without-cloud --- PASS: TestStaticRoleList (0.00s) --- PASS: TestStaticRoleList/ok (0.00s) --- PASS: TestStaticRoleList/error (0.00s) --- PASS: TestStaticRoleList/filter-get-err (0.00s) --- PASS: TestStaticRoleList/filter (0.00s) === CONT TestRoleCreate/error/root-user-groups === CONT TestRoleCreate/error/root-password === CONT TestRoleCreate/error/root-user-roles === RUN TestRoleCreate/not-existing-cloud === PAUSE TestRoleCreate/not-existing-cloud === RUN TestRoleCreate/save-store-err === PAUSE TestRoleCreate/save-store-err === CONT TestRoleCreate/not-existing-cloud === CONT TestRoleCreate/save-store-err --- PASS: TestRoleCreate (0.00s) --- PASS: TestRoleCreate/ok (0.00s) --- PASS: TestRoleCreate/ok/admin (0.00s) --- PASS: TestRoleCreate/ok/ttl (0.00s) --- PASS: TestRoleCreate/ok/endpoint-override (0.00s) --- PASS: TestRoleCreate/ok/password (0.00s) --- PASS: TestRoleCreate/ok/token (0.00s) --- PASS: TestRoleCreate/error (0.00s) --- PASS: TestRoleCreate/error/root-ttl (0.00s) --- PASS: TestRoleCreate/error/without-cloud (0.00s) --- PASS: TestRoleCreate/error/root-user-groups (0.00s) --- PASS: TestRoleCreate/error/root-user-roles (0.00s) --- PASS: TestRoleCreate/error/root-password (0.00s) --- PASS: TestRoleCreate/save-store-err (0.00s) --- PASS: TestRoleCreate/not-existing-cloud (0.00s) === RUN TestRotateRootCredentials_error/no-post === RUN TestRotateRootCredentials_error/no-get --- PASS: TestRotateRootCredentials_error (0.01s) --- PASS: TestRotateRootCredentials_error/read-fail (0.00s) --- PASS: TestRotateRootCredentials_error/no-change (0.00s) --- PASS: TestRotateRootCredentials_error/no-post (0.00s) --- PASS: TestRotateRootCredentials_error/no-get (0.00s) === RUN TestStaticRoleCreate/error === RUN TestStaticRoleCreate/error/username === PAUSE TestStaticRoleCreate/error/username === RUN TestStaticRoleCreate/error/without-cloud === PAUSE TestStaticRoleCreate/error/without-cloud === CONT TestStaticRoleCreate/error/username === CONT TestStaticRoleCreate/error/without-cloud === RUN TestStaticRoleCreate/not-existing-cloud === PAUSE TestStaticRoleCreate/not-existing-cloud === RUN TestStaticRoleCreate/save-store-err === PAUSE TestStaticRoleCreate/save-store-err === CONT TestStaticRoleCreate/not-existing-cloud === CONT TestStaticRoleCreate/save-store-err --- PASS: TestStaticRoleCreate (0.01s) --- PASS: TestStaticRoleCreate/ok (0.00s) --- PASS: TestStaticRoleCreate/ok/token (0.00s) --- PASS: TestStaticRoleCreate/ok/rotation_duration (0.00s) --- PASS: TestStaticRoleCreate/ok/password (0.00s) --- PASS: TestStaticRoleCreate/ok/endpoint-override (0.00s) --- PASS: TestStaticRoleCreate/error (0.00s) --- PASS: TestStaticRoleCreate/error/username (0.00s) --- PASS: TestStaticRoleCreate/error/without-cloud (0.00s) --- PASS: TestStaticRoleCreate/save-store-err (0.00s) --- PASS: TestStaticRoleCreate/not-existing-cloud (0.00s) PASS ok github.com/opentelekomcloud/vault-plugin-secrets-openstack/openstack 0.404s ? github.com/opentelekomcloud/vault-plugin-secrets-openstack/openstack/fixtures [no test files] Process finished with the exit code 0 Reviewed-by: Aloento <None> Reviewed-by: Anton Kachurin <None> Reviewed-by: Artem Lifshits <None>
1 parent 474d01e commit 384f556

File tree

9 files changed

+826
-118
lines changed

9 files changed

+826
-118
lines changed

acceptance/static_creds_test.go

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
//go:build acceptance
2+
// +build acceptance
3+
4+
package acceptance
5+
6+
import (
7+
"fmt"
8+
"github.com/gophercloud/gophercloud"
9+
"github.com/gophercloud/gophercloud/openstack/identity/v3/roles"
10+
"github.com/gophercloud/gophercloud/openstack/identity/v3/users"
11+
"github.com/opentelekomcloud/vault-plugin-secrets-openstack/openstack"
12+
"github.com/opentelekomcloud/vault-plugin-secrets-openstack/openstack/fixtures"
13+
"github.com/stretchr/testify/require"
14+
"net/http"
15+
"testing"
16+
)
17+
18+
type testStaticCase struct {
19+
cloud string
20+
projectID string
21+
domainID string
22+
secretType string
23+
username string
24+
extensions map[string]interface{}
25+
}
26+
27+
func (p *PluginTest) TestStaticCredsLifecycle() {
28+
t := p.T()
29+
30+
cloud := openstackCloudConfig(t)
31+
require.NotEmpty(t, cloud)
32+
33+
client, aux := openstackClient(t)
34+
35+
userRoleName := "member"
36+
allRoles := getAllRoles(t, client)
37+
38+
dataCloud := map[string]interface{}{
39+
"auth_url": cloud.AuthURL,
40+
"username": cloud.Username,
41+
"password": cloud.Password,
42+
"user_domain_name": cloud.UserDomainName,
43+
}
44+
45+
cases := map[string]testStaticCase{
46+
"user_password": {
47+
cloud: cloud.Name,
48+
projectID: aux.ProjectID,
49+
domainID: aux.DomainID,
50+
username: "static-test-1",
51+
secretType: "password",
52+
},
53+
"user_token": {
54+
cloud: cloud.Name,
55+
projectID: aux.ProjectID,
56+
domainID: aux.DomainID,
57+
username: "static-test-2",
58+
secretType: "token",
59+
extensions: map[string]interface{}{
60+
"identity_api_version": "3",
61+
},
62+
},
63+
}
64+
65+
for name, data := range cases {
66+
t.Run(name, func(t *testing.T) {
67+
data := data
68+
69+
roleName := openstack.RandomString(openstack.NameDefaultSet, 4)
70+
71+
userId := userSetup(t, client, data, aux, allRoles[userRoleName].ID)
72+
t.Cleanup(func() {
73+
require.NoError(t, users.Delete(client, userId).ExtractErr())
74+
})
75+
76+
resp, err := p.vaultDo(
77+
http.MethodPost,
78+
cloudURL(cloudName),
79+
dataCloud,
80+
)
81+
require.NoError(t, err)
82+
assertStatusCode(t, http.StatusNoContent, resp)
83+
84+
resp, err = p.vaultDo(
85+
http.MethodPost,
86+
staticRoleURL(roleName),
87+
cloudToStaticRoleMap(data),
88+
)
89+
require.NoError(t, err)
90+
assertStatusCode(t, http.StatusNoContent, resp)
91+
92+
resp, err = p.vaultDo(
93+
http.MethodGet,
94+
staticRoleURL(roleName),
95+
nil,
96+
)
97+
require.NoError(t, err)
98+
assertStatusCode(t, http.StatusOK, resp)
99+
100+
resp, err = p.vaultDo(
101+
http.MethodGet,
102+
staticCredsURL(roleName),
103+
nil,
104+
)
105+
require.NoError(t, err)
106+
assertStatusCode(t, http.StatusOK, resp)
107+
108+
resp, err = p.vaultDo(
109+
http.MethodDelete,
110+
staticRoleURL(roleName),
111+
nil,
112+
)
113+
require.NoError(t, err)
114+
assertStatusCode(t, http.StatusNoContent, resp)
115+
116+
resp, err = p.vaultDo(
117+
http.MethodDelete,
118+
cloudURL(cloudName),
119+
nil,
120+
)
121+
require.NoError(t, err)
122+
assertStatusCode(t, http.StatusNoContent, resp)
123+
})
124+
}
125+
}
126+
127+
func staticCredsURL(roleName string) string {
128+
return fmt.Sprintf("/v1/openstack/static-creds/%s", roleName)
129+
}
130+
131+
func cloudToStaticRoleMap(data testStaticCase) map[string]interface{} {
132+
return fixtures.SanitizedMap(map[string]interface{}{
133+
"cloud": data.cloud,
134+
"project_id": data.projectID,
135+
"domain_id": data.domainID,
136+
"secret_type": data.secretType,
137+
"username": data.username,
138+
"extensions": data.extensions,
139+
})
140+
}
141+
142+
func getAllRoles(t *testing.T, client *gophercloud.ServiceClient) map[string]roles.Role {
143+
rolePages, err := roles.List(client, nil).AllPages()
144+
require.NoError(t, err)
145+
146+
roleList, err := roles.ExtractRoles(rolePages)
147+
require.NoError(t, err)
148+
149+
result := make(map[string]roles.Role, len(roleList))
150+
151+
for _, role := range roleList {
152+
result[role.Name] = role
153+
}
154+
155+
return result
156+
}
157+
158+
func userSetup(t *testing.T, client *gophercloud.ServiceClient, data testStaticCase, aux *AuxiliaryData, roleID string) string {
159+
createUserOpts := users.CreateOpts{
160+
Name: data.username,
161+
Description: "Static user",
162+
DefaultProjectID: aux.ProjectID,
163+
DomainID: aux.DomainID,
164+
Password: openstack.RandomString(openstack.PwdDefaultSet, 16),
165+
}
166+
user, err := users.Create(client, createUserOpts).Extract()
167+
require.NoError(t, err)
168+
169+
assignOpts := roles.AssignOpts{
170+
UserID: user.ID,
171+
ProjectID: aux.ProjectID,
172+
}
173+
174+
err = roles.Assign(client, roleID, assignOpts).ExtractErr()
175+
require.NoError(t, err)
176+
177+
return user.ID
178+
}

acceptance/static_roles_test.go

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"time"
1111

1212
"github.com/gophercloud/gophercloud/acceptance/tools"
13+
"github.com/gophercloud/gophercloud/openstack/identity/v3/users"
1314
"github.com/hashicorp/vault/sdk/helper/jsonutil"
1415
"github.com/opentelekomcloud/vault-plugin-secrets-openstack/openstack"
1516
"github.com/stretchr/testify/assert"
@@ -23,7 +24,6 @@ type staticRoleData struct {
2324
ProjectID string `json:"project_id"`
2425
ProjectName string `json:"project_name"`
2526
Extensions map[string]interface{} `json:"extensions"`
26-
Root bool `json:"root"`
2727
SecretType string `json:"secret_type"`
2828
Username string `json:"username"`
2929
}
@@ -42,17 +42,40 @@ func extractStaticRoleData(t *testing.T, resp *http.Response) *staticRoleData {
4242
func (p *PluginTest) TestStaticRoleLifecycle() {
4343
t := p.T()
4444

45-
cloud := &openstack.OsCloud{
46-
Name: openstack.RandomString(openstack.NameDefaultSet, 10),
47-
AuthURL: "https://example.com/v3",
48-
UserDomainName: openstack.RandomString(openstack.NameDefaultSet, 10),
49-
Username: openstack.RandomString(openstack.NameDefaultSet, 10),
50-
Password: openstack.RandomString(openstack.PwdDefaultSet, 10),
51-
UsernameTemplate: "u-{{ .RoleName }}-{{ random 4 }}",
45+
cloud := openstackCloudConfig(t)
46+
require.NotEmpty(t, cloud)
47+
48+
client, aux := openstackClient(t)
49+
50+
dataCloud := map[string]interface{}{
51+
"auth_url": cloud.AuthURL,
52+
"username": cloud.Username,
53+
"password": cloud.Password,
54+
"user_domain_name": cloud.UserDomainName,
5255
}
53-
p.makeCloud(cloud)
5456

55-
data := expectedStaticRoleData(cloud.Name)
57+
resp, err := p.vaultDo(
58+
http.MethodPost,
59+
cloudURL(cloudName),
60+
dataCloud,
61+
)
62+
require.NoError(t, err)
63+
assert.Equal(t, http.StatusNoContent, resp.StatusCode, readJSONResponse(t, resp))
64+
65+
createUserOpts := users.CreateOpts{
66+
Name: "vault-test",
67+
Description: "Static user",
68+
DomainID: aux.DomainID,
69+
Password: openstack.RandomString(openstack.PwdDefaultSet, 16),
70+
}
71+
user, err := users.Create(client, createUserOpts).Extract()
72+
require.NoError(t, err)
73+
74+
t.Cleanup(func() {
75+
require.NoError(t, users.Delete(client, user.ID).ExtractErr())
76+
})
77+
78+
data := expectedStaticRoleData(cloud.Name, aux)
5679
roleName := "test-write"
5780
t.Run("WriteRole", func(t *testing.T) {
5881
resp, err := p.vaultDo(
@@ -74,12 +97,10 @@ func (p *PluginTest) TestStaticRoleLifecycle() {
7497

7598
expected := &staticRoleData{
7699
Cloud: data["cloud"].(string),
77-
TTL: data["ttl"].(time.Duration),
78100
RotationDuration: data["rotation_duration"].(time.Duration),
79101
ProjectID: data["project_id"].(string),
80102
ProjectName: data["project_name"].(string),
81103
Extensions: data["extensions"].(map[string]interface{}),
82-
Root: data["root"].(bool),
83104
SecretType: data["secret_type"].(string),
84105
Username: data["username"].(string),
85106
}
@@ -112,17 +133,17 @@ func staticRoleURL(name string) string {
112133
return fmt.Sprintf("/v1/openstack/static-role/%s", name)
113134
}
114135

115-
func expectedStaticRoleData(cloudName string) map[string]interface{} {
136+
func expectedStaticRoleData(cloudName string, aux *AuxiliaryData) map[string]interface{} {
116137
expectedMap := map[string]interface{}{
117138
"cloud": cloudName,
118139
"ttl": time.Hour / time.Second,
119140
"rotation_duration": time.Hour / time.Second,
120-
"project_id": "",
141+
"project_id": aux.ProjectID,
142+
"domain_id": aux.DomainID,
121143
"project_name": tools.RandomString("p", 5),
122144
"extensions": map[string]interface{}{},
123-
"root": false,
124145
"secret_type": "password",
125-
"username": "static-test",
146+
"username": "vault-test",
126147
}
127148
return expectedMap
128149
}

doc/source/api.md

Lines changed: 71 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -440,10 +440,6 @@ created. If the role exists, it will be updated with the new attributes.
440440

441441
- `username` `(string: <required>)` - Specifies username of user managed by the static role.
442442

443-
- `root` `(bool: <optional>)` - Specifies whenever to use the root user as a role actor.
444-
If set to `true`, `secret_type` can't be set to `password`.
445-
If set to `true`, `ttl` value is ignored.
446-
447443
- `rotation_duration` `(string: "1h")` - Specifies password rotation time value for the static user as a
448444
string duration with time suffix.
449445

@@ -492,17 +488,6 @@ $ curl \
492488
}
493489
```
494490

495-
#### Creating a static role using root user
496-
497-
```json
498-
{
499-
"cloud": "example-cloud",
500-
"root": true,
501-
"project_name": "test",
502-
"username": "test-user"
503-
}
504-
```
505-
506491
#### Creating a static role for password-based access
507492

508493
```json
@@ -585,3 +570,74 @@ $ curl \
585570
}
586571
}
587572
```
573+
574+
## Read Static Role Credentials
575+
576+
This endpoint returns user credentials based on the named static role.
577+
578+
| Method | Path |
579+
|:---------|:--------------------------------|
580+
| `GET` | `/openstack/static-creds/:name` |
581+
582+
### Parameters
583+
584+
- `name` (`string: <required>`) - Specifies the name of the role to return credentials against.
585+
586+
### Sample Request
587+
588+
```shell
589+
$ curl \
590+
--header "X-Vault-Token: ..." \
591+
http://127.0.0.1:8200/v1/openstack/static-creds/example-role
592+
```
593+
594+
### Sample Responses
595+
596+
#### Credentials for the token-type static role
597+
598+
```json
599+
{
600+
"data": {
601+
"auth": {
602+
"auth_url": "https://example.com/v3/",
603+
"token": "gAAAAABiA6Xfybumdwd84qvMDJKYOaauWxSvG9ItslSr5w0Mb...",
604+
"project_name": "test",
605+
"project_domain_id": "Default"
606+
},
607+
"auth_type": "token"
608+
}
609+
}
610+
```
611+
612+
#### Credentials for the password-type static role with project scope
613+
614+
```json
615+
{
616+
"data": {
617+
"auth": {
618+
"auth_url": "https://example.com/v3/",
619+
"username": "admin",
620+
"password": "RcigTiYrJjVmEkrV71Cd",
621+
"project_name": "test",
622+
"project_domain_id": "Default"
623+
},
624+
"auth_type": "password"
625+
}
626+
}
627+
```
628+
629+
#### Credentials for the password-type static role with domain scope
630+
631+
```json
632+
{
633+
"data": {
634+
"auth": {
635+
"auth_url": "https://example.com/v3/",
636+
"username": "admin",
637+
"password": "RcigTiYrJjVmEkrV71Cd",
638+
"user_domain_id": "Default"
639+
},
640+
"auth_type": "password"
641+
}
642+
}
643+
```

openstack/backend.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ func Factory(ctx context.Context, conf *logical.BackendConfig) (logical.Backend,
5454
b.pathStaticRole(),
5555
b.pathRotateRoot(),
5656
b.pathCreds(),
57+
b.pathStaticCreds(),
5758
},
5859
Secrets: []*framework.Secret{
5960
secretToken(b),

0 commit comments

Comments
 (0)