server

package
v0.12.2 Latest Latest
Warning

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

Go to latest
Published: Feb 23, 2026 License: MIT Imports: 38 Imported by: 2

Documentation

Overview

Package server contains code for serving the Funnel API, and accessing database backends.

Index

Constants

View Source
const (
	AccessAll          = "All"
	AccessOwner        = "Owner"
	AccessOwnerOrAdmin = "OwnerOrAdmin"
)
View Source
const InternalCallKey contextKey = "internalCall"

Variables

View Source
var (
	UserInfoKey = userInfoContextKey("user-info")
)

Functions

func GetUsername

func GetUsername(ctx context.Context) string

func NewMarshaler

func NewMarshaler() runtime.Marshaler

Types

type Authentication

type Authentication struct {
	// contains filtered or unexported fields
}

func NewAuthentication

func NewAuthentication(
	creds []*config.BasicCredential,
	oidc *config.OidcAuth,
	taskAccess string,
) *Authentication

func (*Authentication) EchoTokenHandler

func (a *Authentication) EchoTokenHandler(w http.ResponseWriter, req *http.Request)

HTTP request handler for the /login/token endpoint. In case of OIDC enabled, prints the JWT from the sent cookie. In all other cases, an empty HTTP 200 response.

func (*Authentication) Interceptor

func (a *Authentication) Interceptor(
	ctx context.Context,
	req interface{},
	info *grpc.UnaryServerInfo,
	handler grpc.UnaryHandler) (interface{}, error)

Return a new gRPC interceptor function that authorizes RPCs.

func (*Authentication) LoginHandler

func (a *Authentication) LoginHandler(w http.ResponseWriter, req *http.Request)

HTTP request handler for the /login endpoint. Initiates user authentication flow based on the configuration (OIDC, Basic, none).

type CustomMarshal

type CustomMarshal struct {
	// contains filtered or unexported fields
}

CustomMarshal is a custom marshaler for the GRPC gateway that returns the required fields based on the View value: - View_MINIMAL: returns only the id and state fields - View_BASIC: returns the id, state, creation_time, description, name, inputs, outputs, resources, tags, volumes, executors, and logs fields - View_FULL: returns all fields

This could be improved by updating the generated protobuf code to include the View field in the Task struct Related discussion: https://github.com/ohsu-comp-bio/funnel/pull/716#discussion_r1375155983

func (*CustomMarshal) ContentType

func (marshal *CustomMarshal) ContentType(i interface{}) string

ContentType return content type of marshler

func (*CustomMarshal) DetectView

func (mclean *CustomMarshal) DetectView(task *tes.Task) (tes.View, error)

func (*CustomMarshal) Marshal

func (mclean *CustomMarshal) Marshal(v interface{}) ([]byte, error)

Marshal serializes v into a JSON encoded byte array. If v is of type `proto.Message` the then field "result" is extracted and returned by itself. This is mainly to get around a weird behavior of the GRPC gateway streaming output

func (*CustomMarshal) MarshalList

func (mclean *CustomMarshal) MarshalList(list *tes.ListTasksResponse) ([]byte, error)

func (*CustomMarshal) MarshalTask

func (mclean *CustomMarshal) MarshalTask(task *tes.Task) ([]byte, error)

func (*CustomMarshal) NewDecoder

func (mclean *CustomMarshal) NewDecoder(r io.Reader) runtime.Decoder

NewDecoder shims runtime.Marshaler.NewDecoder

func (*CustomMarshal) NewEncoder

func (mclean *CustomMarshal) NewEncoder(w io.Writer) runtime.Encoder

NewEncoder shims runtime.Marshaler.NewEncoder

func (*CustomMarshal) TranslateTask

func (mclean *CustomMarshal) TranslateTask(task *tes.Task, view tes.View) interface{}

func (*CustomMarshal) Unmarshal

func (mclean *CustomMarshal) Unmarshal(data []byte, v interface{}) error

Unmarshal shims runtime.Marshaler.Unmarshal

type IntrospectionResponse

type IntrospectionResponse struct {
	Active bool `json:"active"`
}

JSON structure of the OIDC token introspection response (only some fields)

type JSONError

type JSONError struct {
	Error string `json:"error"`
}

type OidcConfig

type OidcConfig struct {
	// contains filtered or unexported fields
}

OIDC configuration structure used for validating input from request.

func (*OidcConfig) Authorize

func (c *OidcConfig) Authorize(authorization string) *UserInfo

func (*OidcConfig) EchoTokenHandler

func (c *OidcConfig) EchoTokenHandler(w http.ResponseWriter, req *http.Request)

Prints the JWT from the cookie value in the response body. Missing cookie value results in HTTP 404 response. Frontend uses this endpoint for fetching the JWT for performing API requests. Frontend cannot access the cookie directly as it is HttpOnly. Although the API could also obtain the JWT from the cookie, it would be harder to maintain, especially in the gRPC code. Therefore, the frontend uses this login-token endpoint to establish JWT first, and then provide the JWT value in the Authorization header of API requests.

