Commit Graph

89 Commits

Author SHA1 Message Date
Sacha Al Himdani
f7070c43a4 Serialize gqlgen codegen to fix build cache race
Parallel gqlgen instances race on the Go build cache, causing
Rewriter.getSource() to panic with "slice bounds out of range"
when go/packages returns empty source. Chain gqlgen targets with
order-only prerequisites in the Makefile and switch the CI build
job to sequential generation.

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-04-20 16:33:58 +02:00
Émile Ré
1ec8e475de Add UX for cookie banner management
Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-20 17:47:04 +04:00
Bryan Frimin
11770b4058 Add OAuth2/OpenID Connect authorization server
Implement a full OAuth2 2.0 and OpenID Connect 1.0 authorization
server with support for authorization code flow (with PKCE),
refresh token rotation, device authorization grant, dynamic
client registration, token introspection, and token revocation.

Includes database schema, coredata layer, service logic, HTTP
handlers, OIDC discovery endpoint, and JWKS publishing.

Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2026-04-19 12:00:53 +02:00
Aurélien Sibiril
3d36d93e32 Replace panic with error handling in connector handlers
The connector initiate and complete HTTP handlers used panic for
operational errors (network, DB, provider failures). No recovery
middleware exists on the console chi router, so these panics
produced incomplete responses instead of proper HTTP 500 errors.

Use the same log-and-render pattern already established in
loadExistingConnector error handling.

Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
2026-04-13 19:24:46 +02:00
Aurélien Sibiril
08f163f02f refactor(console): rewrite /connectors/initiate to union scopes
The initiate handler now looks up the existing connector for the
target (organization, provider) pair, reads its stored scope set
through Connection.Scopes, and unions it with the scopes the caller
passed in the query string. The union is what gets requested on the
OAuth authorization URL, so reconnects never drop a previously
granted scope.

When an existing connector is found the handler also flags the
flow as a reconnect via InitiateOptions.ConnectorID, so the
OAuth2 state carries the id and the callback updates the row in
place. When the provider supports it (Google Workspace), the auth
URL also carries include_granted_scopes=true and the user sees
only the delta on the consent screen.

There is no short-circuit: every initiate click runs the full
OAuth flow even if stored scopes already cover the request, because
scope coverage is an unsafe proxy for token liveness. Revoked
tokens or leftover connectors from deleted access sources would
otherwise be silently reused.

The handler body is extracted to its own file to keep NewMux
readable.

Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
2026-04-13 19:24:46 +02:00
Aurélien Sibiril
5340953966 feat(probo): validate reconnects and preserve dropped token fields
Reconnect now takes a ReconnectConnectorRequest carrying the expected
OrganizationID and Provider. It validates inside the same transaction
that the loaded connector belongs to the requested org, provider and
OAUTH2 protocol before mutating the row. This blocks cross-org and
cross-provider corruption via a crafted connector_id reaching the
OAuth callback through the HMAC-signed state token.

preserveConnectionFields copies fields from the existing connection
onto the new one when the new one omits them:

- OAuth2 refresh_token: Google drops it on incremental-auth reuse
  when prompt=consent is skipped.
- Slack webhook URL, channel and channel ID: access review Slack
  reconnects without the incoming-webhook scope return a token
  response with no incoming_webhook field.

GetByOrganizationIDAndProvider now routes through the widest-scope
coredata loader, and GetWithConnection exposes a by-ID load that
returns the fully decrypted connector so the initiate handler can
read the stored scope set.

Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
2026-04-13 19:24:46 +02:00
Aurélien Sibiril
53d6ab09cb Fully expand r.Get call for connectors/complete handler
Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
2026-04-08 11:05:12 +02:00
Aurélien Sibiril
e006f335b2 Pass OAuth2 scopes to connector at initiate time
Add an InitiateOptions struct to the Connector interface so each
caller can declare the scopes it needs instead of having them baked
into the connector at registration. The HTTP handler reads repeated
?scope= query parameters from /connectors/initiate and forwards them.

