Movatterモバイル変換


[0]ホーム

URL:


Alert GO-2024-3228: Coder vulnerable to post-auth URL redirection to untrusted site ('Open Redirect') in github.com/coder/coder
Notice  The highest tagged major version isv2.

workspaceapps

package
v0.27.3Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 1, 2023 License:AGPL-3.0Imports:33Imported by:0

Details

Repository

github.com/coder/coder

Links

Documentation

Index

Constants

View Source
const (// TODO(@deansheather): configurable expiryDefaultTokenExpiry =time.Minute// RedirectURIQueryParam is the query param for the app URL to be passed// back to the API auth endpoint on the main access URL.RedirectURIQueryParam = "redirect_uri")
View Source
const (// This needs to be a super unique query parameter because we don't want to// conflict with query parameters that users may use.//nolint:gosecSubdomainProxyAPIKeyParam = "coder_application_connect_api_key_35e783")

Variables

This section is empty.

Functions

funcWebsocketNetConnadded inv0.22.0

func WebsocketNetConn(ctxcontext.Context, conn *websocket.Conn, msgTypewebsocket.MessageType) (context.Context,net.Conn)

WebsocketNetConn wraps websocket.NetConn and returns a context thatis tied to the parent context and the lifetime of the conn. Any errorduring read or write will cancel the context, but not close theconn. Close should be called to release context resources.

funcWriteWorkspaceApp404added inv0.22.0

func WriteWorkspaceApp404(logslog.Logger, accessURL *url.URL, rwhttp.ResponseWriter, r *http.Request, appReq *Request, msgstring)

WriteWorkspaceApp404 writes a HTML 404 error page for a workspace app. IfappReq is not nil, it will be used to log the request details at debug level.

funcWriteWorkspaceApp500added inv0.22.0

func WriteWorkspaceApp500(logslog.Logger, accessURL *url.URL, rwhttp.ResponseWriter, r *http.Request, appReq *Request, errerror, msgstring)

WriteWorkspaceApp500 writes a HTML 500 error page for a workspace app. IfappReq is not nil, it's fields will be added to the logged error message.

funcWriteWorkspaceAppOfflineadded inv0.22.0

func WriteWorkspaceAppOffline(logslog.Logger, accessURL *url.URL, rwhttp.ResponseWriter, r *http.Request, appReq *Request, msgstring)

WriteWorkspaceAppOffline writes a HTML 502 error page for a workspace app. IfappReq is not nil, it will be used to log the request details at debug level.

Types

typeAccessMethod

type AccessMethodstring
const (AccessMethodPathAccessMethod = "path"AccessMethodSubdomainAccessMethod = "subdomain"// AccessMethodTerminal is special since it's not a real app and only// applies to the PTY endpoint on the API.AccessMethodTerminalAccessMethod = "terminal")

typeAgentProvideradded inv0.26.2

type AgentProvider interface {// ReverseProxy returns an httputil.ReverseProxy for proxying HTTP requests// to the specified agent.//// TODO: after wsconncache is deleted this doesn't need to return an error.ReverseProxy(targetURL, dashboardURL *url.URL, agentIDuuid.UUID) (_ *httputil.ReverseProxy, release func(), _error)// AgentConn returns a new connection to the specified agent.//// TODO: after wsconncache is deleted this doesn't need to return a release// func.AgentConn(ctxcontext.Context, agentIDuuid.UUID) (_ *codersdk.WorkspaceAgentConn, release func(), _error)Close()error}

typeDBTokenProvideradded inv0.22.0

type DBTokenProvider struct {Loggerslog.Logger// DashboardURL is the main dashboard access URL for error pages.DashboardURL                  *url.URLAuthorizerrbac.AuthorizerDatabasedatabase.StoreDeploymentValues              *codersdk.DeploymentValuesOAuth2Configs                 *httpmw.OAuth2ConfigsWorkspaceAgentInactiveTimeouttime.DurationSigningKeySecurityKey}

DBTokenProvider provides authentication and authorization for workspace appsby querying the database if the request is missing a valid token.

func (*DBTokenProvider)FromRequestadded inv0.23.0

func (p *DBTokenProvider) FromRequest(r *http.Request) (*SignedToken,bool)

func (*DBTokenProvider)Issueadded inv0.23.0

typeEncryptedAPIKeyPayloadadded inv0.22.0

type EncryptedAPIKeyPayload struct {APIKeystring    `json:"api_key"`ExpiresAttime.Time `json:"expires_at"`}

typeIssueTokenRequestadded inv0.23.0

type IssueTokenRequest struct {AppRequestRequest `json:"app_request"`// PathAppBaseURL is required.PathAppBaseURLstring `json:"path_app_base_url"`// AppHostname is the optional hostname for subdomain apps on the external// proxy. It must start with an asterisk.AppHostnamestring `json:"app_hostname"`// AppPath is the path of the user underneath the app base path.AppPathstring `json:"app_path"`// AppQuery is the query parameters the user provided in the app request.AppQuerystring `json:"app_query"`// SessionToken is the session token provided by the user.SessionTokenstring `json:"session_token"`}

func (IssueTokenRequest)AppBaseURLadded inv0.23.0

func (rIssueTokenRequest) AppBaseURL() (*url.URL,error)

AppBaseURL returns the base URL of this specific app request. An error isreturned if a subdomain app hostname is not provided but the app is asubdomain app.

typeRequest

type Request struct {AccessMethodAccessMethod `json:"access_method"`// BasePath of the app. For path apps, this is the path prefix in the router// for this particular app. For subdomain apps, this should be "/". This is// used for setting the cookie path.BasePathstring `json:"base_path"`// For the following fields, if the AccessMethod is AccessMethodTerminal,// then only AgentNameOrID may be set and it must be a UUID. The other// fields must be left blank.UsernameOrIDstring `json:"username_or_id"`// WorkspaceAndAgent xor WorkspaceNameOrID are required.WorkspaceAndAgentstring `json:"-"`// "workspace" or "workspace.agent"WorkspaceNameOrIDstring `json:"workspace_name_or_id"`// AgentNameOrID is not required if the workspace has only one agent.AgentNameOrIDstring `json:"agent_name_or_id"`AppSlugOrPortstring `json:"app_slug_or_port"`}

func (Request)Normalizeadded inv0.22.0

func (rRequest) Normalize()Request

Normalize replaces WorkspaceAndAgent with WorkspaceNameOrID andAgentNameOrID. This must be called before Validate.

func (Request)Validate

func (rRequest) Validate()error

Validate ensures the request is correct and contains the necessaryparameters.

typeResolveRequestOptionsadded inv0.23.0

type ResolveRequestOptions struct {Loggerslog.LoggerSignedTokenProviderSignedTokenProviderDashboardURL   *url.URLPathAppBaseURL *url.URLAppHostnamestringAppRequestRequest// TODO: Replace these 2 fields with a "BrowserURL" field which is used for// redirecting the user back to their initial request after authenticating.// AppPath is the path under the app that was hit.AppPathstring// AppQuery is the raw query of the request.AppQuerystring}

typeSecurityKeyadded inv0.22.0

type SecurityKey [96]byte

SecurityKey is used for signing and encrypting app tokens and API keys.

The first 64 bytes of the key are used for signing tokens with HMAC-SHA256,and the last 32 bytes are used for encrypting API keys with AES-256-GCM.We use a single key for both operations to avoid having to store and managetwo keys.

funcKeyFromStringadded inv0.22.0

func KeyFromString(strstring) (SecurityKey,error)

func (SecurityKey)DecryptAPIKeyadded inv0.22.0

func (kSecurityKey) DecryptAPIKey(encryptedAPIKeystring) (string,error)

DecryptAPIKey undoes EncryptAPIKey and is used in the subdomain app handler.

func (SecurityKey)EncryptAPIKeyadded inv0.22.0

func (kSecurityKey) EncryptAPIKey(payloadEncryptedAPIKeyPayload) (string,error)

EncryptAPIKey encrypts an API key for subdomain token smuggling.

func (SecurityKey)SignTokenadded inv0.22.0

func (kSecurityKey) SignToken(payloadSignedToken) (string,error)

SignToken generates a signed workspace app token with the given payload. Ifthe payload doesn't have an expiry, it will be set to the current time plusthe default expiry.

func (SecurityKey)Stringadded inv0.23.0

func (kSecurityKey) String()string

func (SecurityKey)VerifySignedTokenadded inv0.22.0

func (kSecurityKey) VerifySignedToken(strstring) (SignedToken,error)

VerifySignedToken parses a signed workspace app token with the given key andreturns the payload. If the token is invalid or expired, an error isreturned.

typeServeradded inv0.22.0

type Server struct {Loggerslog.Logger// DashboardURL should be a url to the coderd dashboard. This can be the// same as the AccessURL if the Server is embedded.DashboardURL *url.URLAccessURL    *url.URL// Hostname should be the wildcard hostname to use for workspace// applications INCLUDING the asterisk, (optional) suffix and leading dot.// It will use the same scheme and port number as the access URL.// E.g. "*.apps.coder.com" or "*-apps.coder.com".Hostnamestring// HostnameRegex contains the regex version of Hostname as generated by// httpapi.CompileHostnamePattern(). It MUST be set if Hostname is set.HostnameRegex *regexp.RegexpRealIPConfig  *httpmw.RealIPConfigSignedTokenProviderSignedTokenProviderAppSecurityKeySecurityKey// DisablePathApps disables path-based apps. This is a security feature as path// based apps share the same cookie as the dashboard, and are susceptible to XSS// by a malicious workspace app.//// Subdomain apps are safer with their cookies scoped to the subdomain, and XSS// calls to the dashboard are not possible due to CORs.DisablePathAppsboolSecureAuthCookieboolAgentProviderAgentProvider// contains filtered or unexported fields}

Server serves workspace apps endpoints, including:- Path-based apps- Subdomain app middleware- Workspace reconnecting-pty (aka. web terminal)

func (*Server)Attachadded inv0.22.0

func (s *Server) Attach(r chi.Router)

func (*Server)Closeadded inv0.22.0

func (s *Server) Close()error

Close waits for all reconnecting-pty WebSocket connections to drain beforereturning.

func (*Server)HandleSubdomainadded inv0.23.0

func (s *Server) HandleSubdomain(middlewares ...func(http.Handler)http.Handler) func(http.Handler)http.Handler

HandleSubdomain handles subdomain-based application proxy requests (aka.DevURLs in Coder V1).

There are a lot of paths here:

  1. If api.Hostname is not set then we pass on.
  2. If we can't read the request hostname then we return a 400.
  3. If the request hostname matches api.AccessURL then we pass on.
  4. We split the subdomain into the subdomain and the "rest". If there are noperiods in the hostname then we pass on.
  5. We parse the subdomain into a httpapi.ApplicationURL struct. If weencounter an error:a. If the "rest" does not match api.Hostname then we pass on;b. Otherwise, we return a 400.
  6. Finally, we verify that the "rest" matches api.Hostname, else wereturn a 404.

Rationales for each of the above steps:

  1. We pass on if api.Hostname is not set to avoid returning any errors if`--app-hostname` is not configured.
  2. Every request should have a valid Host header anyways.
  3. We pass on if the request hostname matches api.AccessURL so we cansupport having the access URL be at the same level as the applicationbase hostname.
  4. We pass on if there are no periods in the hostname as application URLsmust be a subdomain of a hostname, which implies there must be at leastone period.
  5. a. If the request subdomain is not a valid application URL, and the"rest" does not match api.Hostname, then it is very unlikely thatthe request was intended for this handler. We pass on.b. If the request subdomain is not a valid application URL, but the"rest" matches api.Hostname, then we return a 400 because therequest is probably a typo or something.
  6. We finally verify that the "rest" matches api.Hostname for securitypurposes regarding re-authentication and application proxy sessiontokens.

typeSignedTokenadded inv0.22.0

type SignedToken struct {// Request details.Request `json:"request"`// Trusted resolved details.Expirytime.Time `json:"expiry"`// set by GenerateToken if unsetUserIDuuid.UUID `json:"user_id"`WorkspaceIDuuid.UUID `json:"workspace_id"`AgentIDuuid.UUID `json:"agent_id"`AppURLstring    `json:"app_url"`}

SignedToken is the struct data contained inside a workspace app JWE. Itcontains the details of the workspace app that the token is valid for toavoid database queries.

funcFromRequestadded inv0.23.0

func FromRequest(r *http.Request, keySecurityKey) (*SignedToken,bool)

FromRequest returns the signed token from the request, if it exists and isvalid. The caller must check that the token matches the request.

funcResolveRequestadded inv0.22.0

func (SignedToken)MatchesRequestadded inv0.22.0

func (tSignedToken) MatchesRequest(reqRequest)bool

MatchesRequest returns true if the token matches the request. Any token thatdoes not match the request should be considered invalid.

typeSignedTokenProvideradded inv0.22.0

type SignedTokenProvider interface {// FromRequest returns a parsed token from the request. If the request does// not contain a signed app token or is is invalid (expired, invalid// signature, etc.), it returns false.FromRequest(r *http.Request) (*SignedToken,bool)// Issue mints a new token for the given app request. It uses the long-lived// session token in the HTTP request to authenticate and authorize the// client for the given workspace app. The token is returned in struct and// string form. The string form should be written as a cookie.//// If the request is invalid or the user is not authorized to access the// app, false is returned. An error page is written to the response writer// in this case.Issue(ctxcontext.Context, rwhttp.ResponseWriter, r *http.Request, appReqIssueTokenRequest) (*SignedToken,string,bool)}

SignedTokenProvider provides signed workspace app tokens (aka. app tickets).

funcNewDBTokenProvideradded inv0.22.0

func NewDBTokenProvider(logslog.Logger, accessURL *url.URL, authzrbac.Authorizer, dbdatabase.Store, cfg *codersdk.DeploymentValues, oauth2Cfgs *httpmw.OAuth2Configs, workspaceAgentInactiveTimeouttime.Duration, signingKeySecurityKey)SignedTokenProvider

Source Files

View all Source files

Directories

PathSynopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f orF : Jump to
y orY : Canonical URL
go.dev uses cookies from Google to deliver and enhance the quality of its services and to analyze traffic.Learn more.

[8]ページ先頭

©2009-2025 Movatter.jp