func (*OidcConfig) HandleAuthCode

func (c *OidcConfig) HandleAuthCode(w http.ResponseWriter, req *http.Request)

func (*OidcConfig) ParseJwtSubject

func (c *OidcConfig) ParseJwtSubject(jwtString string) string

func (*OidcConfig) RedirectToLogin

func (c *OidcConfig) RedirectToLogin(w http.ResponseWriter, req *http.Request)

type OidcRemoteConfig

type OidcRemoteConfig struct {
	Issuer                string `json:"issuer"`
	JwksURI               string `json:"jwks_uri"`
	AuthorizationEndpoint string `json:"authorization_endpoint"`
	IntrospectionEndpoint string `json:"introspection_endpoint"`
	TokenEndpoint         string `json:"token_endpoint"`
}

JSON structure of the OIDC configuration (only some fields)

type Server

type Server struct {
	RPCAddress       string
	HTTPPort         string
	BasicAuth        []*config.BasicCredential
	OidcAuth         *config.OidcAuth
	TaskAccess       string
	Tasks            tes.TaskServiceServer
	Events           events.EventServiceServer
	Nodes            scheduler.SchedulerServiceServer
	DisableHTTPCache bool
	Log              *logger.Logger
	Plugins          *config.Plugins
}

Server represents a Funnel server. The server handles RPC traffic via gRPC, HTTP traffic for the TES API, and also serves the web dashboard.

func (*Server) Serve

func (s *Server) Serve(pctx context.Context) error

Serve starts the server and does not block. This will open TCP ports for both RPC and HTTP.

type TaskService

type TaskService struct {
	tes.UnimplementedTaskServiceServer
	Name          string
	Event         events.Writer
	Compute       events.Computer
	Read          tes.ReadOnlyServer
	Log           *logger.Logger
	Config        *config.Config
	Plugin        shared.Authorize
	PluginManager *shared.Manager
}

TaskService is a wrapper which handles common TES Task Service operations, such as initializing a task when CreateTask is called. The TaskService is backed by two parts: a read API which provides the GetTask and ListTasks endpoints, and a write API which implements the events.Writer interface. Task creation and cancelation is managed by writing events to underlying event writer.

This makes it easier to define task service backends for new databases, and ensures that common operations are handled consistently, such as setting IDs, handling 404s, GetServiceInfo, etc.

func (*TaskService) CancelTask

CancelTask cancels a task

func (*TaskService) CreateTask

func (ts *TaskService) CreateTask(ctx context.Context, task *tes.Task) (*tes.CreateTaskResponse, error)

CreateTask provides an HTTP/gRPC endpoint for creating a task. This is part of the TES implementation.

func (*TaskService) DoPluginAction added in v0.11.4

func (ts *TaskService) DoPluginAction(ctx context.Context, task *tes.Task, taskType proto.Type) (*proto.JobResponse, error)

LoadPlugins loads plugins for a task.

func (*TaskService) GetServiceInfo

func (ts *TaskService) GetServiceInfo(ctx context.Context, info *tes.GetServiceInfoRequest) (*tes.ServiceInfo, error)

GetServiceInfo returns service metadata.

func (*TaskService) GetTask

func (ts *TaskService) GetTask(ctx context.Context, req *tes.GetTaskRequest) (*tes.Task, error)

GetTask calls GetTask on the underlying tes.ReadOnlyServer. If the underlying server returns tes.ErrNotFound, TaskService will handle returning the appropriate gRPC error.

func (*TaskService) HandleDoPluginAction added in v0.11.4

func (ts *TaskService) HandleDoPluginAction(ctx context.Context, task *tes.Task, taskType proto.Type) (*proto.JobResponse, error)

func (*TaskService) ListTasks

ListTasks calls ListTasks on the underlying tes.ReadOnlyServer.

type UserInfo

type UserInfo struct {
	// Public users are non-authenticated, in case Funnel configuration does
	// not require OIDC nor Basic authentication.
	IsPublic bool
	// Administrators are defined by the configuration file:
	// 1) Basic-authentication: a user with the `Admin: true` property.
	// 2) OIDC-authentication: one of the usernames under the `Admins` property.
	IsAdmin bool
	// Username of an authenticated user (subject field from JWT).
	Username string
	// In case of OIDC authentication, the provided Bearer token, which can be
	// used when requesting task input data.
	Token string
}

Extracted info about the current user, which is exposed through Context.

func GetUser

func GetUser(ctx context.Context) *UserInfo

func (*UserInfo) CanSeeAllTasks

func (u *UserInfo) CanSeeAllTasks() bool

Reports whether the current user can access all tasks considering the configuration (Server.TaskAccess) and whether the user has Admin status. If the result is false, data access must be verified (see: IsAccessible).

func (*UserInfo) IsAccessible

func (u *UserInfo) IsAccessible(dataOwner string) bool

Reports whether the current user can access data with the specified owner. Evaluation depends on configuration (Server.TaskAccess), current username, and the username recorded in the task. For public users and unknown task owners, the username is an empty string.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL