From af43e999b695bed9ebb09b79db6f5269329ef779 Mon Sep 17 00:00:00 2001 From: Rodion Gyrbu Date: Mon, 23 May 2022 22:51:41 +0300 Subject: [PATCH] Add `project`/`domain` in `root_token` and remove `password` from `cloud` response (#84) Add `project`/`domain` in `root_token` and remove `password` from `cloud` response Description Remove password from cloud response Add project_name/id and domain_name/id in token root token reponse 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_password === RUN TestPlugin/TestCredsLifecycle/root_token === RUN TestPlugin/TestCredsLifecycle/user_token === RUN TestPlugin/TestInfo === RUN TestPlugin/TestRoleLifecycle roles_test.go:53: Cloud with name `y96wtu4gft` 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 `y96wtu4gft` has been removed === RUN TestPlugin/TestRootRotate rotate_test.go:65: Cloud with name `default1` was created rotate_test.go:68: Cloud with name `saf4` was created plugin_test.go:337: Cloud with name `saf4` has been removed plugin_test.go:337: Cloud with name `default1` has been removed --- PASS: TestPlugin (11.48s) --- PASS: TestPlugin/TestCloudLifecycle (0.39s) --- PASS: TestPlugin/TestCloudLifecycle/WriteCloud (0.38s) --- 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.01s) --- PASS: TestPlugin/TestCloudLifecycle/DeleteCloud (0.00s) --- PASS: TestPlugin/TestCredsLifecycle (4.83s) --- PASS: TestPlugin/TestCredsLifecycle/user_password (1.38s) --- PASS: TestPlugin/TestCredsLifecycle/root_token (0.66s) --- PASS: TestPlugin/TestCredsLifecycle/user_token (1.90s) --- PASS: TestPlugin/TestInfo (0.00s) --- PASS: TestPlugin/TestRoleLifecycle (0.02s) --- 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.43s) PASS ok github.com/opentelekomcloud/vault-plugin-secrets-openstack/acceptance 11.490s Reviewed-by: Anton Sidelnikov --- README.md | 17 +++++--- acceptance/cloud_test.go | 1 - doc/source/api.md | 3 +- openstack/path_cloud.go | 1 - openstack/path_cloud_test.go | 1 - openstack/path_creds.go | 75 ++++++++++++++++++++++++------------ 6 files changed, 63 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index 543299f..403f8ec 100644 --- a/README.md +++ b/README.md @@ -80,15 +80,20 @@ You must have a Vault server already running, unsealed, and authenticated. ```sh $ vault read /openstack/creds/example-role - + Key Value --- ----- - lease_id openstack/creds/example-role/Kuma41Qu8s1k5f4AZ8PUmDxE - lease_duration 1h + lease_id openstack/creds/example-role/v7I5mxix3iCpkdGYDelNmKdo + lease_duration 24h lease_renewable false - auth_url https://127.0.0.1/v3/ - expires_at 2022-04-19 02:03:36 +0000 UTC - token gAAAAABiXW-4r2Ofy4s4-oFlnbNgIrqONkmIHPnE... + auth map[auth_url:https://127.0.0.1/v3/ project_domain_name:mydomain project_name:myproject token:MIIF-QYJKoZIhvcNAQcCoIIF7jCCBeoCAQExDTALBglghkgBZQMEAgEwggOCBgkqhkiG9w0BBwGgggNzBIIDb3sidG + 9rZW4iOnsiZXhwaXJlc19hdCI6IjIwMjItMDUtMjRUMTc6MTU6NDQuNTI4MDAwWiIsIm1ldGhvZHMiOlsicGFzc3dvcmQiXSwiY2F0YWxvZyI6W10sInJvbGVzIjpbeyJuYW1lIjoic2VydmVyX2FkbSIsImlkIjoiMCJ9LHsibmFtZSI6InRlX2FkbWluIiwiaWQiOiIwIn0seyJuYW1lIjoib3BfZ2F0ZWRfY2 + NlX3N3aXRjaCIsImlkIjoiMCJ9LHsibmFtZSIwiaWQiOiIwIn1dLCJwcm9qZWN0Ijp7ImRvbWFpbiI6eyJ4ZG9tYWluX3R5cGUiOiJUU0kiLCJuYW1lIjoiT1RDMDAwMDAwMDAwMDEwMDAwMDA0NDciLCJpZCI6ImZhZjcyZTg1MWMxZTQ4MzE5Mjk2ZjE4MTgxOGYxNzZhIiwieGRvbWFpbl9pZCI6IjAwMD + AwMDAwMDAxMDAwMDAwNDQ3In0sIm5hbWUiOiJlCwYDVQQHDARCb25uMRwwGgYDVQQKDBNEZXV0c2NoZSBUZWxla29tIEFHMTcwNQYDVQQLDC5ULVN5c3RlbXMgUFUgUHVibGljIENsb3VkIC0gT3BlbiBUZWxla29tIENsb3VkMRMwEQYDVQQDDApjYS5pYW0ucGtpAg + kAi0NlULiz2iIwCwYJYIZIAWUDBAIBMA0GCSqGSIb3DQEBAQUABIIBgBtmvHm0ChAl0kppzoaVJgYSovI0ujP6Srk7sDrDVO7auks+dQ-D1yb4Xh398mn1VNs0i4e98Bp-AQnwb3N-uZcUnbNHAUg2uRUoWUBmVs8oXszkGJYRK6Kf+BgGE5GqS4KgE2e8ob96xPGRQ5WdKMjYzb9nAz37sUsvy-jz70anyhKoWW + B55kYVDyCn4JYh7-ivKrfaHdNY9GSebskw0zqAeMr2Lr4DZyZcr6mor88p1MnT+kz028qcxkrHBKiHQ0wt8YWUfAFD7RV-b97ZkBBSeEMs3ai1zMbYWXtIzztAWZLn52l+vstKiae8hXoE4HIpkMOD+fTyj2z6gN7X6xfvfBIZC2mSOQ2PAiTls2JTrcDVEo3eCI1vgvKrFdY52yDGmb3lHBITPPya0ztvjFrdNv59Gdx8-rxf1fr1htXRhyaMOBiaPDGVkUtjwqC9Zjm3fve5Z5A6UQurBm8xDjtRWjnFB5kAQ708adpCUHJAdxand3Mf-Md4UysLVSf4Ug==] + auth_type token + ``` ### Developing diff --git a/acceptance/cloud_test.go b/acceptance/cloud_test.go index 3f56e5d..2eab1eb 100644 --- a/acceptance/cloud_test.go +++ b/acceptance/cloud_test.go @@ -70,7 +70,6 @@ func (p *PluginTest) TestCloudLifecycle() { AuthURL: data["auth_url"].(string), UserDomainName: data["user_domain_name"].(string), Username: data["username"].(string), - Password: data["password"].(string), UsernameTemplate: openstack.DefaultUsernameTemplate, PasswordPolicy: data["password_policy"].(string), } diff --git a/doc/source/api.md b/doc/source/api.md index 15966de..eadb9bc 100644 --- a/doc/source/api.md +++ b/doc/source/api.md @@ -75,7 +75,8 @@ $ curl \ { "auth_url": "https://example.com/v3/", "username": "admin", - "user_domain_name": "Default" + "user_domain_name": "Default", + "username_template": "user-{{ .RoleName }}-{{ random 4 }}" } ``` diff --git a/openstack/path_cloud.go b/openstack/path_cloud.go index 26cadf6..16b510b 100644 --- a/openstack/path_cloud.go +++ b/openstack/path_cloud.go @@ -210,7 +210,6 @@ func (b *backend) pathCloudRead(ctx context.Context, r *logical.Request, d *fram "auth_url": cloudConfig.AuthURL, "user_domain_name": cloudConfig.UserDomainName, "username": cloudConfig.Username, - "password": cloudConfig.Password, "username_template": cloudConfig.UsernameTemplate, "password_policy": cloudConfig.PasswordPolicy, }, diff --git a/openstack/path_cloud_test.go b/openstack/path_cloud_test.go index 1df5ce1..13435d8 100644 --- a/openstack/path_cloud_test.go +++ b/openstack/path_cloud_test.go @@ -143,7 +143,6 @@ func TestCloudCreate(t *testing.T) { assert.Equal(t, res.Data["auth_url"], testAuthURL) assert.Equal(t, res.Data["user_domain_name"], testUserDomainName) assert.Equal(t, res.Data["username"], testUsername) - assert.Equal(t, res.Data["password"], testPassword1) }) t.Run("Delete", func(t *testing.T) { diff --git a/openstack/path_creds.go b/openstack/path_creds.go index e60bc7e..21c7fc6 100644 --- a/openstack/path_creds.go +++ b/openstack/path_creds.go @@ -105,12 +105,17 @@ func getRootCredentials(client *gophercloud.ServiceClient, opts *credsOpts) (*lo return nil, err } + authResponse := &authResponseData{ + AuthURL: opts.Config.AuthURL, + Token: token.ID, + DomainName: opts.Config.UserDomainName, + } + data := map[string]interface{}{ - "auth": map[string]interface{}{ - "auth_url": opts.Config.AuthURL, - "token": token.ID, - "user_domain_name": opts.Config.UserDomainName, - }, + "auth": formAuthResponse( + opts.Role, + authResponse, + ), "auth_type": "token", } secret := &logical.Secret{ @@ -159,14 +164,16 @@ func getTmpUserCredentials(client *gophercloud.ServiceClient, opts *credsOpts) ( return nil, err } + authResponse := &authResponseData{ + AuthURL: opts.Config.AuthURL, + Token: token.ID, + DomainID: user.DomainID, + } + data = map[string]interface{}{ "auth": formAuthResponse( opts.Role, - "", - "", - token.ID, - opts.Config.AuthURL, - user.DomainID, + authResponse, ), "auth_type": "token", } @@ -177,14 +184,16 @@ func getTmpUserCredentials(client *gophercloud.ServiceClient, opts *credsOpts) ( "expires_at": token.ExpiresAt.String(), } case SecretPassword: + authResponse := &authResponseData{ + AuthURL: opts.Config.AuthURL, + Username: user.Name, + Password: password, + DomainID: user.DomainID, + } data = map[string]interface{}{ "auth": formAuthResponse( opts.Role, - user.Name, - password, - "", - opts.Config.AuthURL, - user.DomainID, + authResponse, ), "auth_type": "password", } @@ -465,7 +474,16 @@ func getScopeFromRole(role *roleEntry) tokens.Scope { return scope } -func formAuthResponse(role *roleEntry, username, password, token, authURL, domainID string) map[string]interface{} { +type authResponseData struct { + AuthURL string + Username string + Password string + Token string + DomainID string + DomainName string +} + +func formAuthResponse(role *roleEntry, authResponse *authResponseData) map[string]interface{} { var auth map[string]interface{} switch { @@ -474,24 +492,31 @@ func formAuthResponse(role *roleEntry, username, password, token, authURL, domai "project_id": role.ProjectID, } case role.ProjectName != "": - auth = map[string]interface{}{ - "project_name": role.ProjectName, - "project_domain_id": domainID, + if role.Root { + auth = map[string]interface{}{ + "project_name": role.ProjectName, + "project_domain_name": authResponse.DomainName, + } + } else { + auth = map[string]interface{}{ + "project_name": role.ProjectName, + "project_domain_id": authResponse.DomainID, + } } default: auth = map[string]interface{}{ - "user_domain_id": domainID, + "user_domain_id": authResponse.DomainID, } } - if token != "" { - auth["token"] = token + if authResponse.Token != "" { + auth["token"] = authResponse.Token } else { - auth["username"] = username - auth["password"] = password + auth["username"] = authResponse.Username + auth["password"] = authResponse.Password } - auth["auth_url"] = authURL + auth["auth_url"] = authResponse.AuthURL return auth }