Skip to content

Commit 0ed56a9

Browse files
committed
Add integration test to check token timeouts
NOTE: because we impose a minimum timeout of 5min (to keep writes limited to a reasonable amount) we need to special case out this test so that it is allowed to run for more than 5 minutes. Signed-off-by: Simo Sorce <[email protected]>
1 parent aa34658 commit 0ed56a9

File tree

2 files changed

+211
-1
lines changed

2 files changed

+211
-1
lines changed
+201
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
package integration
2+
3+
import (
4+
"testing"
5+
"time"
6+
7+
kerrors "k8s.io/apimachinery/pkg/api/errors"
8+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
9+
restclient "k8s.io/client-go/rest"
10+
11+
"github.com/openshift/origin/pkg/cmd/util/tokencmd"
12+
oauthapi "github.com/openshift/origin/pkg/oauth/apis/oauth"
13+
oauthvalidation "github.com/openshift/origin/pkg/oauth/apis/oauth/validation"
14+
oauthclient "github.com/openshift/origin/pkg/oauth/generated/internalclientset/typed/oauth/internalversion"
15+
userclient "github.com/openshift/origin/pkg/user/generated/internalclientset/typed/user/internalversion"
16+
testutil "github.com/openshift/origin/test/util"
17+
testserver "github.com/openshift/origin/test/util/server"
18+
)
19+
20+
func testTokenWorks(t *testing.T, anonConfig *restclient.Config, token string, expectTimeout bool) {
21+
// Make sure we can use the token, and it represents who we expect
22+
userConfig := *anonConfig
23+
userConfig.BearerToken = token
24+
userClient, err := userclient.NewForConfig(&userConfig)
25+
if err != nil {
26+
t.Fatal(err)
27+
}
28+
29+
user, err := userClient.Users().Get("~", metav1.GetOptions{})
30+
if err != nil {
31+
if expectTimeout && kerrors.IsUnauthorized(err) {
32+
return
33+
}
34+
t.Errorf("Unexpected error getting user ~: %v", err)
35+
}
36+
if user.Name != "username" {
37+
t.Errorf("Expected username as the user, got %v", user)
38+
}
39+
}
40+
41+
func testTimeoutOAuthFlows(t *testing.T, tokens oauthclient.OAuthAccessTokenInterface, oauthClient *oauthapi.OAuthClient, anonConfig *restclient.Config, expectedTimeout int32) string {
42+
var lastToken string
43+
44+
// token flow followed by code flow
45+
for _, tokenFlow := range []bool{true, false} {
46+
tokenOpts := tokencmd.NewRequestTokenOptions(anonConfig, nil, "username", "password", tokenFlow)
47+
if err := tokenOpts.SetDefaultOsinConfig(); err != nil {
48+
t.Fatal(err)
49+
}
50+
tokenOpts.OsinConfig.ClientId = oauthClient.Name
51+
tokenOpts.OsinConfig.RedirectUrl = oauthClient.RedirectURIs[0]
52+
token, err := tokenOpts.RequestToken()
53+
if err != nil {
54+
t.Fatal(err)
55+
}
56+
57+
// Make sure the token exists with the overridden time
58+
tokenObj, err := tokens.Get(token, metav1.GetOptions{})
59+
if err != nil {
60+
t.Fatal(err)
61+
}
62+
if tokenObj.InactivityTimeoutSeconds != expectedTimeout {
63+
t.Errorf("Token flow=%v, expected timeout of %d, got %#v",
64+
tokenFlow, expectedTimeout, tokenObj.InactivityTimeoutSeconds)
65+
}
66+
67+
testTokenWorks(t, anonConfig, token, false)
68+
69+
lastToken = token
70+
}
71+
72+
return lastToken
73+
}
74+
75+
func TestOAuthTimeout(t *testing.T) {
76+
testTimeout := int32(oauthvalidation.MinimumInactivityTimeoutSeconds * 2)
77+
masterOptions, err := testserver.DefaultMasterOptions()
78+
if err != nil {
79+
t.Fatal(err)
80+
}
81+
masterOptions.OAuthConfig.TokenConfig.AccessTokenInactivityTimeoutSeconds = &testTimeout
82+
defer testserver.CleanupMasterEtcd(t, masterOptions)
83+
84+
clusterAdminKubeConfig, err := testserver.StartConfiguredMaster(masterOptions)
85+
if err != nil {
86+
t.Fatal(err)
87+
}
88+
89+
clientConfig, err := testutil.GetClusterAdminClientConfig(clusterAdminKubeConfig)
90+
if err != nil {
91+
t.Fatal(err)
92+
}
93+
oauthClient := oauthclient.NewForConfigOrDie(clientConfig)
94+
95+
// Use the server and CA info
96+
anonConfig := restclient.AnonymousClientConfig(clientConfig)
97+
98+
{
99+
client, err := oauthClient.OAuthClients().Create(&oauthapi.OAuthClient{
100+
ObjectMeta: metav1.ObjectMeta{Name: "defaulttimeout"},
101+
RespondWithChallenges: true,
102+
RedirectURIs: []string{"http://localhost"},
103+
GrantMethod: oauthapi.GrantHandlerAuto,
104+
})
105+
if err != nil {
106+
t.Fatal(err)
107+
}
108+
109+
testTimeoutOAuthFlows(t, oauthClient.OAuthAccessTokens(), client, anonConfig, testTimeout)
110+
}
111+
112+
{
113+
client, err := oauthClient.OAuthClients().Create(&oauthapi.OAuthClient{
114+
ObjectMeta: metav1.ObjectMeta{Name: "notimeout"},
115+
RespondWithChallenges: true,
116+
RedirectURIs: []string{"http://localhost"},
117+
AccessTokenInactivityTimeoutSeconds: new(int32),
118+
GrantMethod: oauthapi.GrantHandlerAuto,
119+
})
120+
if err != nil {
121+
t.Fatal(err)
122+
}
123+
124+
testTimeoutOAuthFlows(t, oauthClient.OAuthAccessTokens(), client, anonConfig, 0)
125+
}
126+
127+
// check that we get an error trying to set a client value that is less
128+
// than the allowable minimum
129+
{
130+
invalid := int32(oauthvalidation.MinimumInactivityTimeoutSeconds - 1)
131+
_, err := oauthClient.OAuthClients().Create(&oauthapi.OAuthClient{
132+
ObjectMeta: metav1.ObjectMeta{Name: "notvalid"},
133+
RespondWithChallenges: true,
134+
RedirectURIs: []string{"http://localhost"},
135+
AccessTokenInactivityTimeoutSeconds: &invalid,
136+
GrantMethod: oauthapi.GrantHandlerAuto,
137+
})
138+
if !kerrors.IsInvalid(err) {
139+
t.Errorf("The 'notvalid' test is supposed to be invalid but gave=%v", err)
140+
}
141+
}
142+
143+
{
144+
min := int32(oauthvalidation.MinimumInactivityTimeoutSeconds)
145+
client, err := oauthClient.OAuthClients().Create(&oauthapi.OAuthClient{
146+
ObjectMeta: metav1.ObjectMeta{Name: "mintimeout"},
147+
RespondWithChallenges: true,
148+
RedirectURIs: []string{"http://localhost"},
149+
AccessTokenInactivityTimeoutSeconds: &min,
150+
GrantMethod: oauthapi.GrantHandlerAuto,
151+
})
152+
if err != nil {
153+
t.Fatal(err)
154+
}
155+
156+
token := testTimeoutOAuthFlows(t, oauthClient.OAuthAccessTokens(), client, anonConfig, min)
157+
158+
// wait 50% of timeout time, then try token and see it still work
159+
time.Sleep(time.Duration(min/2) * time.Second)
160+
testTokenWorks(t, anonConfig, token, false)
161+
162+
// Then Ensure the token times out
163+
time.Sleep(time.Duration(min+1) * time.Second)
164+
testTokenWorks(t, anonConfig, token, true)
165+
}
166+
}
167+
168+
func TestOAuthTimeoutNotEnabled(t *testing.T) {
169+
masterConfig, clusterAdminKubeConfig, err := testserver.StartTestMasterAPI()
170+
if err != nil {
171+
t.Fatal(err)
172+
}
173+
defer testserver.CleanupMasterEtcd(t, masterConfig)
174+
175+
clientConfig, err := testutil.GetClusterAdminClientConfig(clusterAdminKubeConfig)
176+
if err != nil {
177+
t.Fatal(err)
178+
}
179+
oauthClient := oauthclient.NewForConfigOrDie(clientConfig)
180+
181+
// Use the server and CA info
182+
anonConfig := restclient.AnonymousClientConfig(clientConfig)
183+
184+
min := int32(oauthvalidation.MinimumInactivityTimeoutSeconds)
185+
client, err := oauthClient.OAuthClients().Create(&oauthapi.OAuthClient{
186+
ObjectMeta: metav1.ObjectMeta{Name: "shorttimeoutthatisignored"},
187+
RespondWithChallenges: true,
188+
RedirectURIs: []string{"http://localhost"},
189+
AccessTokenInactivityTimeoutSeconds: &min,
190+
GrantMethod: oauthapi.GrantHandlerAuto,
191+
})
192+
if err != nil {
193+
t.Fatal(err)
194+
}
195+
196+
token := testTimeoutOAuthFlows(t, oauthClient.OAuthAccessTokens(), client, anonConfig, min)
197+
198+
// ensure the token does not timeout because the feature is not active by default
199+
time.Sleep(time.Duration(min+30) * time.Second)
200+
testTokenWorks(t, anonConfig, token, false)
201+
}

