8000 feat: app sharing (now open source!) by deansheather · Pull Request #4378 · coder/coder · GitHub
[go: up one dir, main page]

Skip to content

feat: app sharing (now open source!) #4378

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 16 commits into from
Oct 14, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Merge branch 'main' into dean/app-sharing
  • Loading branch information
deansheather committed Oct 12, 2022
commit 40300a7171232378587f690ac30e004190275462
63 changes: 0 additions & 63 deletions coderd/users.go
Original file line number Diff line number Diff line change
Expand Up @@ -938,69 +938,6 @@ func (api *API) postLogin(rw http.ResponseWriter, r *http.Request) {
})
}

// Creates a new session key, used for logging in via the CLI.
func (api *API) postAPIKey(rw http.ResponseWriter, r *http.Request) {
ctx := r.Context()
user := httpmw.UserParam(r)

if !api.Authorize(r, rbac.ActionCreate, rbac.ResourceAPIKey.WithOwner(user.ID.String())) {
httpapi.ResourceNotFound(rw)
return
}

lifeTime := time.Hour * 24 * 7
cookie, err := api.createAPIKey(ctx, createAPIKeyParams{
UserID: user.ID,
LoginType: database.LoginTypePassword,
RemoteAddr: r.RemoteAddr,
// All API generated keys will last 1 week. Browser login tokens have
// a shorter life.
ExpiresAt: database.Now().Add(lifeTime),
LifetimeSeconds: int64(lifeTime.Seconds()),
})
if err != nil {
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Failed to create API key.",
Detail: err.Error(),
})
return
}

// We intentionally do not set the cookie on the response here.
// Setting the cookie will couple the browser session to the API
// key we return here, meaning logging out of the website would
// invalid your CLI key.
httpapi.Write(ctx, rw, http.StatusCreated, codersdk.GenerateAPIKeyResponse{Key: cookie.Value})
}

func (api *API) apiKey(rw http.ResponseWriter, r *http.Request) {
var (
ctx = r.Context()
user = httpmw.UserParam(r)
)

if !api.Authorize(r, rbac.ActionRead, rbac.ResourceAPIKey.WithOwner(user.ID.String())) {
httpapi.ResourceNotFound(rw)
return
}

keyID := chi.URLParam(r, "keyid")
key, err := api.Database.GetAPIKeyByID(ctx, keyID)
if errors.Is(err, sql.ErrNoRows) {
httpapi.ResourceNotFound(rw)
return
}
if err != nil {
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching API key.",
Detail: err.Error(),
})
return
}

httpapi.Write(ctx, rw, http.StatusOK, convertAPIKey(key))
}

