Skip to content

Commit 440470e

Browse files
committed
Add test for CLI
1 parent 1b65d08 commit 440470e

File tree

5 files changed

+53
-11
lines changed

5 files changed

+53
-11
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: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ func TestPostWorkspaceAgentAuthenticateGoogleInstanceIdentity(t *testing.T) {
3737
client := coderdtest.New(t, &coderdtest.Options{
3838
GoogleTokenValidator: validator,
3939
})
40-
_, err := client.WorkspaceAgentAuthenticateGoogleInstanceIdentity(context.Background(), "", createMetadataClient(signedKey))
40+
_, err := client.AuthenticateWorkspaceAgentUsingGoogleCloudIdentity(context.Background(), "", createMetadataClient(signedKey))
4141
var apiErr *codersdk.Error
4242
require.ErrorAs(t, err, &apiErr)
4343
require.Equal(t, http.StatusUnauthorized, apiErr.StatusCode())
@@ -51,7 +51,7 @@ func TestPostWorkspaceAgentAuthenticateGoogleInstanceIdentity(t *testing.T) {
5151
client := coderdtest.New(t, &coderdtest.Options{
5252
GoogleTokenValidator: validator,
5353
})
54-
_, err := client.WorkspaceAgentAuthenticateGoogleInstanceIdentity(context.Background(), "", createMetadataClient(signedKey))
54+
_, err := client.AuthenticateWorkspaceAgentUsingGoogleCloudIdentity(context.Background(), "", createMetadataClient(signedKey))
5555
var apiErr *codersdk.Error
5656
require.ErrorAs(t, err, &apiErr)
5757
require.Equal(t, http.StatusNotFound, apiErr.StatusCode())
@@ -91,7 +91,7 @@ func TestPostWorkspaceAgentAuthenticateGoogleInstanceIdentity(t *testing.T) {
9191
require.NoError(t, err)
9292
coderdtest.AwaitWorkspaceProvisionJob(t, client, user.Organization, firstHistory.ProvisionJobID)
9393

94-
_, err = client.WorkspaceAgentAuthenticateGoogleInstanceIdentity(context.Background(), "", createMetadataClient(signedKey))
94+
_, err = client.AuthenticateWorkspaceAgentUsingGoogleCloudIdentity(context.Background(), "", createMetadataClient(signedKey))
9595
require.NoError(t, err)
9696
})
9797
}

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: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
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/coder/coder/coderd/coderdtest"
12+
"github.com/stretchr/testify/require"
13+
)
14+
15+
func TestAuthenticateWorkspaceAgentUsingGoogleCloudIdentity(t *testing.T) {
16+
t.Parallel()
17+
t.Run("Error", func(t *testing.T) {
18+
t.Parallel()
19+
client := coderdtest.New(t, nil)
20+
_, err := client.AuthenticateWorkspaceAgentUsingGoogleCloudIdentity(context.Background(), "", metadata.NewClient(&http.Client{
21+
Transport: roundTripper(func(req *http.Request) (*http.Response, error) {
22+
return &http.Response{
23+
StatusCode: http.StatusOK,
24+
Body: io.NopCloser(bytes.NewReader([]byte("sometoken"))),
25+
}, nil
26+
}),
27+
}))
28+
require.Error(t, err)
29+
})
30+
}
31+
32+
type roundTripper func(req *http.Request) (*http.Response, error)
33+
34+
func (r roundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
35+
return r(req)
36+
}

0 commit comments

Comments
 (0)