test/integration/runner/runner_test.go

+10-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ import (
2020
)
2121

2222
var timeout = flag.Duration("sub.timeout", 5*time.Minute, "Specify the timeout for each sub test")
23+
var oauthtimeout = flag.Duration("oauth.timeout", 15*time.Minute, "Timeout for the OAuth tests")
24+
var timeoutException = map[string]*time.Duration{
25+
"TestOAuthTimeout": oauthtimeout,
26+
"TestOAuthTimeoutNotEnabled": oauthtimeout,
27+
}
2328

2429
func TestIntegration(t *testing.T) {
2530
executeTests(t, "..", "github.com/openshift/origin/test/integration", 1)
@@ -160,7 +165,11 @@ func runSingleTest(t *testing.T, dir, binaryPath, name string) error {
160165
if testing.Short() {
161166
cmd.Args = append(cmd.Args, "-test.short")
162167
}
163-
cmd.Args = append(cmd.Args, "-test.timeout", (*timeout).String())
168+
if specialTimeout, ok := timeoutException[name]; ok {
169+
cmd.Args = append(cmd.Args, "-test.timeout", (*specialTimeout).String())
170+
} else {
171+
cmd.Args = append(cmd.Args, "-test.timeout", (*timeout).String())
172+
}
164173

165174
out, err := cmd.CombinedOutput()
166175
if err != nil {

0 commit comments

Comments
 (0)