quarterdeck

package
v0.12.6 Latest Latest
Warning

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

Go to latest
Published: Apr 17, 2024 License: BSD-3-Clause Imports: 42 Imported by: 0

Documentation

Index

Constants

View Source
const (
	UserHuman   = "human"
	UserMachine = "machine"
)
View Source
const HeaderUserAgent = "User-Agent"
View Source
const OneTimeAccessDuration = 5 * time.Minute
View Source
const ServiceName = "quarterdeck"

Variables

This section is empty.

Functions

This section is empty.

Types

type Server

type Server struct {
	service.Server
	// contains filtered or unexported fields
}

Server implements the service.Service interface and provides handlers to respond to Quarterdeck-specific API routes and requests.

func New

func New(conf config.Config) (s *Server, err error)

func (*Server) APIKeyCreate

func (s *Server) APIKeyCreate(c *gin.Context)

Create an API Key for the specified project with the specified permissions. Most of the fields on an APIKey cannot be updated (with the exception of the API Key name). This method is the only way a user can set a keys projectID, createdBy, source, and permissions fields. All other fields are managed by Quarterdeck.

NOTE: a response to this request is the only time the key secret is exposed publicly. The secret is stored as an argon2 derived key so it is impossible for Quarterdeck to return the key to the user at any point after this method is called. The client must be responsible for recording the key and warning the user that this is the one time that it will be displayed. If the user loses the key, they will have to revoke (delete) the key and generate a new one.

func (*Server) APIKeyDelete

func (s *Server) APIKeyDelete(c *gin.Context)

Delete an APIKey by its ID. This endpoint allows user to revoke APIKeys so that they can no longer be used for authentication with Quarterdeck. The APIKey is deleted if its ID can be parsed, it is found in the database, and the user OrgID claims match the organization the APIKey is assigned to. Otherwise this endpoint will return a 404 Not Found error if it cannot correctly retrieve the key. If the API Key is successfully deleted, this endpoint returns a 204 No Content response.

func (*Server) APIKeyDetail

func (s *Server) APIKeyDetail(c *gin.Context)

Retrieve an APIKey by its ID. Most fields of the APIKey object are read-only, though some components, such as the APIKey secret, are not returned at all even on detail. An APIKey is returned if the ID can be parsed, it is found in the database, and the user OrgID claims match the organization the APIKey is assigned to. Otherwise this endpoint will return a 404 Not Found error if it cannot correctly retrieve the key.

NOTE: the APIKey Secret should never be returned from this endpoint!

func (*Server) APIKeyList

func (s *Server) APIKeyList(c *gin.Context)

List the API Keys for organization of the authenticated user, optionally filtered by project ID. The list response returns a subset of the fields in the APIKey object, to get more information about the API Key use the Detail endpoint. This endpoint returns a paginated response, limited by a default page size of 100 if one is not specified by the user (and a maximum page size of 5000). If there is another page of APIKeys the NextPageToken field will be populated, which can be used to make a subsequent request for the next page. Note that the page size or the projectID filter should not be changed between requests and that the NextPageToken will expire after 24 hours and can no longer be used.

NOTE: the APIKey Secret should never be returned from this endpoint!

func (*Server) APIKeyPermissions added in v0.5.0

func (s *Server) APIKeyPermissions(c *gin.Context)

APIKeyPermissions returns the API key permissions available to the user.

func (*Server) APIKeyUpdate

func (s *Server) APIKeyUpdate(c *gin.Context)

Update an APIKey to change it's description. Most fields on the APIKey object are read-only; in order to "change" fields such as permissions it is necessary to delete the key and create a new one. The APIKey is updated if the ID can be parsed, it is found in the database, and the user OrgID claims match the organization the APIKey is assigned to. Otherwise this endpoint will return a 404 Not Found error.

NOTE: the APIKey Secret should never be returned from this endpoint!

func (*Server) AccessToken added in v0.2.0

func (s *Server) AccessToken(claims *tokens.Claims) string

AccessToken returns a token that can be used in tests and is only available if the server is in testing mode, otherwise an empty string is returned.

func (*Server) AccountUpdate added in v0.5.0

func (s *Server) AccountUpdate(c *gin.Context)

func (*Server) Authenticate

func (s *Server) Authenticate(c *gin.Context)

Authenticate is oriented to machine users that have an API key with a client ID and secret for authentication (whereas login is used for human access using an email and password). Authenticate verifies the client secret submitted is correct by looking up the api key by the key ID and using the argon2 derived key verification process to confirm the secret matches. Upon authentication, an access and refresh token with the authorized claims of the keys are returned. These tokens can be used to authenticate with ensign systems and the claims used for authorization. The access and refresh tokens work the same way the user tokens work and the refresh token can be used to fetch a new key pair without having to transmit a secret again.

This method primarily uses read queries so should be highly available. The only write is the update of the last time the key was used, but it does this in a go routine to ensure that this endpoint is not blocked by Quarterdeck Raft replication. TODO: add rate limiting on a per-ip basis to prevent Quarterdeck DOS.

func (*Server) Available

func (s *Server) Available() gin.HandlerFunc

Available is middleware that uses healthy boolean to return a service unavailable http status code if the server is shutting down or in maintenance mode. This middleware must be fairly early on in the chain to ensure that complex handling does not slow the shutdown of the server.

func (*Server) CreateTokenPair added in v0.3.0

func (s *Server) CreateTokenPair(claims *tokens.Claims) (string, string)

Return an access and refresh token that can be used in tests and is only available if the server is in testing mode, otherwise empty strings are returned. It is preferred to use the AccessToken() function for most tests, use this function if a refresh token is required for testing.

func (*Server) ForgotPassword added in v0.11.0

func (s *Server) ForgotPassword(c *gin.Context)

ForgotPassword is a service for users to request a password reset email. The email address must be provided in the POST request and the user must exist in the database. This endpoint always returns 204 regardless of whether the user exists or not to avoid leaking information about users in the database.

func (*Server) GetTaskManager added in v0.5.0

func (s *Server) GetTaskManager() *radish.TaskManager

Expose the task manager to the tests (only allowed in testing mode).

func (*Server) InviteAccept added in v0.10.0

func (s *Server) InviteAccept(c *gin.Context)

InviteAccept accepts a user invitation. This is an authenticated endpoint, so in order to accept the invite the email address of the requesting user must match the email in the invitation. The user must also already exist in the database. Unauthenticated users can call the Login endpoint to accept an invitation if they do not have credentials.

func (*Server) InviteCreate added in v0.5.2

func (s *Server) InviteCreate(c *gin.Context)

Invite a user to the organization. This is an authenticated endpoint that sends an invitation email to an email address. The link in the email contains a token that can only be verified by Quarterdeck. New users are not created in the database until they accept the email invitation.

func (*Server) InvitePreview added in v0.5.2

func (s *Server) InvitePreview(c *gin.Context)

InvitePreview returns details for a user invitation. This is a publicly accessible endpoint because it has to be accessed by unauthenticated users without any claims. Although the endpoint is read-only, it could return sensitive information about an organization so this endpoint relies on the token being difficult to guess.

func (*Server) JWKS added in v0.1.1

func (s *Server) JWKS(c *gin.Context)

JWKS returns the JSON web key set for the public RSA keys that are currently being used by Quarterdeck to sign JWT acccess and refresh tokens. External callers can use these keys to verify that a JWT token was in fact issued by the Quarterdeck API. TODO: add Cache-Control or Expires header to the response TODO: move the jwks construction to the token manager for easier key management.

func (*Server) Login

func (s *Server) Login(c *gin.Context)

Login is oriented towards human users who use their email and password for authentication (whereas authenticate is used for machine access using API keys). Login verifies the password submitted for the user is correct by looking up the user by email and using the argon2 derived key verification process to confirm the password matches. Upon authentication an access token and a refresh token with the authorized claims of the user (based on role) are returned. The user can use the access token to authenticate to Ensign systems and the claims within for authorization. The access token has an expiration and the refresh token can be used with the refresh endpoint to get a new access token without the user having to log in again. The refresh token overlaps with the access token to provide a seamless authentication experience and the user can refresh their access token so long as the refresh token is valid.

This method primarily uses read queries (fetching the user from the database and fetching the user permissions from the database). It does update the user's last logged in timestamp in the database but should be highly available without Quarterdeck Raft replication in most cases. TODO: add rate limiting on a per-user basis to prevent Quarterdeck DOS.

func (*Server) OpenIDConfiguration added in v0.1.1

func (s *Server) OpenIDConfiguration(c *gin.Context)

Returns a JSON document with the OpenID configuration as defined by the OpenID Connect standard: https://connect2id.com/learn/openid-connect. This document helps clients understand how to authenticate with Quarterdeck. TODO: once OpenID endpoints have been configured add them to this JSON response

