Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d16496c

Browse files
committed
Add test for CLI
1 parent 1b65d08 commit d16496c

File tree

5 files changed

+63
-19
lines changed

5 files changed

+63
-19
lines changed

coderd/coderd.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ func New(options *Options) http.Handler {
108108

109109
r.Route("/workspaceagent", func(r chi.Router) {
110110
r.Route("/authenticate", func(r chi.Router) {
111-
r.Post("/google-instance-identity", api.postWorkspaceAgentAuthenticateGoogleInstanceIdentity)
111+
r.Post("/google-instance-identity", api.postAuthenticateWorkspaceAgentUsingGoogleInstanceIdentity)
112112
})
113113
})
114114

coderd/workspaceagent.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@ import (
1313
"github.com/mitchellh/mapstructure"
1414
)
1515

16-
// WorkspaceAgentAuthenticateGoogleInstanceIdentityRequest
17-
type WorkspaceAgentAuthenticateGoogleInstanceIdentityRequest struct {
16+
type AuthenticateWorkspaceAgentUsingGoogleInstanceIdentity struct {
1817
JSONWebToken string `json:"json_web_token" validate:"required"`
1918
}
2019

@@ -27,8 +26,8 @@ type WorkspaceAgentAuthenticateResponse struct {
2726
// Google Compute Engine supports instance identity verification:
2827
// https://cloud.google.com/compute/docs/instances/verifying-instance-identity
2928
// Using this, we can exchange a signed instance payload for an agent token.
30-
func (api *api) postWorkspaceAgentAuthenticateGoogleInstanceIdentity(rw http.ResponseWriter, r *http.Request) {
31-
var req WorkspaceAgentAuthenticateGoogleInstanceIdentityRequest
29+
func (api *api) postAuthenticateWorkspaceAgentUsingGoogleInstanceIdentity(rw http.ResponseWriter, r *http.Request) {
30+
var req AuthenticateWorkspaceAgentUsingGoogleInstanceIdentity
3231
if !httpapi.Read(rw, r, &req) {
3332
return
3433
}

coderd/workspaceagent_test.go

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,18 @@ import (
1414
"time"
1515

1616
"cloud.google.com/go/compute/metadata"
17+
"github.com/golang-jwt/jwt"
18+
"github.com/stretchr/testify/require"
19+
"google.golang.org/api/idtoken"
20+
"google.golang.org/api/option"
21+
1722
"github.com/coder/coder/coderd"
1823
"github.com/coder/coder/coderd/coderdtest"
1924
"github.com/coder/coder/codersdk"
2025
"github.com/coder/coder/cryptorand"
2126
"github.com/coder/coder/database"
2227
"github.com/coder/coder/provisioner/echo"
2328
"github.com/coder/coder/provisionersdk/proto"
24-
"github.com/golang-jwt/jwt"
25-
"github.com/stretchr/testify/require"
26-
"google.golang.org/api/idtoken"
27-
"google.golang.org/api/option"
2829
)
2930

3031
func TestPostWorkspaceAgentAuthenticateGoogleInstanceIdentity(t *testing.T) {
@@ -37,7 +38,7 @@ func TestPostWorkspaceAgentAuthenticateGoogleInstanceIdentity(t *testing.T) {
3738
client := coderdtest.New(t, &coderdtest.Options{
3839
GoogleTokenValidator: validator,
3940
})
40-
_, err := client.WorkspaceAgentAuthenticateGoogleInstanceIdentity(context.Background(), "", createMetadataClient(signedKey))
41+
_, err := client.AuthenticateWorkspaceAgentUsingGoogleCloudIdentity(context.Background(), "", createMetadataClient(signedKey))
4142
var apiErr *codersdk.Error
4243
require.ErrorAs(t, err, &apiErr)
4344
require.Equal(t, http.StatusUnauthorized, apiErr.StatusCode())
@@ -51,7 +52,7 @@ func TestPostWorkspaceAgentAuthenticateGoogleInstanceIdentity(t *testing.T) {
5152
client := coderdtest.New(t, &coderdtest.Options{
5253
GoogleTokenValidator: validator,
5354
})
54-
_, err := client.WorkspaceAgentAuthenticateGoogleInstanceIdentity(context.Background(), "", createMetadataClient(signedKey))
55+
_, err := client.AuthenticateWorkspaceAgentUsingGoogleCloudIdentity(context.Background(), "", createMetadataClient(signedKey))
5556
var apiErr *codersdk.Error
5657
require.ErrorAs(t, err, &apiErr)
5758
require.Equal(t, http.StatusNotFound, apiErr.StatusCode())
@@ -91,7 +92,7 @@ func TestPostWorkspaceAgentAuthenticateGoogleInstanceIdentity(t *testing.T) {
9192
require.NoError(t, err)
9293
coderdtest.AwaitWorkspaceProvisionJob(t, client, user.Organization, firstHistory.ProvisionJobID)
9394

94-
_, err = client.WorkspaceAgentAuthenticateGoogleInstanceIdentity(context.Background(), "", createMetadataClient(signedKey))
95+
_, err = client.AuthenticateWorkspaceAgentUsingGoogleCloudIdentity(context.Background(), "", createMetadataClient(signedKey))
9596
require.NoError(t, err)
9697
})
9798
}
@@ -117,7 +118,7 @@ func createMetadataClient(signedKey string) *metadata.Client {
117118
}
118119

119120
// Create's a signed JWT with a randomly generated private key.
120-
func createSignedToken(t *testing.T, instanceID string, claims *jwt.MapClaims) (string, string, *rsa.PrivateKey) {
121+
func createSignedToken(t *testing.T, instanceID string, claims *jwt.MapClaims) (signedKey string, keyID string, privateKey *rsa.PrivateKey) {
121122
keyID, err := cryptorand.String(12)
122123
require.NoError(t, err)
123124
if claims == nil {
@@ -132,11 +133,11 @@ func createSignedToken(t *testing.T, instanceID string, claims *jwt.MapClaims) (
132133
}
133134
token := jwt.NewWithClaims(jwt.SigningMethodRS256, claims)
134135
token.Header["kid"] = keyID
135-
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
136+
privateKey, err = rsa.GenerateKey(rand.Reader, 2048)
136137
require.NoError(t, err)
137-
signed, err := token.SignedString(privateKey)
138+
signedKey, err = token.SignedString(privateKey)
138139
require.NoError(t, err)
139-
return signed, keyID, privateKey
140+
return signedKey, keyID, privateKey
140141
}
141142

142143
// Create's a validator that verifies against the provided private key.

codersdk/workspaceagent.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,29 @@ import (
77
"net/http"
88

99
"cloud.google.com/go/compute/metadata"
10-
"github.com/coder/coder/coderd"
1110
"golang.org/x/xerrors"
11+
12+
"github.com/coder/coder/coderd"
1213
)
1314

14-
func (c *Client) WorkspaceAgentAuthenticateGoogleInstanceIdentity(ctx context.Context, serviceAccount string, gcpClient *metadata.Client) (coderd.WorkspaceAgentAuthenticateResponse, error) {
15+
// AuthenticateWorkspaceAgentUsingGoogleCloudIdentity uses the Google Compute Engine Metadata API to
16+
// fetch a signed JWT, and exchange it for a session token for a workspace agent.
17+
//
18+
// The requesting instance must be registered as a resource in the latest history for a workspace.
19+
func (c *Client) AuthenticateWorkspaceAgentUsingGoogleCloudIdentity(ctx context.Context, serviceAccount string, gcpClient *metadata.Client) (coderd.WorkspaceAgentAuthenticateResponse, error) {
1520
if serviceAccount == "" {
21+
// This is the default name specified by Google.
1622
serviceAccount = "default"
1723
}
1824
if gcpClient == nil {
1925
gcpClient = metadata.NewClient(c.httpClient)
2026
}
27+
// "format=full" is required, otherwise the responding payload will be missing "instance_id".
2128
jwt, err := gcpClient.Get(fmt.Sprintf("instance/service-accounts/%s/identity?audience=coder&format=full", serviceAccount))
2229
if err != nil {
2330
return coderd.WorkspaceAgentAuthenticateResponse{}, xerrors.Errorf("get metadata identity: %w", err)
2431
}
25-
res, err := c.request(ctx, http.MethodPost, "/api/v2/workspaceagent/authenticate/google-instance-identity", coderd.WorkspaceAgentAuthenticateGoogleInstanceIdentityRequest{
32+
res, err := c.request(ctx, http.MethodPost, "/api/v2/workspaceagent/authenticate/google-instance-identity", coderd.AuthenticateWorkspaceAgentUsingGoogleInstanceIdentity{
2633
JSONWebToken: jwt,
2734
})
2835
if err != nil {

codersdk/workspaceagent_test.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package codersdk_test
2+
3+
import (
4+
"bytes"
5+
"context"
6+
"io"
7+
"net/http"
8+
"testing"
9+
10+
"cloud.google.com/go/compute/metadata"
11+
"github.com/stretchr/testify/require"
12+
13+
"github.com/coder/coder/coderd/coderdtest"
14+
)
15+
16+
func TestAuthenticateWorkspaceAgentUsingGoogleCloudIdentity(t *testing.T) {
17+
t.Parallel()
18+
t.Run("Error", func(t *testing.T) {
19+
t.Parallel()
20+
client := coderdtest.New(t, nil)
21+
_, err := client.AuthenticateWorkspaceAgentUsingGoogleCloudIdentity(context.Background(), "", metadata.NewClient(&http.Client{
22+
Transport: roundTripper(func(req *http.Request) (*http.Response, error) {
23+
return &http.Response{
24+
StatusCode: http.StatusOK,
25+
Body: io.NopCloser(bytes.NewReader([]byte("sometoken"))),
26+
}, nil
27+
}),
28+
}))
29+
require.Error(t, err)
30+
})
31+
}
32+
33+
type roundTripper func(req *http.Request) (*http.Response, error)
34+
35+
func (r roundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
36+
return r(req)
37+
}

0 commit comments

Comments
 (0)