mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: Add agent authentication based on instance ID (#336)
* feat: Add agent authentication based on instance ID Each cloud has it's own unique instance identity signatures, which can be used for zero-token authentication. This change adds support for tracking by "instance_id", and automatically authenticating with Google Cloud. * Add test for CLI * Fix workspace agent request name * Fix race with adding to wait group * Fix name of instance identity token
This commit is contained in:
@@ -195,6 +195,18 @@ func (q *fakeQuerier) GetWorkspaceByUserIDAndName(_ context.Context, arg databas
|
||||
return database.Workspace{}, sql.ErrNoRows
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) GetWorkspaceResourceByInstanceID(_ context.Context, instanceID string) (database.WorkspaceResource, error) {
|
||||
q.mutex.Lock()
|
||||
defer q.mutex.Unlock()
|
||||
|
||||
for _, workspaceResource := range q.workspaceResource {
|
||||
if workspaceResource.InstanceID.String == instanceID {
|
||||
return workspaceResource, nil
|
||||
}
|
||||
}
|
||||
return database.WorkspaceResource{}, sql.ErrNoRows
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) GetWorkspaceOwnerCountsByProjectIDs(_ context.Context, projectIDs []uuid.UUID) ([]database.GetWorkspaceOwnerCountsByProjectIDsRow, error) {
|
||||
counts := map[string]map[string]struct{}{}
|
||||
for _, projectID := range projectIDs {
|
||||
@@ -916,6 +928,7 @@ func (q *fakeQuerier) InsertWorkspaceResource(_ context.Context, arg database.In
|
||||
ID: arg.ID,
|
||||
CreatedAt: arg.CreatedAt,
|
||||
WorkspaceHistoryID: arg.WorkspaceHistoryID,
|
||||
InstanceID: arg.InstanceID,
|
||||
Type: arg.Type,
|
||||
Name: arg.Name,
|
||||
WorkspaceAgentToken: arg.WorkspaceAgentToken,
|
||||
|
||||
Generated
+1
@@ -276,6 +276,7 @@ CREATE TABLE workspace_resource (
|
||||
id uuid NOT NULL,
|
||||
created_at timestamp with time zone NOT NULL,
|
||||
workspace_history_id uuid NOT NULL,
|
||||
instance_id character varying(64),
|
||||
type character varying(256) NOT NULL,
|
||||
name character varying(64) NOT NULL,
|
||||
workspace_agent_token character varying(128) NOT NULL,
|
||||
|
||||
@@ -38,6 +38,9 @@ CREATE TABLE workspace_resource (
|
||||
id uuid NOT NULL UNIQUE,
|
||||
created_at timestamptz NOT NULL,
|
||||
workspace_history_id uuid NOT NULL REFERENCES workspace_history (id) ON DELETE CASCADE,
|
||||
-- A unique identifier for the resource. This can be used
|
||||
-- to exchange for an agent token with various providers.
|
||||
instance_id varchar(64),
|
||||
-- Resource type produced by a provisioner.
|
||||
-- eg. "google_compute_instance"
|
||||
type varchar(256) NOT NULL,
|
||||
|
||||
+8
-7
@@ -452,11 +452,12 @@ type WorkspaceHistory struct {
|
||||
}
|
||||
|
||||
type WorkspaceResource struct {
|
||||
ID uuid.UUID `db:"id" json:"id"`
|
||||
CreatedAt time.Time `db:"created_at" json:"created_at"`
|
||||
WorkspaceHistoryID uuid.UUID `db:"workspace_history_id" json:"workspace_history_id"`
|
||||
Type string `db:"type" json:"type"`
|
||||
Name string `db:"name" json:"name"`
|
||||
WorkspaceAgentToken string `db:"workspace_agent_token" json:"workspace_agent_token"`
|
||||
WorkspaceAgentID uuid.NullUUID `db:"workspace_agent_id" json:"workspace_agent_id"`
|
||||
ID uuid.UUID `db:"id" json:"id"`
|
||||
CreatedAt time.Time `db:"created_at" json:"created_at"`
|
||||
WorkspaceHistoryID uuid.UUID `db:"workspace_history_id" json:"workspace_history_id"`
|
||||
InstanceID sql.NullString `db:"instance_id" json:"instance_id"`
|
||||
Type string `db:"type" json:"type"`
|
||||
Name string `db:"name" json:"name"`
|
||||
WorkspaceAgentToken string `db:"workspace_agent_token" json:"workspace_agent_token"`
|
||||
WorkspaceAgentID uuid.NullUUID `db:"workspace_agent_id" json:"workspace_agent_id"`
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ type querier interface {
|
||||
GetWorkspaceHistoryByWorkspaceIDAndName(ctx context.Context, arg GetWorkspaceHistoryByWorkspaceIDAndNameParams) (WorkspaceHistory, error)
|
||||
GetWorkspaceHistoryByWorkspaceIDWithoutAfter(ctx context.Context, workspaceID uuid.UUID) (WorkspaceHistory, error)
|
||||
GetWorkspaceOwnerCountsByProjectIDs(ctx context.Context, ids []uuid.UUID) ([]GetWorkspaceOwnerCountsByProjectIDsRow, error)
|
||||
GetWorkspaceResourceByInstanceID(ctx context.Context, instanceID string) (WorkspaceResource, error)
|
||||
GetWorkspaceResourcesByHistoryID(ctx context.Context, workspaceHistoryID uuid.UUID) ([]WorkspaceResource, error)
|
||||
GetWorkspacesByProjectAndUserID(ctx context.Context, arg GetWorkspacesByProjectAndUserIDParams) ([]Workspace, error)
|
||||
GetWorkspacesByUserID(ctx context.Context, ownerID string) ([]Workspace, error)
|
||||
|
||||
+12
-1
@@ -328,6 +328,16 @@ WHERE
|
||||
LIMIT
|
||||
1;
|
||||
|
||||
-- name: GetWorkspaceResourceByInstanceID :one
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
workspace_resource
|
||||
WHERE
|
||||
instance_id = @instance_id :: text
|
||||
ORDER BY
|
||||
created_at;
|
||||
|
||||
-- name: GetWorkspaceResourcesByHistoryID :many
|
||||
SELECT
|
||||
*
|
||||
@@ -596,12 +606,13 @@ INSERT INTO
|
||||
id,
|
||||
created_at,
|
||||
workspace_history_id,
|
||||
instance_id,
|
||||
type,
|
||||
name,
|
||||
workspace_agent_token
|
||||
)
|
||||
VALUES
|
||||
($1, $2, $3, $4, $5, $6) RETURNING *;
|
||||
($1, $2, $3, $4, $5, $6, $7) RETURNING *;
|
||||
|
||||
-- name: UpdateAPIKeyByID :exec
|
||||
UPDATE
|
||||
|
||||
+40
-8
@@ -1111,9 +1111,36 @@ func (q *sqlQuerier) GetWorkspaceOwnerCountsByProjectIDs(ctx context.Context, id
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getWorkspaceResourceByInstanceID = `-- name: GetWorkspaceResourceByInstanceID :one
|
||||
SELECT
|
||||
id, created_at, workspace_history_id, instance_id, type, name, workspace_agent_token, workspace_agent_id
|
||||
FROM
|
||||
workspace_resource
|
||||
WHERE
|
||||
instance_id = $1 :: text
|
||||
ORDER BY
|
||||
created_at
|
||||
`
|
||||
|
||||
func (q *sqlQuerier) GetWorkspaceResourceByInstanceID(ctx context.Context, instanceID string) (WorkspaceResource, error) {
|
||||
row := q.db.QueryRowContext(ctx, getWorkspaceResourceByInstanceID, instanceID)
|
||||
var i WorkspaceResource
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.CreatedAt,
|
||||
&i.WorkspaceHistoryID,
|
||||
&i.InstanceID,
|
||||
&i.Type,
|
||||
&i.Name,
|
||||
&i.WorkspaceAgentToken,
|
||||
&i.WorkspaceAgentID,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getWorkspaceResourcesByHistoryID = `-- name: GetWorkspaceResourcesByHistoryID :many
|
||||
SELECT
|
||||
id, created_at, workspace_history_id, type, name, workspace_agent_token, workspace_agent_id
|
||||
id, created_at, workspace_history_id, instance_id, type, name, workspace_agent_token, workspace_agent_id
|
||||
FROM
|
||||
workspace_resource
|
||||
WHERE
|
||||
@@ -1133,6 +1160,7 @@ func (q *sqlQuerier) GetWorkspaceResourcesByHistoryID(ctx context.Context, works
|
||||
&i.ID,
|
||||
&i.CreatedAt,
|
||||
&i.WorkspaceHistoryID,
|
||||
&i.InstanceID,
|
||||
&i.Type,
|
||||
&i.Name,
|
||||
&i.WorkspaceAgentToken,
|
||||
@@ -2112,21 +2140,23 @@ INSERT INTO
|
||||
id,
|
||||
created_at,
|
||||
workspace_history_id,
|
||||
instance_id,
|
||||
type,
|
||||
name,
|
||||
workspace_agent_token
|
||||
)
|
||||
VALUES
|
||||
($1, $2, $3, $4, $5, $6) RETURNING id, created_at, workspace_history_id, type, name, workspace_agent_token, workspace_agent_id
|
||||
($1, $2, $3, $4, $5, $6, $7) RETURNING id, created_at, workspace_history_id, instance_id, type, name, workspace_agent_token, workspace_agent_id
|
||||
`
|
||||
|
||||
type InsertWorkspaceResourceParams struct {
|
||||
ID uuid.UUID `db:"id" json:"id"`
|
||||
CreatedAt time.Time `db:"created_at" json:"created_at"`
|
||||
WorkspaceHistoryID uuid.UUID `db:"workspace_history_id" json:"workspace_history_id"`
|
||||
Type string `db:"type" json:"type"`
|
||||
Name string `db:"name" json:"name"`
|
||||
WorkspaceAgentToken string `db:"workspace_agent_token" json:"workspace_agent_token"`
|
||||
ID uuid.UUID `db:"id" json:"id"`
|
||||
CreatedAt time.Time `db:"created_at" json:"created_at"`
|
||||
WorkspaceHistoryID uuid.UUID `db:"workspace_history_id" json:"workspace_history_id"`
|
||||
InstanceID sql.NullString `db:"instance_id" json:"instance_id"`
|
||||
Type string `db:"type" json:"type"`
|
||||
Name string `db:"name" json:"name"`
|
||||
WorkspaceAgentToken string `db:"workspace_agent_token" json:"workspace_agent_token"`
|
||||
}
|
||||
|
||||
func (q *sqlQuerier) InsertWorkspaceResource(ctx context.Context, arg InsertWorkspaceResourceParams) (WorkspaceResource, error) {
|
||||
@@ -2134,6 +2164,7 @@ func (q *sqlQuerier) InsertWorkspaceResource(ctx context.Context, arg InsertWork
|
||||
arg.ID,
|
||||
arg.CreatedAt,
|
||||
arg.WorkspaceHistoryID,
|
||||
arg.InstanceID,
|
||||
arg.Type,
|
||||
arg.Name,
|
||||
arg.WorkspaceAgentToken,
|
||||
@@ -2143,6 +2174,7 @@ func (q *sqlQuerier) InsertWorkspaceResource(ctx context.Context, arg InsertWork
|
||||
&i.ID,
|
||||
&i.CreatedAt,
|
||||
&i.WorkspaceHistoryID,
|
||||
&i.InstanceID,
|
||||
&i.Type,
|
||||
&i.Name,
|
||||
&i.WorkspaceAgentToken,
|
||||
|
||||
Reference in New Issue
Block a user