func (*Server) OrganizationDetail added in v0.4.0

func (s *Server) OrganizationDetail(c *gin.Context)

Retrieve an organization by ID. Users are only allowed to retrieve their own organization. TODO: Eventually allow users to retrieve other organizations they are a part of.

func (*Server) OrganizationList added in v0.5.2

func (s *Server) OrganizationList(c *gin.Context)

func (*Server) OrganizationUpdate added in v0.10.0

func (s *Server) OrganizationUpdate(c *gin.Context)

Update an organization by ID. Users are only allowed to update their own organization.

func (*Server) ProjectAccess added in v0.5.0

func (s *Server) ProjectAccess(c *gin.Context)

func (*Server) ProjectCreate added in v0.3.0

func (s *Server) ProjectCreate(c *gin.Context)

func (*Server) ProjectDetail added in v0.7.0

func (s *Server) ProjectDetail(c *gin.Context)

func (*Server) ProjectList added in v0.7.0

func (s *Server) ProjectList(c *gin.Context)

func (*Server) Refresh

func (s *Server) Refresh(c *gin.Context)

Refresh re-authenticates users and api keys using a refresh token rather than requiring a username and password or API key credentials a second time and returns a new access and refresh token pair with the current credentials of the user. This endpoint is intended to facilitate long-running connections to ensign systems that last longer than the duration of an access token; e.g. long sessions on the Beacon UI or (especially) long running publishers and subscribers (machine users) that need to stay authenticated semi-permanently.

func (*Server) Register

func (s *Server) Register(c *gin.Context)

Register creates a new user in the database with the specified password, allowing the user to login to Quarterdeck. This endpoint requires a "strong" password and a valid register request, otherwise a 400 reply is returned. The password is stored in the database as an argon2 derived key so it is impossible for a hacker to get access to raw passwords.

An organization is created for the user registering based on the organization data in the register request and the user is assigned the Owner role. A project ID can be provided in the request to allow the client to safely create a default project for the user, although the field is optional. This endpoint does not handle adding users to existing organizations through collaborator invites. TODO: add rate limiting to ensure that we don't get spammed with registrations

func (*Server) ResendEmail added in v0.10.0

func (s *Server) ResendEmail(c *gin.Context)

ResendEmail accepts an email address via a POST request and always returns a 204 response, no matter the input or result of the processing. This is to ensure that no secure information is leaked from this unauthenticated endpoint. If the email address belongs to a user who has not been verified, another verification email is sent. If the post request contains an orgID and the user is invited to that organization but hasn't accepted the invite, then the invite is resent.

func (*Server) ResetPassword added in v0.11.0

func (s *Server) ResetPassword(c *gin.Context)

ResetPassword allows users to set a new password after requesting a password reset. A token must be provided in the request and must not be expired. On success this endpoint sends a confirmation email to the user and returns a 204 No Content.

func (*Server) ResetTaskManager added in v0.5.0

func (s *Server) ResetTaskManager()

Reset the task manager from the tests (only allowed in testing mode)

func (*Server) Routes added in v0.4.0

func (s *Server) Routes(router *gin.Engine) (err error)

Setup the server's middleware and routes.

func (*Server) SecurityTxt added in v0.1.1

func (s *Server) SecurityTxt(c *gin.Context)

Writes the security.txt file generated from https://securitytxt.org/ and digitally signed with the [email protected] PGP keys to alert security researchers to our security policies and allow them to contact us with any security flaws.

func (*Server) SendDailyUsers added in v0.5.2

func (s *Server) SendDailyUsers(data *emails.DailyUsersData) (err error)

Send the daily users report to the Rotational admins. This method overwrites the email data on the report with the configured sender and recipient of the server so it should not be specified by the user (e.g. the user should only supply the report data for the email template).

func (*Server) SendInviteEmail added in v0.5.2

func (s *Server) SendInviteEmail(inviter *models.User, org *models.Organization, invite *models.UserInvitation) (err error)

Send an email to a user to invite them to join an organization.

func (*Server) SendPasswordResetRequestEmail added in v0.11.0

func (s *Server) SendPasswordResetRequestEmail(user *models.User) (err error)

Send an email to a user to request them to reset their password.

func (*Server) SendPasswordResetSuccessEmail added in v0.11.0

func (s *Server) SendPasswordResetSuccessEmail(user *models.User) (err error)

Send an email to a user to inform them that their password has been reset.

func (*Server) SendVerificationEmail added in v0.5.0