// Clear the user's session cookie.
func (api *API) postLogout(rw http.ResponseWriter, r *http.Request) {
ctx := r.Context()
Expand Down
6 changes: 3 additions & 3 deletions coderd/workspaceapps.go
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ func (api *API) authorizeWorkspaceApp(r *http.Request, sharingLevel database.App
// Regardless of share level or whether it's enabled or not, the owner of
// the workspace can always access applications (as long as their key's
// scope allows it).
err := api.Authorizer.ByRoleName(ctx, roles.ID.String(), roles.Roles, roles.Scope.ToRBAC(), rbac.ActionCreate, workspace.ApplicationConnectRBAC())
err := api.Authorizer.ByRoleName(ctx, roles.ID.String(), roles.Roles, roles.Scope.ToRBAC(), []string{}, rbac.ActionCreate, workspace.ApplicationConnectRBAC())
if err == nil {
return true, nil
}
Expand All @@ -327,7 +327,7 @@ func (api *API) authorizeWorkspaceApp(r *http.Request, sharingLevel database.App
return false, xerrors.Errorf("get template %q: %w", workspace.TemplateID, err)
}

err = api.Authorizer.ByRoleName(ctx, roles.ID.String(), roles.Roles, roles.Scope.ToRBAC(), rbac.ActionRead, template.RBACObject())
err = api.Authorizer.ByRoleName(ctx, roles.ID.String(), roles.Roles, roles.Scope.ToRBAC(), []string{}, rbac.ActionRead, template.RBACObject())
if err == nil {
return true, nil
}
Expand All @@ -337,7 +337,7 @@ func (api *API) authorizeWorkspaceApp(r *http.Request, sharingLevel database.App
// workspaces. This ensures that the key's scope has permission to
// connect to workspace apps.
object := rbac.ResourceWorkspaceApplicationConnect.WithOwner(roles.ID.String())
err := api.Authorizer.ByRoleName(ctx, roles.ID.String(), roles.Roles, roles.Scope.ToRBAC(), rbac.ActionCreate, object)
err := api.Authorizer.ByRoleName(ctx, roles.ID.String(), roles.Roles, roles.Scope.ToRBAC(), []string{}, rbac.ActionCreate, object)
if err == nil {
return true, nil
}
Expand Down
10 changes: 1 addition & 9 deletions enterprise/cli/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,7 @@ func server() *cobra.Command {
return api.AGPL, nil
})

enterpriseOnly := cliui.Styles.Keyword.Render("This is an Enterprise feature. Contact sales@coder.com for licensing")
cliflag.BoolVarP(cmd.Flags(), &auditLogging, "audit-logging", "", "CODER_AUDIT_LOGGING", true,
"Specifies whether audit logging is enabled. "+enterpriseOnly)
cliflag.BoolVarP(cmd.Flags(), &browserOnly, "browser-only", "", "CODER_BROWSER_ONLY", false,
"Whether Coder only allows connections to workspaces via the browser. "+enterpriseOnly)
cliflag.StringVarP(cmd.Flags(), &scimAuthHeader, "scim-auth-header", "", "CODER_SCIM_API_KEY", "",
"Enables SCIM and sets the authentication header for the built-in SCIM server. New users are automatically created with OIDC authentication. "+enterpriseOnly)
cliflag.IntVarP(cmd.Flags(), &userWorkspaceQuota, "user-workspace-quota", "", "CODER_USER_WORKSPACE_QUOTA", 0,
"A positive number applies a limit on how many workspaces each user can create. "+enterpriseOnly)
deployment.AttachFlags(cmd.Flags(), dflags, true)

return cmd
}
51 changes: 14 additions & 37 deletions enterprise/coderd/coderd.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"github.com/coder/coder/coderd/httpapi"
"github.com/coder/coder/coderd/httpmw"
"github.com/coder/coder/coderd/rbac"
"github.com/coder/coder/coderd/workspacequota"
"github.com/coder/coder/codersdk"
"github.com/coder/coder/enterprise/audit"
"github.com/coder/coder/enterprise/audit/backends"
Expand All @@ -42,20 +43,8 @@ func New(ctx context.Context, options *Options) (*API, error) {
}
ctx, cancelFunc := context.WithCancel(ctx)
api := &API{
AGPL: coderd.New(options.Options),
Options: options,

entitlements: entitlements{
activeUsers: codersdk.Feature{
Entitlement: codersdk.EntitlementNotEntitled,
Enabled: false,
},
auditLogs: codersdk.EntitlementNotEntitled,
browserOnly: codersdk.EntitlementNotEntitled,
scim: codersdk.EntitlementNotEntitled,
workspaceQuota: codersdk.EntitlementNotEntitled,
applicationSharing: codersdk.EntitlementNotEntitled,
},
AGPL: coderd.New(options.Options),
Options: options,
cancelEntitlementsLoop: cancelFunc,
}
oauthConfigs := &httpmw.OAuth2Configs{
Expand Down Expand Up @@ -157,17 +146,7 @@ type API struct {

cancelEntitlementsLoop func()
entitlementsMu sync.RWMutex
entitlements entitlements
}

type entitlements struct {
hasLicense bool
activeUsers codersdk.Feature
auditLogs codersdk.Entitlement
browserOnly codersdk.Entitlement
scim codersdk.Entitlement
workspaceQuota codersdk.Entitlement
applicationSharing codersdk.Entitlement
entitlements codersdk.Entitlements
}

func (api *API) Close() error {
Expand All @@ -190,18 +169,16 @@ func (api *API) updateEntitlements(ctx context.Context) error {
return err
}

// Default all entitlements to be disabled.
entitlements := entitlements{
hasLicense: false,
activeUsers: codersdk.Feature{
Enabled: false,
Entitlement: codersdk.EntitlementNotEntitled,
},
auditLogs: codersdk.EntitlementNotEntitled,
scim: codersdk.EntitlementNotEntitled,
browserOnly: codersdk.EntitlementNotEntitled,
workspaceQuota: codersdk.EntitlementNotEntitled,
applicationSharing: codersdk.EntitlementNotEntitled,
featureChanged := func(featureName string) (changed bool, enabled bool) {
if api.entitlements.Features == nil {
return true, entitlements.Features[featureName].Enabled
}
oldFeature := api.entitlements.Features[featureName]
newFeature := entitlements.Features[featureName]
if oldFeature.Enabled != newFeature.Enabled {
return true, newFeature.Enabled
}
return false, newFeature.Enabled
}

if changed, enabled := featureChanged(codersdk.FeatureAuditLog); changed {
Expand Down
6 changes: 5 additions & 1 deletion site/src/api/typesGenerated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -933,7 +933,11 @@ export type WorkspaceAppHealth =
| "unhealthy"

// From codersdk/workspaceapps.go
export type WorkspaceAppSharingLevel = "authenticated" | "owner" | "public" | "template"
export type WorkspaceAppSharingLevel =
| "authenticated"
| "owner"
| "public"
| "template"

// From codersdk/workspacebuilds.go
export type WorkspaceStatus =
Expand Down
You are viewing a condensed version of this merge commit. You can view the full changes here.
0