Skip to content

Commit dcb9441

Browse files
authored
Fix issue with cached outdated token in client (#90)
Fix issue with cached outdated `token` in `client` Description Reinit client to prevent use of outdated token Refers to: #87 Tests performed 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/root_token === RUN TestPlugin/TestCredsLifecycle/user_token === RUN TestPlugin/TestCredsLifecycle/user_password === RUN TestPlugin/TestInfo === RUN TestPlugin/TestRoleLifecycle roles_test.go:53: Cloud with name `jsrus8zg5u` 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 `jsrus8zg5u` has been removed === RUN TestPlugin/TestRootRotate rotate_test.go:65: Cloud with name `default1` was created rotate_test.go:68: Cloud with name `qj6s` was created plugin_test.go:337: Cloud with name `qj6s` has been removed plugin_test.go:337: Cloud with name `default1` has been removed --- PASS: TestPlugin (14.02s) --- PASS: TestPlugin/TestCloudLifecycle (0.36s) --- PASS: TestPlugin/TestCloudLifecycle/WriteCloud (0.36s) --- 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 (8.31s) --- PASS: TestPlugin/TestCredsLifecycle/root_token (2.05s) --- PASS: TestPlugin/TestCredsLifecycle/user_token (3.27s) --- PASS: TestPlugin/TestCredsLifecycle/user_password (2.14s) --- 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.64s) PASS ok github.com/opentelekomcloud/vault-plugin-secrets-openstack/acceptance 14.030s 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/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-user-post --- PASS: TestCredentialsRead_error/no-user-post (0.00s) === RUN TestCredentialsRead_error/no-users-token-post --- PASS: TestCredentialsRead_error/no-users-token-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/admin === PAUSE TestRoleCreate/ok/admin === CONT TestRoleCreate/ok/admin --- PASS: TestRoleCreate/ok/admin (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/error --- PASS: TestRoleCreate/error (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/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/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-get --- PASS: TestRotateRootCredentials_error/no-get (0.00s) === RUN TestRotateRootCredentials_error/no-change --- PASS: TestRotateRootCredentials_error/no-change (0.00s) === RUN TestRotateRootCredentials_error/no-post --- PASS: TestRotateRootCredentials_error/no-post (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: Anton Sidelnikov <None>
1 parent 18316aa commit dcb9441

File tree

3 files changed

+49
-32
lines changed

3 files changed

+49
-32
lines changed

acceptance/creds_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,14 @@ func (p *PluginTest) TestCredsLifecycle() {
109109
require.NoError(t, err)
110110
assert.Equal(t, http.StatusOK, resp.StatusCode, readJSONResponse(t, resp))
111111

112+
resp, err = p.vaultDo(
113+
http.MethodPost,
114+
"/v1/sys/leases/revoke-force/openstack/creds",
115+
nil,
116+
)
117+
require.NoError(t, err)
118+
assertStatusCode(t, http.StatusNoContent, resp)
119+
112120
resp, err = p.vaultDo(
113121
http.MethodDelete,
114122
roleURL(roleName),

openstack/backend.go

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"fmt"
66
"sync"
7+
"time"
78

89
"github.com/gophercloud/gophercloud"
910
"github.com/gophercloud/gophercloud/openstack"
@@ -21,8 +22,9 @@ const (
2122
type sharedCloud struct {
2223
name string
2324

24-
client *gophercloud.ServiceClient
25-
lock sync.Mutex
25+
client *gophercloud.ServiceClient
26+
expiresAt time.Time
27+
lock sync.Mutex
2628

2729
passwords *Passwords
2830
}
@@ -87,20 +89,14 @@ func (c *sharedCloud) getClient(ctx context.Context, s logical.Storage) (*gopher
8789
defer c.lock.Unlock()
8890

8991
if c.client != nil {
90-
valid, err := tokens.Validate(c.client, c.client.Token())
91-
if err != nil {
92-
return nil, err
92+
diff := time.Since(c.expiresAt)
93+
if diff.Seconds() <= -120 {
94+
return c.client, nil
9395
}
96+
}
9497

95-
if !valid {
96-
if err := c.initClient(ctx, s); err != nil {
97-
return nil, err
98-
}
99-
}
100-
} else {
101-
if err := c.initClient(ctx, s); err != nil {
102-
return nil, err
103-
}
98+
if err := c.initClient(ctx, s); err != nil {
99+
return nil, err
104100
}
105101

106102
return c.client, nil
@@ -135,6 +131,13 @@ func (c *sharedCloud) initClient(ctx context.Context, s logical.Storage) error {
135131
return fmt.Errorf("error creating service client: %w", err)
136132
}
137133

134+
tokenResponse := tokens.Get(sClient, sClient.Token())
135+
token, err := tokenResponse.ExtractToken()
136+
if err != nil {
137+
return err
138+
}
139+
140+
c.expiresAt = token.ExpiresAt
138141
c.client = sClient
139142

140143
return nil

openstack/backend_test.go

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"net/http"
77
"sync"
88
"testing"
9+
"time"
910

1011
"github.com/gophercloud/gophercloud"
1112
"github.com/gophercloud/gophercloud/acceptance/tools"
@@ -91,20 +92,11 @@ func TestSharedCloud_client(t *testing.T) {
9192

9293
t.Run("existing-client", func(t *testing.T) {
9394
cloud := &sharedCloud{
94-
client: thClient.ServiceClient(),
95-
lock: sync.Mutex{},
95+
client: thClient.ServiceClient(),
96+
expiresAt: time.Now().Add(time.Hour),
97+
lock: sync.Mutex{},
9698
}
9799

98-
th.Mux.HandleFunc("/auth/tokens", func(w http.ResponseWriter, r *http.Request) {
99-
th.TestMethod(t, r, "HEAD")
100-
th.TestHeaderUnset(t, r, "Content-Type")
101-
th.TestHeader(t, r, "Accept", "application/json")
102-
th.TestHeader(t, r, "X-Auth-Token", thClient.TokenID)
103-
th.TestHeader(t, r, "X-Subject-Token", thClient.TokenID)
104-
105-
w.WriteHeader(http.StatusNoContent)
106-
})
107-
108100
client, err := cloud.getClient(context.Background(), s)
109101
assert.NoError(t, err)
110102
assert.Equal(t, testClient, client)
@@ -114,12 +106,14 @@ func TestSharedCloud_client(t *testing.T) {
114106
authURL := testClient.Endpoint + "v3"
115107

116108
th.Mux.HandleFunc("/v3/auth/tokens", func(w http.ResponseWriter, r *http.Request) {
117-
th.TestMethod(t, r, "POST")
118-
th.TestHeader(t, r, "Content-Type", "application/json")
119-
th.TestHeader(t, r, "Accept", "application/json")
120-
121-
w.WriteHeader(http.StatusCreated)
122-
_, _ = fmt.Fprintf(w, `
109+
switch r.Method {
110+
case "POST":
111+
th.TestMethod(t, r, "POST")
112+
th.TestHeader(t, r, "Content-Type", "application/json")
113+
th.TestHeader(t, r, "Accept", "application/json")
114+
115+
w.WriteHeader(http.StatusCreated)
116+
_, _ = fmt.Fprintf(w, `
123117
{
124118
"token": {
125119
"expires_at": "2014-10-02T13:45:00.000000Z",
@@ -142,6 +136,18 @@ func TestSharedCloud_client(t *testing.T) {
142136
}
143137
}
144138
`, authURL)
139+
case "GET":
140+
th.TestMethod(t, r, "GET")
141+
142+
w.WriteHeader(http.StatusOK)
143+
_, _ = fmt.Fprint(w, `
144+
{
145+
"token": {
146+
"expires_at": "2023-10-02T13:45:00.000000Z"
147+
}
148+
}
149+
`)
150+
}
145151
})
146152

147153
cloud := &sharedCloud{name: tools.RandomString("cl", 5)}

0 commit comments

Comments
 (0)