Merge pull request #36 from mattmoyer/fix-expiration-handling
Fix expiration timestamp handling
This commit is contained in:
commit
3d293c96bc
@ -138,10 +138,11 @@ func (r *REST) Create(ctx context.Context, obj runtime.Object, createValidation
|
|||||||
return failureResponse(), nil
|
return failureResponse(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
expires := metav1.NewTime(time.Now().UTC().Add(clientCertificateTTL))
|
||||||
return &placeholderapi.LoginRequest{
|
return &placeholderapi.LoginRequest{
|
||||||
Status: placeholderapi.LoginRequestStatus{
|
Status: placeholderapi.LoginRequestStatus{
|
||||||
Credential: &placeholderapi.LoginRequestCredential{
|
Credential: &placeholderapi.LoginRequestCredential{
|
||||||
ExpirationTimestamp: nil,
|
ExpirationTimestamp: &expires,
|
||||||
ClientCertificateData: string(certPEM),
|
ClientCertificateData: string(certPEM),
|
||||||
ClientKeyData: string(keyPEM),
|
ClientKeyData: string(keyPEM),
|
||||||
},
|
},
|
||||||
|
@ -153,6 +153,13 @@ func TestCreateSucceedsWhenGivenATokenAndTheWebhookAuthenticatesTheToken(t *test
|
|||||||
response, err := callCreate(context.Background(), storage, validLoginRequestWithToken(requestToken))
|
response, err := callCreate(context.Background(), storage, validLoginRequestWithToken(requestToken))
|
||||||
|
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
require.IsType(t, &placeholderapi.LoginRequest{}, response)
|
||||||
|
|
||||||
|
expires := response.(*placeholderapi.LoginRequest).Status.Credential.ExpirationTimestamp
|
||||||
|
require.NotNil(t, expires)
|
||||||
|
require.InDelta(t, time.Now().Add(1*time.Hour).Unix(), expires.Unix(), 5)
|
||||||
|
response.(*placeholderapi.LoginRequest).Status.Credential.ExpirationTimestamp = nil
|
||||||
|
|
||||||
require.Equal(t, response, &placeholderapi.LoginRequest{
|
require.Equal(t, response, &placeholderapi.LoginRequest{
|
||||||
Status: placeholderapi.LoginRequestStatus{
|
Status: placeholderapi.LoginRequestStatus{
|
||||||
User: &placeholderapi.User{
|
User: &placeholderapi.User{
|
||||||
|
@ -132,6 +132,8 @@ func ExchangeToken(ctx context.Context, token, caBundle, apiEndpoint string) (*C
|
|||||||
Kind string `json:"kind"`
|
Kind string `json:"kind"`
|
||||||
Status struct {
|
Status struct {
|
||||||
Credential *struct {
|
Credential *struct {
|
||||||
|
ExpirationTimestamp string `json:"expirationTimestamp"`
|
||||||
|
Token string `json:"token"`
|
||||||
ClientCertificateData string `json:"clientCertificateData"`
|
ClientCertificateData string `json:"clientCertificateData"`
|
||||||
ClientKeyData string `json:"clientKeyData"`
|
ClientKeyData string `json:"clientKeyData"`
|
||||||
}
|
}
|
||||||
@ -146,8 +148,18 @@ func ExchangeToken(ctx context.Context, token, caBundle, apiEndpoint string) (*C
|
|||||||
return nil, fmt.Errorf("%w: %s", ErrLoginFailed, respBody.Status.Message)
|
return nil, fmt.Errorf("%w: %s", ErrLoginFailed, respBody.Status.Message)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &Credential{
|
result := Credential{
|
||||||
|
Token: respBody.Status.Credential.Token,
|
||||||
ClientCertificateData: respBody.Status.Credential.ClientCertificateData,
|
ClientCertificateData: respBody.Status.Credential.ClientCertificateData,
|
||||||
ClientKeyData: respBody.Status.Credential.ClientKeyData,
|
ClientKeyData: respBody.Status.Credential.ClientKeyData,
|
||||||
}, nil
|
}
|
||||||
|
if str := respBody.Status.Credential.ExpirationTimestamp; str != "" {
|
||||||
|
expiration, err := time.Parse(time.RFC3339, str)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("invalid login response: %w", err)
|
||||||
|
}
|
||||||
|
result.ExpirationTimestamp = &expiration
|
||||||
|
}
|
||||||
|
|
||||||
|
return &result, nil
|
||||||
}
|
}
|
||||||
|
@ -151,6 +151,33 @@ func TestExchangeToken(t *testing.T) {
|
|||||||
require.Nil(t, got)
|
require.Nil(t, got)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("invalid timestamp failure", func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
// Start a test server that returns success but with an error message
|
||||||
|
caBundle, endpoint := startTestServer(t, func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Header().Set("content-type", "application/json")
|
||||||
|
w.WriteHeader(http.StatusCreated)
|
||||||
|
_, _ = w.Write([]byte(`
|
||||||
|
{
|
||||||
|
"kind": "LoginRequest",
|
||||||
|
"apiVersion": "placeholder.suzerain-io.github.io/v1alpha1",
|
||||||
|
"metadata": {
|
||||||
|
"creationTimestamp": null
|
||||||
|
},
|
||||||
|
"spec": {},
|
||||||
|
"status": {
|
||||||
|
"credential": {
|
||||||
|
"expirationTimestamp": "invalid"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`))
|
||||||
|
})
|
||||||
|
|
||||||
|
got, err := ExchangeToken(ctx, "", caBundle, endpoint)
|
||||||
|
require.EqualError(t, err, `invalid login response: parsing time "invalid" as "2006-01-02T15:04:05Z07:00": cannot parse "invalid" as "2006"`)
|
||||||
|
require.Nil(t, got)
|
||||||
|
})
|
||||||
|
|
||||||
t.Run("success", func(t *testing.T) {
|
t.Run("success", func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
@ -192,6 +219,8 @@ func TestExchangeToken(t *testing.T) {
|
|||||||
"spec": {},
|
"spec": {},
|
||||||
"status": {
|
"status": {
|
||||||
"credential": {
|
"credential": {
|
||||||
|
"expirationTimestamp": "2020-07-30T15:52:01Z",
|
||||||
|
"token": "test-token",
|
||||||
"clientCertificateData": "test-certificate",
|
"clientCertificateData": "test-certificate",
|
||||||
"clientKeyData": "test-key"
|
"clientKeyData": "test-key"
|
||||||
}
|
}
|
||||||
@ -201,7 +230,10 @@ func TestExchangeToken(t *testing.T) {
|
|||||||
|
|
||||||
got, err := ExchangeToken(ctx, "test-token", caBundle, endpoint)
|
got, err := ExchangeToken(ctx, "test-token", caBundle, endpoint)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
expires := time.Date(2020, 07, 30, 15, 52, 1, 0, time.UTC)
|
||||||
require.Equal(t, &Credential{
|
require.Equal(t, &Credential{
|
||||||
|
ExpirationTimestamp: &expires,
|
||||||
|
Token: "test-token",
|
||||||
ClientCertificateData: "test-certificate",
|
ClientCertificateData: "test-certificate",
|
||||||
ClientKeyData: "test-key",
|
ClientKeyData: "test-key",
|
||||||
}, got)
|
}, got)
|
||||||
|
@ -67,6 +67,8 @@ func TestClient(t *testing.T) {
|
|||||||
clientConfig := library.NewClientConfig(t)
|
clientConfig := library.NewClientConfig(t)
|
||||||
resp, err := client.ExchangeToken(ctx, tmcClusterToken, string(clientConfig.CAData), clientConfig.Host)
|
resp, err := client.ExchangeToken(ctx, tmcClusterToken, string(clientConfig.CAData), clientConfig.Host)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, resp.ExpirationTimestamp)
|
||||||
|
require.InDelta(t, time.Until(*resp.ExpirationTimestamp), 1*time.Hour, float64(5*time.Second))
|
||||||
|
|
||||||
// Create a client using the certificate and key returned by the token exchange.
|
// Create a client using the certificate and key returned by the token exchange.
|
||||||
validClient := library.NewClientsetWithConfig(t, library.NewClientConfigWithCertAndKey(t, resp.ClientCertificateData, resp.ClientKeyData))
|
validClient := library.NewClientsetWithConfig(t, library.NewClientConfigWithCertAndKey(t, resp.ClientCertificateData, resp.ClientKeyData))
|
||||||
|
@ -55,7 +55,8 @@ func TestSuccessfulLoginRequest(t *testing.T) {
|
|||||||
require.Empty(t, response.Status.Credential.Token)
|
require.Empty(t, response.Status.Credential.Token)
|
||||||
require.NotEmpty(t, response.Status.Credential.ClientCertificateData)
|
require.NotEmpty(t, response.Status.Credential.ClientCertificateData)
|
||||||
require.NotEmpty(t, response.Status.Credential.ClientKeyData)
|
require.NotEmpty(t, response.Status.Credential.ClientKeyData)
|
||||||
require.Nil(t, response.Status.Credential.ExpirationTimestamp)
|
require.NotNil(t, response.Status.Credential.ExpirationTimestamp)
|
||||||
|
require.InDelta(t, time.Until(response.Status.Credential.ExpirationTimestamp.Time), 1*time.Hour, float64(5*time.Second))
|
||||||
require.NotNil(t, response.Status.User)
|
require.NotNil(t, response.Status.User)
|
||||||
require.NotEmpty(t, response.Status.User.Name)
|
require.NotEmpty(t, response.Status.User.Name)
|
||||||
require.Contains(t, response.Status.User.Groups, "tmc:member")
|
require.Contains(t, response.Status.User.Groups, "tmc:member")
|
||||||
|
Loading…
Reference in New Issue
Block a user