Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion coderd/coderdtest/coderdtest.go
Original file line number Diff line number Diff line change
Expand Up @@ -1610,10 +1610,11 @@ func RequestExternalAuthCallback(t testing.TB, providerID string, client *coders
// NewGoogleInstanceIdentity returns a metadata client and ID token validator for faking
// instance authentication for Google Cloud.
// nolint:revive
func NewGoogleInstanceIdentity(t testing.TB, instanceID string, expired bool) (*idtoken.Validator, *metadata.Client) {
func NewGoogleInstanceIdentity(t testing.TB, instanceID string, expired bool, audience string) (*idtoken.Validator, *metadata.Client) {
keyID, err := cryptorand.String(12)
require.NoError(t, err)
claims := jwt.MapClaims{
"aud": audience,
"google": map[string]interface{}{
"compute_engine": map[string]string{
"instance_id": instanceID,
Expand Down
2 changes: 1 addition & 1 deletion coderd/coderdtest/coderdtest_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func TestNew(t *testing.T) {
workspace := coderdtest.CreateWorkspace(t, client, template.ID)
coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID)
coderdtest.AwaitWorkspaceAgents(t, client, workspace.ID)
_, _ = coderdtest.NewGoogleInstanceIdentity(t, "example", false)
_, _ = coderdtest.NewGoogleInstanceIdentity(t, "example", false, "coder")
_, _ = coderdtest.NewAWSInstanceIdentity(t, "an-instance")
}

Expand Down
3 changes: 1 addition & 2 deletions coderd/workspaceresourceauth.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,7 @@ func (api *API) postWorkspaceAuthGoogleInstanceIdentity(rw http.ResponseWriter,
return
}

// We leave the audience blank. It's not important we validate who made the token.
payload, err := api.GoogleTokenValidator.Validate(ctx, req.JSONWebToken, "")
payload, err := api.GoogleTokenValidator.Validate(ctx, req.JSONWebToken, "coder")
if err != nil {
httpapi.Write(ctx, rw, http.StatusUnauthorized, codersdk.Response{
Message: "Invalid GCP identity.",
Expand Down
31 changes: 26 additions & 5 deletions coderd/workspaceresourceauth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ func TestPostWorkspaceAuthGoogleInstanceIdentity(t *testing.T) {
t.Parallel()

instanceID := newTestInstanceID(t)
validator, metadata := coderdtest.NewGoogleInstanceIdentity(t, instanceID, true)
validator, metadata := coderdtest.NewGoogleInstanceIdentity(t, instanceID, true, "coder")
client := coderdtest.New(t, &coderdtest.Options{
GoogleTokenValidator: validator,
})
Expand All @@ -310,7 +310,7 @@ func TestPostWorkspaceAuthGoogleInstanceIdentity(t *testing.T) {
t.Parallel()

instanceID := newTestInstanceID(t)
validator, metadata := coderdtest.NewGoogleInstanceIdentity(t, instanceID, false)
validator, metadata := coderdtest.NewGoogleInstanceIdentity(t, instanceID, false, "coder")
client := coderdtest.New(t, &coderdtest.Options{
GoogleTokenValidator: validator,
})
Expand All @@ -329,24 +329,45 @@ func TestPostWorkspaceAuthGoogleInstanceIdentity(t *testing.T) {
t.Parallel()

instanceID := newTestInstanceID(t)
validator, metadata := coderdtest.NewGoogleInstanceIdentity(t, instanceID, false)
client, _ := setupInstanceIDWorkspace(t, &coderdtest.Options{
validator, metadata := coderdtest.NewGoogleInstanceIdentity(t, instanceID, false, "coder")
client, store := setupInstanceIDWorkspace(t, &coderdtest.Options{
GoogleTokenValidator: validator,
}, workspaceAgentsForInstanceID(instanceID, "dev"))
expectedAgent := requireWorkspaceAgentByInstanceIDAndName(t, store, instanceID, "dev")

ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
defer cancel()

agentClient := agentsdk.New(client.URL, agentsdk.WithGoogleInstanceIdentity("", metadata))
err := agentClient.RefreshToken(ctx)
require.NoError(t, err)
require.Equal(t, expectedAgent.AuthToken.String(), agentClient.SDK.SessionToken())
})

t.Run("ForeignAudience", func(t *testing.T) {
t.Parallel()

instanceID := newTestInstanceID(t)
validator, metadata := coderdtest.NewGoogleInstanceIdentity(t, instanceID, false, "other-service")
client, _ := setupInstanceIDWorkspace(t, &coderdtest.Options{
GoogleTokenValidator: validator,
}, workspaceAgentsForInstanceID(instanceID, "dev"))

ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
defer cancel()

agentClient := agentsdk.New(client.URL, agentsdk.WithGoogleInstanceIdentity("", metadata))
err := agentClient.RefreshToken(ctx)
var apiErr *codersdk.Error
require.ErrorAs(t, err, &apiErr)
require.Equal(t, http.StatusUnauthorized, apiErr.StatusCode())
})

t.Run("Ambiguous/GoogleWithSelector", func(t *testing.T) {
t.Parallel()

instanceID := newTestInstanceID(t)
validator, metadata := coderdtest.NewGoogleInstanceIdentity(t, instanceID, false)
validator, metadata := coderdtest.NewGoogleInstanceIdentity(t, instanceID, false, "coder")
client, store := setupInstanceIDWorkspace(t, &coderdtest.Options{
GoogleTokenValidator: validator,
}, workspaceAgentsForInstanceID(instanceID, "alpha", "beta"))
Expand Down
Loading