Also restore GOOGLE_WORKSPACE and LINEAR provider definitions which
were silently dropped from the bootstrap config refactor.

Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
2026-04-08 11:05:12 +02:00
Aurélien Sibiril
4cc0e31214 Preserve continuation URL on OAuth2 error redirect
Use the ContinueURL from the state token so the user is redirected
back to where they initiated the flow instead of the root URL.
The redirect is safe because safeRedirect validates the host.

Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
2026-04-08 11:05:12 +02:00
Aurélien Sibiril
47fc9df716 Handle OAuth2 error responses in connector callback
When a provider returns an error (e.g. user denies consent), the
callback now logs the error with provider name and redirects to
the base URL with error and error_description query parameters
instead of falling through to the code exchange.

Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
2026-04-08 11:05:12 +02:00
Aurélien Sibiril
b2d5f49bef Extract connector complete handler from NewMux
Reduce closure size in NewMux by extracting the /connectors/complete
handler into a dedicated handleConnectorComplete function. Cache
r.URL.Query() into a local variable to avoid repeated parsing.

Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
2026-04-08 11:05:12 +02:00
Émile Ré
11a96633ec No need for saferedirect on known connectors
Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-03 18:53:02 +04:00
Aurélien Sibiril
ebfc0b7e31 Add access review console GraphQL API
Add queries, mutations, and types for access review
campaigns, access sources, access entries with decisions
and flags, connector provider info, and provider org
listing. Wire accessreview.Service into the Resolver.

Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
2026-04-02 14:37:29 +02:00
Bryan Frimin
419c93fc7d Fix compliance page login redirect to custom domains
SafeRedirect previously matched against a single static host string,
so OIDC callbacks always fell back to the console instead of
redirecting back to compliance pages on custom domains. Refactor
AllowedHost into a dynamic AllowedHostFunc and wire a trust-service
lookup into the connect handler so custom domain hosts are accepted.

Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2026-03-31 10:51:34 +02:00
Sacha Al Himdani
8c02c53315 Update copyright headers across all Go files
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-03-25 17:38:32 +01:00
Bryan Frimin
d24712344e Add GraphQL dataloaders for batched record lookups
Introduce dataloadgen-based dataloaders to batch individual
record-by-ID fetches in GraphQL resolvers into single SQL
queries. Each entity type (organization, framework, control,
vendor, document, risk, measure, task, file, report, profile)
gets a LoadByIDs method in coredata and a GetByIDs service
method with variadic arguments and dedicated collection return
types. Resolvers now use dataloader.FromContext instead of
direct service calls for single-record lookups.

Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2026-03-25 15:19:46 +01:00
Bryan Frimin
7b320916af Add audit log feature for recording all actions
Adds audit logging that records all authorized actions performed by
users and API keys. The audit log is automatically populated whenever
the authorizer approves an action, and is queryable via GraphQL, MCP,
and CLI interfaces. Permission checks are excluded via a dry-run flag
to avoid phantom entries on page loads.

Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2026-03-21 19:16:19 +01:00
Sacha Al Himdani
d5c62a9383 Run go fmt/fix
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-03-13 14:48:13 +01:00
Sacha Al Himdani
aa01c40184 Remove with tenant from mailman
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-03-11 15:34:36 +01:00
Sacha Al Himdani
4d2cb793b6 Add compliance page mailing list base
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-03-11 15:34:36 +01:00
Émile Ré
0a532f17c5 Remove legacy document signing endpoints
Signed-off-by: Émile Ré <emile@getprobo.com>
2026-03-11 17:08:42 +04:00
Bryan Frimin
c191d25e9a Add electronic signature
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2026-02-23 09:38:27 +01:00
Émile Ré
5fb389e8bc Remove people service and coredata
Signed-off-by: Émile Ré <emile@getprobo.com>
2026-02-12 16:21:12 +04:00
Bryan Frimin
bc5bbdae81 Add scim bridge with connector
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2026-02-02 09:14:38 +01:00
Émile Ré
ff65303a1a Fix documents signing authentication
Signed-off-by: Émile Ré <emile@getprobo.com>
2026-01-21 12:24:34 +04:00
Bryan Frimin
2b11ff90af Revert back to graphql endpoint
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2026-01-20 07:47:48 -08:00
Émile Ré
4881901a73 Revert console graphql endpoint pathname for tmp n8n app fix
Signed-off-by: Émile Ré <emile@getprobo.com>
2026-01-20 14:56:42 +04:00
Émile Ré
7322201dab Plug trust center part 1
Signed-off-by: Émile Ré <emile@getprobo.com>
2026-01-17 12:34:23 -08:00
Émile Ré
1257347df9 Extract authn & authz utils
Signed-off-by: Émile Ré <emile@getprobo.com>
2026-01-17 12:34:03 -08:00
Émile Ré
c6094ff572 Implement organization assumption check in authorization layer
Signed-off-by: Émile Ré <emile@getprobo.com>
2026-01-17 12:34:01 -08:00
Émile Ré
e46a11001a Fix iam pages permissions handling
Signed-off-by: Émile Ré <nemile.re@gmail.com>
2026-01-17 11:08:16 -08:00
Émile Ré
ca533ce7a7 Expose permission field on each core schema node implementation
Signed-off-by: Émile Ré <nemile.re@gmail.com>
2026-01-17 11:05:33 -08:00
Bryan Frimin
63abfe3698 Fix not token secret
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2026-01-17 10:35:52 -08:00
Bryan Frimin
799bf6a0ec Fix slack connector permission
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2026-01-17 10:25:16 -08:00
Bryan Frimin
09c456b8ac WIP
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2026-01-17 10:25:16 -08:00
Bryan Frimin
e9ac50d91c Update RBAC on console
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2026-01-17 10:23:45 -08:00
Bryan Frimin
dccac5c088 Move UnwrapOmittable in a dedicated helper
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2026-01-17 10:14:56 -08:00
Bryan Frimin
0f7c755d53 Rename user into identity
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2026-01-17 10:10:27 -08:00
Bryan Frimin
e61d72f15d Rewrite permission system
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2026-01-17 10:07:41 -08:00
Bryan Frimin
74fc3b8cd1 Rewrite identity and access management
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2026-01-17 10:07:34 -08:00
Émile Ré
d702c4b7c6 Use gqlgen via tool and update generated code
Signed-off-by: Émile Ré <nemile.re@gmail.com>
2025-12-16 12:45:25 +01:00
Bryan Frimin
dfd924abeb Add tools and update authenticztion and RBAC
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2025-11-21 10:22:01 +01:00
Sacha Al Himdani
21c4b7cd9d Add role management
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2025-11-13 17:11:22 +01:00
Sacha Al Himdani
fee5a9232e Make secure cookie configurable
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2025-11-04 17:09:51 +01:00
Sacha Al Himdani
5212d0c18f Add api keys
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2025-11-04 13:37:31 +01:00
Bryan Frimin
59aa332ab5 Move to vanity import url
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2025-10-31 17:01:52 +01:00
Sacha Al Himdani
9a33f7b771 Manage errors
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2025-10-31 15:14:56 +01:00
Bryan Frimin
29917578fc Fix various bad tenant isolation
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2025-10-30 16:38:13 +01:00
Bryan Frimin
6f2bd9c92f Fix failed to to cannot
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2025-10-30 16:38:08 +01:00
Bryan Frimin
2766f8e423 Add SAML support
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2025-10-30 16:31:27 +01:00