func (s *Server) SendVerificationEmail(user *models.User) (err error)

Send an email to a user to verify their email address. This method requires the user object to have an existing verification token.

func (*Server) Setup added in v0.4.0

func (s *Server) Setup() (err error)

Setup the server before the routes are configured.

func (*Server) Started added in v0.4.0

func (s *Server) Started() (err error)

Called when the server has been started and is ready.

func (*Server) Status

func (s *Server) Status(c *gin.Context)

Status handler returns the current healthy status of the server (can't be unhealthy otherwise the Available middleware would have intercepted the request)

func (*Server) Stop added in v0.4.0

func (s *Server) Stop(ctx context.Context) (err error)

Cleanup when the server is being shutdown. Note that in tests you should call Shutdown() to ensure the server is gracefully closed and not this method.

func (*Server) Switch added in v0.5.2

func (s *Server) Switch(c *gin.Context)

Switch re-authenticates users (human users only) using the access token the user posts in the headers in order to give the user new claims with a new organization ID. E.g. the user switches from being logged into one organization to being logged into another organization. The user must submit the orgID of the organization they wish to switch to and the user must belong to that organization otherwise an error is returned.

NOTE: this endpoint cannot be used with api keys because api keys are only ever issued to one organization (and in fact, one project inside of one organization). Only human users can belong to multiple organizations.

func (*Server) UserDetail added in v0.4.0

func (s *Server) UserDetail(c *gin.Context)

func (*Server) UserList added in v0.4.0

func (s *Server) UserList(c *gin.Context)

func (*Server) UserRemove added in v0.5.2

func (s *Server) UserRemove(c *gin.Context)

Remove a user from the requesting user's organization by their ID. If the user owns resources in the organization, then this endpoint sends a 200 response with the list of resources that would be deleted and a confirmation token with an expiration. The token must be provided to the UserRemoveConfirm endpoint in order to remove the user and their associated resources. Users that do not own any resources in the organization are removed without confirmation and a 200 response is returned. If a user is left with no organizations then the user is also deleted from the database. TODO: determine all the components of this process (billing, removal of organization, etc)

func (*Server) UserRemoveConfirm added in v0.7.0

func (s *Server) UserRemoveConfirm(c *gin.Context)

Remove a user from the requesting user's organization by providing a confirmation token. Confirmation tokens are created by the UserRemove endpoint when additional resources would be deleted by removing the user from the organization. If the confirmation token does not exist in the database, is expired, or is for the wrong organization user then a 404 response is returned.

func (*Server) UserRoleUpdate added in v0.5.2

func (s *Server) UserRoleUpdate(c *gin.Context)

The UserRoleUpdate endpoint updates the role of a user in the organization. If the role is not valid or user already has the role, a 400 error is returned.

func (*Server) UserUpdate added in v0.3.0

func (s *Server) UserUpdate(c *gin.Context)

func (*Server) VerifyEmail added in v0.5.0

func (s *Server) VerifyEmail(c *gin.Context)

VerifyEmail verifies a user's email address by validating the token in the request. This endpoint is intended to be called by frontend applications after the user has followed the link in the verification email. If the user is not verified and the token is valid then the user is logged in. If the user is already verified then a 204 response is returned.

func (*Server) VerifyToken added in v0.3.0

func (s *Server) VerifyToken(tks string) (*tokens.Claims, error)

VerifyToken extracts the claims from an access or refresh token returned by the server. This is only available if the server is in testing mode.

func (*Server) WorkspaceLookup added in v0.10.0

func (s *Server) WorkspaceLookup(c *gin.Context)

Lookup an organization's workspace by domain slug. This authenticated GET request expects the read:organizations permission from the user. It also expects a query parameter domain, otherwise a 400 bad request is returned. If the domain exists and the user belongs to the organization, then a full workspace record is returned; otherwise just the domain and is_available=false is returned. If the domain does not exist and there is no check_availability query param a 404 is returned; otherwise a 200 response is returned with is_available=true.

Directories

Path Synopsis
api
v1
Package authtest provides helper functionality for testing authentication with Quarterdeck as simply as possible.
Package authtest provides helper functionality for testing authentication with Quarterdeck as simply as possible.
db
Package db establishes a connection with a Raft replicated sqlite3 database.
Package db establishes a connection with a Raft replicated sqlite3 database.
Package keygen provides functionality for generating API client IDs and secrets.
Package keygen provides functionality for generating API client IDs and secrets.
replica

Jump to

Keyboard shortcuts

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