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

Skip to content

feat: Add agent authentication based on instance ID #336

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Feb 21, 2022
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
2 changes: 2 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,13 @@
"gossh",
"hashicorp",
"httpmw",
"idtoken",
"isatty",
"Jobf",
"kirsle",
"manifoldco",
"mattn",
"mitchellh",
"moby",
"nhooyr",
"nolint",
Expand Down
2 changes: 1 addition & 1 deletion cli/clitest/clitest_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func TestMain(m *testing.M) {
func TestCli(t *testing.T) {
t.Parallel()
clitest.CreateProjectVersionSource(t, nil)
client := coderdtest.New(t)
client := coderdtest.New(t, nil)
cmd, config := clitest.New(t)
clitest.SetupConfig(t, client, config)
pty := ptytest.New(t)
Expand Down
8 changes: 4 additions & 4 deletions cli/login_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ func TestLogin(t *testing.T) {
t.Parallel()
t.Run("InitialUserNoTTY", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t)
client := coderdtest.New(t, nil)
root, _ := clitest.New(t, "login", client.URL.String())
err := root.Execute()
require.Error(t, err)
})

t.Run("InitialUserTTY", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t)
client := coderdtest.New(t, nil)
// The --force-tty flag is required on Windows, because the `isatty` library does not
// accurately detect Windows ptys when they are not attached to a process:
// https://github.com/mattn/go-isatty/issues/59
Expand Down Expand Up @@ -55,7 +55,7 @@ func TestLogin(t *testing.T) {

t.Run("ExistingUserValidTokenTTY", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t)
client := coderdtest.New(t, nil)
_, err := client.CreateInitialUser(context.Background(), coderd.CreateInitialUserRequest{
Username: "test-user",
Email: "[email protected]",
Expand Down Expand Up @@ -85,7 +85,7 @@ func TestLogin(t *testing.T) {

t.Run("ExistingUserInvalidTokenTTY", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t)
client := coderdtest.New(t, nil)
_, err := client.CreateInitialUser(context.Background(), coderd.CreateInitialUserRequest{
Username: "test-user",
Email: "[email protected]",
Expand Down
4 changes: 2 additions & 2 deletions cli/projectcreate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ func TestProjectCreate(t *testing.T) {
t.Parallel()
t.Run("NoParameters", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t)
client := coderdtest.New(t, nil)
coderdtest.CreateInitialUser(t, client)
source := clitest.CreateProjectVersionSource(t, &echo.Responses{
Parse: echo.ParseComplete,
Expand Down Expand Up @@ -53,7 +53,7 @@ func TestProjectCreate(t *testing.T) {

t.Run("Parameter", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t)
client := coderdtest.New(t, nil)
coderdtest.CreateInitialUser(t, client)
source := clitest.CreateProjectVersionSource(t, &echo.Responses{
Parse: []*proto.Parse_Response{{
Expand Down
4 changes: 2 additions & 2 deletions cli/projectlist_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ func TestProjectList(t *testing.T) {
t.Parallel()
t.Run("None", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t)
client := coderdtest.New(t, nil)
coderdtest.CreateInitialUser(t, client)
cmd, root := clitest.New(t, "projects", "list")
clitest.SetupConfig(t, client, root)
Expand All @@ -32,7 +32,7 @@ func TestProjectList(t *testing.T) {
})
t.Run("List", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t)
client := coderdtest.New(t, nil)
user := coderdtest.CreateInitialUser(t, client)
daemon := coderdtest.NewProvisionerDaemon(t, client)
job := coderdtest.CreateProjectImportJob(t, client, user.Organization, nil)
Expand Down
2 changes: 1 addition & 1 deletion cli/workspacecreate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ func TestWorkspaceCreate(t *testing.T) {
t.Parallel()
t.Run("Create", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t)
client := coderdtest.New(t, nil)
user := coderdtest.CreateInitialUser(t, client)
_ = coderdtest.NewProvisionerDaemon(t, client)
job := coderdtest.CreateProjectImportJob(t, client, user.Organization, &echo.Responses{
Expand Down
9 changes: 9 additions & 0 deletions coderd/coderd.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"sync"

"github.com/go-chi/chi/v5"
"google.golang.org/api/idtoken"

"cdr.dev/slog"
"github.com/coder/coder/database"
Expand All @@ -18,6 +19,8 @@ type Options struct {
Logger slog.Logger
Database database.Store
Pubsub database.Pubsub

GoogleTokenValidator *idtoken.Validator
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, interesting - so we'll have to add token validation for all the cloud instances we support?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems like longer term we might want to refactor these into some common interface or something

Copy link
Contributor

@bryphe-coder bryphe-coder Feb 21, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That sounds like a great idea @jawnsy ! @misskniss - I'm also thinking we'll need to track the work for adding additional validators for stuff we want to have in Alpha (EC2, Azure?)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to abstract it, but didn't think it was worth it. It'll make more intricate testing harder, because we want to mock the metadata server n' such.

Maybe eventually we can, but I wanted to keep the handlers in coderd.

}

// New constructs the Coder API into an HTTP handler.
Expand Down Expand Up @@ -107,6 +110,12 @@ func New(options *Options) (http.Handler, func()) {
})
})

r.Route("/workspaceagent", func(r chi.Router) {
r.Route("/authenticate", func(r chi.Router) {
r.Post("/google-instance-identity", api.postAuthenticateWorkspaceAgentUsingGoogleInstanceIdentity)
})
})

r.Route("/files", func(r chi.Router) {
r.Use(httpmw.ExtractAPIKey(options.Database, nil))
r.Post("/", api.postFiles)
Expand Down
29 changes: 28 additions & 1 deletion coderd/coderdtest/coderdtest.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ import (
"github.com/google/uuid"
"github.com/moby/moby/pkg/namesgenerator"
"github.com/stretchr/testify/require"
"go.opencensus.io/stats/view"
"google.golang.org/api/idtoken"
"google.golang.org/api/option"

"cdr.dev/slog"
"cdr.dev/slog/sloggers/slogtest"
Expand All @@ -29,9 +32,31 @@ import (
"github.com/coder/coder/provisionersdk/proto"
)

type Options struct {
GoogleTokenValidator *idtoken.Validator
}

// New constructs an in-memory coderd instance and returns
// the connected client.
func New(t *testing.T) *codersdk.Client {
func New(t *testing.T, options *Options) *codersdk.Client {
// Stops the opencensus.io worker from leaking a goroutine.
// The worker isn't used anyways, and is an indirect dependency
// of the Google Cloud SDK.
t.Cleanup(func() {
view.Stop()
})

if options == nil {
options = &Options{}
}
if options.GoogleTokenValidator == nil {
ctx, cancelFunc := context.WithCancel(context.Background())
t.Cleanup(cancelFunc)
var err error
options.GoogleTokenValidator, err = idtoken.NewValidator(ctx, option.WithoutAuthentication())
require.NoError(t, err)
}

// This can be hotswapped for a live database instance.
db := databasefake.New()
pubsub := database.NewPubsubInMemory()
Expand Down Expand Up @@ -59,6 +84,8 @@ func New(t *testing.T) *codersdk.Client {
Logger: slogtest.Make(t, nil).Leveled(slog.LevelDebug),
Database: db,
Pubsub: pubsub,

GoogleTokenValidator: options.GoogleTokenValidator,
})
srv := httptest.NewUnstartedServer(handler)
srv.Config.BaseContext = func(_ net.Listener) context.Context {
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 @@ -19,7 +19,7 @@ func TestMain(m *testing.M) {

func TestNew(t *testing.T) {
t.Parallel()
client := coderdtest.New(t)
client := coderdtest.New(t, nil)
user := coderdtest.CreateInitialUser(t, client)
closer := coderdtest.NewProvisionerDaemon(t, client)
job := coderdtest.CreateProjectImportJob(t, client, user.Organization, nil)
Expand Down
6 changes: 3 additions & 3 deletions coderd/files_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,23 @@ func TestPostFiles(t *testing.T) {
t.Parallel()
t.Run("BadContentType", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t)
client := coderdtest.New(t, nil)
_ = coderdtest.CreateInitialUser(t, client)
_, err := client.UploadFile(context.Background(), "bad", []byte{'a'})
require.Error(t, err)
})

t.Run("Insert", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t)
client := coderdtest.New(t, nil)
_ = coderdtest.CreateInitialUser(t, client)
_, err := client.UploadFile(context.Background(), codersdk.ContentTypeTar, make([]byte, 1024))
require.NoError(t, err)
})

t.Run("InsertAlreadyExists", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t)
client := coderdtest.New(t, nil)
_ = coderdtest.CreateInitialUser(t, client)
data := make([]byte, 1024)
_, err := client.UploadFile(context.Background(), codersdk.ContentTypeTar, data)
Expand Down
16 changes: 8 additions & 8 deletions coderd/projectimport_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ func TestPostProjectImportByOrganization(t *testing.T) {
t.Parallel()
t.Run("FileNotFound", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t)
client := coderdtest.New(t, nil)
user := coderdtest.CreateInitialUser(t, client)
_, err := client.CreateProjectImportJob(context.Background(), user.Organization, coderd.CreateProjectImportJobRequest{
StorageMethod: database.ProvisionerStorageMethodFile,
Expand All @@ -30,7 +30,7 @@ func TestPostProjectImportByOrganization(t *testing.T) {
})
t.Run("Create", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t)
client := coderdtest.New(t, nil)
user := coderdtest.CreateInitialUser(t, client)
_ = coderdtest.CreateProjectImportJob(t, client, user.Organization, nil)
})
Expand All @@ -40,7 +40,7 @@ func TestProjectImportJobSchemasByID(t *testing.T) {
t.Parallel()
t.Run("ListRunning", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t)
client := coderdtest.New(t, nil)
user := coderdtest.CreateInitialUser(t, client)
job := coderdtest.CreateProjectImportJob(t, client, user.Organization, nil)
_, err := client.ProjectImportJobSchemas(context.Background(), user.Organization, job.ID)
Expand All @@ -50,7 +50,7 @@ func TestProjectImportJobSchemasByID(t *testing.T) {
})
t.Run("List", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t)
client := coderdtest.New(t, nil)
user := coderdtest.CreateInitialUser(t, client)
coderdtest.NewProvisionerDaemon(t, client)
job := coderdtest.CreateProjectImportJob(t, client, user.Organization, &echo.Responses{
Expand Down Expand Up @@ -80,7 +80,7 @@ func TestProjectImportJobParametersByID(t *testing.T) {
t.Parallel()
t.Run("ListRunning", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t)
client := coderdtest.New(t, nil)
user := coderdtest.CreateInitialUser(t, client)
job := coderdtest.CreateProjectImportJob(t, client, user.Organization, nil)
_, err := client.ProjectImportJobSchemas(context.Background(), user.Organization, job.ID)
Expand All @@ -90,7 +90,7 @@ func TestProjectImportJobParametersByID(t *testing.T) {
})
t.Run("List", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t)
client := coderdtest.New(t, nil)
user := coderdtest.CreateInitialUser(t, client)
coderdtest.NewProvisionerDaemon(t, client)
job := coderdtest.CreateProjectImportJob(t, client, user.Organization, &echo.Responses{
Expand Down Expand Up @@ -126,7 +126,7 @@ func TestProjectImportJobResourcesByID(t *testing.T) {
t.Parallel()
t.Run("ListRunning", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t)
client := coderdtest.New(t, nil)
user := coderdtest.CreateInitialUser(t, client)
job := coderdtest.CreateProjectImportJob(t, client, user.Organization, nil)
_, err := client.ProjectImportJobResources(context.Background(), user.Organization, job.ID)
Expand All @@ -136,7 +136,7 @@ func TestProjectImportJobResourcesByID(t *testing.T) {
})
t.Run("List", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t)
client := coderdtest.New(t, nil)
user := coderdtest.CreateInitialUser(t, client)
coderdtest.NewProvisionerDaemon(t, client)
job := coderdtest.CreateProjectImportJob(t, client, user.Organization, &echo.Responses{
Expand Down
22 changes: 11 additions & 11 deletions coderd/projects_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func TestProjects(t *testing.T) {

t.Run("ListEmpty", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t)
client := coderdtest.New(t, nil)
_ = coderdtest.CreateInitialUser(t, client)
projects, err := client.Projects(context.Background(), "")
require.NoError(t, err)
Expand All @@ -28,7 +28,7 @@ func TestProjects(t *testing.T) {

t.Run("List", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t)
client := coderdtest.New(t, nil)
user := coderdtest.CreateInitialUser(t, client)
job := coderdtest.CreateProjectImportJob(t, client, user.Organization, nil)
_ = coderdtest.CreateProject(t, client, user.Organization, job.ID)
Expand All @@ -39,7 +39,7 @@ func TestProjects(t *testing.T) {

t.Run("ListWorkspaceOwnerCount", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t)
client := coderdtest.New(t, nil)
user := coderdtest.CreateInitialUser(t, client)
coderdtest.NewProvisionerDaemon(t, client)
job := coderdtest.CreateProjectImportJob(t, client, user.Organization, nil)
Expand All @@ -58,7 +58,7 @@ func TestProjectsByOrganization(t *testing.T) {
t.Parallel()
t.Run("ListEmpty", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t)
client := coderdtest.New(t, nil)
user := coderdtest.CreateInitialUser(t, client)
projects, err := client.Projects(context.Background(), user.Organization)
require.NoError(t, err)
Expand All @@ -68,7 +68,7 @@ func TestProjectsByOrganization(t *testing.T) {

t.Run("List", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t)
client := coderdtest.New(t, nil)
user := coderdtest.CreateInitialUser(t, client)
job := coderdtest.CreateProjectImportJob(t, client, user.Organization, nil)
_ = coderdtest.CreateProject(t, client, user.Organization, job.ID)
Expand All @@ -82,15 +82,15 @@ func TestPostProjectsByOrganization(t *testing.T) {
t.Parallel()
t.Run("Create", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t)
client := coderdtest.New(t, nil)
user := coderdtest.CreateInitialUser(t, client)
job := coderdtest.CreateProjectImportJob(t, client, user.Organization, nil)
_ = coderdtest.CreateProject(t, client, user.Organization, job.ID)
})

t.Run("AlreadyExists", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t)
client := coderdtest.New(t, nil)
user := coderdtest.CreateInitialUser(t, client)
job := coderdtest.CreateProjectImportJob(t, client, user.Organization, nil)
project := coderdtest.CreateProject(t, client, user.Organization, job.ID)
Expand All @@ -108,7 +108,7 @@ func TestProjectByOrganization(t *testing.T) {
t.Parallel()
t.Run("Get", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t)
client := coderdtest.New(t, nil)
user := coderdtest.CreateInitialUser(t, client)
job := coderdtest.CreateProjectImportJob(t, client, user.Organization, nil)
project := coderdtest.CreateProject(t, client, user.Organization, job.ID)
Expand All @@ -121,7 +121,7 @@ func TestPostParametersByProject(t *testing.T) {
t.Parallel()
t.Run("Create", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t)
client := coderdtest.New(t, nil)
user := coderdtest.CreateInitialUser(t, client)
job := coderdtest.CreateProjectImportJob(t, client, user.Organization, nil)
project := coderdtest.CreateProject(t, client, user.Organization, job.ID)
Expand All @@ -139,7 +139,7 @@ func TestParametersByProject(t *testing.T) {
t.Parallel()
t.Run("ListEmpty", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t)
client := coderdtest.New(t, nil)
user := coderdtest.CreateInitialUser(t, client)
job := coderdtest.CreateProjectImportJob(t, client, user.Organization, nil)
project := coderdtest.CreateProject(t, client, user.Organization, job.ID)
Expand All @@ -150,7 +150,7 @@ func TestParametersByProject(t *testing.T) {

t.Run("List", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t)
client := coderdtest.New(t, nil)
user := coderdtest.CreateInitialUser(t, client)
job := coderdtest.CreateProjectImportJob(t, client, user.Organization, nil)
project := coderdtest.CreateProject(t, client, user.Organization, job.ID)
Expand Down
Loading