-
Notifications
You must be signed in to change notification settings - Fork 157
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
use library-go config observer for access token inactivity timeout
- Loading branch information
Showing
5 changed files
with
203 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,166 @@ | ||
package e2e | ||
|
||
import ( | ||
"bytes" | ||
"context" | ||
"crypto/tls" | ||
"fmt" | ||
"net/http" | ||
"testing" | ||
"time" | ||
|
||
oauthapi "github.com/openshift/api/oauth/v1" | ||
userapi "github.com/openshift/api/user/v1" | ||
configclient "github.com/openshift/client-go/config/clientset/versioned/typed/config/v1" | ||
oauthclient "github.com/openshift/client-go/oauth/clientset/versioned/typed/oauth/v1" | ||
userclient "github.com/openshift/client-go/user/clientset/versioned/typed/user/v1" | ||
test "github.com/openshift/cluster-kube-apiserver-operator/test/library" | ||
"github.com/stretchr/testify/require" | ||
|
||
corev1 "k8s.io/api/core/v1" | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
) | ||
|
||
const ( | ||
defaultAccessTokenMaxAgeSeconds = 86400 | ||
) | ||
|
||
func TestTokenInactivityTimeout(t *testing.T) { | ||
kubeConfig, err := test.NewClientConfigForTest() | ||
require.NoError(t, err) | ||
|
||
userClient := userclient.NewForConfigOrDie(kubeConfig) | ||
oauthClientClient := oauthclient.NewForConfigOrDie(kubeConfig) | ||
configClient := configclient.NewForConfigOrDie(kubeConfig) | ||
|
||
// Update OAuth cluster config with token inactivity timeout | ||
updateOAuthServerClusterConfigSpec(t, configClient, 300*time.Second) | ||
|
||
// Wait for kube-apiserver pods to start progressing | ||
test.WaitForKubeAPIServerStartProgressing(t, configClient) | ||
|
||
// Wait until all kube-apiserver pods are restarted with new config. | ||
test.WaitForKubeAPIServerClusterOperatorAvailableNotProgressingNotDegraded(t, configClient) | ||
|
||
// Create the user, identity, oauthclient and oauthaccesstoken objects needed for authentication using Bearer tokens. | ||
user := &userapi.User{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Name: "testuser2", | ||
}, | ||
Identities: []string{"htpasswd:testuser2"}, | ||
} | ||
userInfo, err := userClient.Users().Create(context.Background(), user, metav1.CreateOptions{}) | ||
require.NoError(t, err) | ||
defer func() { | ||
if err := userClient.Users().Delete(context.Background(), user.Name, metav1.DeleteOptions{}); err != nil { | ||
t.Logf("%v", err) | ||
} | ||
}() | ||
|
||
identity := &userapi.Identity{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Name: "htpasswd:testuser2", | ||
}, | ||
ProviderName: "htpasswd", | ||
ProviderUserName: user.Name, | ||
User: corev1.ObjectReference{ | ||
Name: userInfo.Name, | ||
UID: userInfo.UID, | ||
}, | ||
} | ||
_, err = userClient.Identities().Create(context.Background(), identity, metav1.CreateOptions{}) | ||
require.NoError(t, err) | ||
defer func() { | ||
if err := userClient.Identities().Delete(context.Background(), identity.Name, metav1.DeleteOptions{}); err != nil { | ||
t.Logf("%v", err) | ||
} | ||
}() | ||
|
||
oauthClient := &oauthapi.OAuthClient{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Name: "demooauthclient", | ||
}, | ||
Secret: "ThisIsATopSecret", | ||
RedirectURIs: []string{"https://localhost"}, | ||
GrantMethod: "auto", | ||
} | ||
_, err = oauthClientClient.OAuthClients().Create(context.Background(), oauthClient, metav1.CreateOptions{}) | ||
require.NoError(t, err) | ||
defer func() { | ||
if err := oauthClientClient.OAuthClients().Delete(context.Background(), oauthClient.Name, metav1.DeleteOptions{}); err != nil { | ||
t.Logf("%v", err) | ||
} | ||
}() | ||
|
||
shortLivedOAuthAccessToken := &oauthapi.OAuthAccessToken{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Name: "Wf0AA1DphiD1FFLQV7BQIsesaaba-15RoSPZ3SvvXXS", | ||
}, | ||
ClientName: oauthClient.Name, | ||
ExpiresIn: 86400, | ||
Scopes: []string{"user:full"}, | ||
RedirectURI: oauthClient.RedirectURIs[0], | ||
UserName: user.Name, | ||
UserUID: string(userInfo.UID), | ||
AuthorizeToken: "mJOQ7Es5l9V7WYDl0bvl3E_hRjnJ21ZZxXH6YZj3yeS", | ||
InactivityTimeoutSeconds: 300, | ||
} | ||
_, err = oauthClientClient.OAuthAccessTokens().Create(context.Background(), shortLivedOAuthAccessToken, metav1.CreateOptions{}) | ||
require.NoError(t, err) | ||
defer func() { | ||
if err := oauthClientClient.OAuthAccessTokens().Delete(context.Background(), shortLivedOAuthAccessToken.Name, metav1.DeleteOptions{}); err != nil { | ||
t.Logf("%v", err) | ||
} | ||
}() | ||
|
||
buf := bytes.Buffer{} | ||
req, err := http.NewRequest(http.MethodGet, kubeConfig.Host+"/apis/user.openshift.io/v1/users/~", &buf) | ||
require.NoError(t, err) | ||
req.Header.Set("Authorization", "Bearer "+shortLivedOAuthAccessToken.Name) | ||
|
||
httpClient := &http.Client{ | ||
Transport: &http.Transport{ | ||
TLSClientConfig: &tls.Config{ | ||
InsecureSkipVerify: true, | ||
}, | ||
}, | ||
} | ||
|
||
resp, err := httpClient.Do(req) | ||
require.NoError(t, err) | ||
|
||
if resp.StatusCode != http.StatusOK { | ||
t.Fatalf("access token should work. Recieved status %v", resp.Status) | ||
} | ||
|
||
// Wait for token to expire. | ||
fmt.Println("Waiting for token to expire due to inactivity") | ||
time.Sleep(305 * time.Second) | ||
|
||
resp, err = httpClient.Do(req) | ||
require.NoError(t, err) | ||
|
||
if resp.StatusCode == http.StatusOK { | ||
t.Fatalf("access token should not work. Recieved status %v", resp.Status) | ||
} | ||
|
||
updateOAuthServerClusterConfigSpec(t, configClient, 0) | ||
|
||
// Wait for kube-apiserver to start the new rollout | ||
test.WaitForKubeAPIServerStartProgressing(t, configClient) | ||
|
||
// Wait until all kube-apiserver pods are restarted with new config. | ||
test.WaitForKubeAPIServerClusterOperatorAvailableNotProgressingNotDegraded(t, configClient) | ||
|
||
} | ||
|
||
func updateOAuthServerClusterConfigSpec(t *testing.T, client *configclient.ConfigV1Client, duration time.Duration) { | ||
oauthConfig, err := client.OAuths().Get(context.Background(), "cluster", metav1.GetOptions{}) | ||
require.NoError(t, err) | ||
|
||
oauthConfig.Spec.TokenConfig.AccessTokenMaxAgeSeconds = int32(defaultAccessTokenMaxAgeSeconds) | ||
oauthConfig.Spec.TokenConfig.AccessTokenInactivityTimeout = &metav1.Duration{Duration: duration} | ||
|
||
oauthConfig, err = client.OAuths().Update(context.Background(), oauthConfig, metav1.UpdateOptions{}) | ||
require.NoError(t, err) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters