diff --git a/GNUmakefile b/GNUmakefile index 469a52058..f3ac67abd 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -424,18 +424,20 @@ psql: ## Open a psql shell to the postgres container $(DOCKER_COMPOSE) exec postgres psql -U probod -d probod compose/step-ca/certs/root_ca.crt: - # step-ca runs as UID 1000 and creates 0700 dirs; open them for the - # host user so later `go list ./...` can walk the bind mount on Linux. + # step-ca runs as UID 1000 and creates 0700 dirs. On Linux CI the host + # user cannot traverse them, so `-f` never sees root_ca.crt and a host + # chmod cannot fix ownership. Open perms from inside the container. @$(MKDIR) compose/step-ca @chmod a+rwx compose/step-ca $(DOCKER_COMPOSE) up -d acme-http-01-proxy step-ca @i=0; \ while [ ! -f $@ ] && [ $$i -lt 60 ]; do \ + $(DOCKER_COMPOSE) exec -T -u 0 step-ca chmod -R a+rX /home/step 2>/dev/null || true; \ sleep 1; \ i=$$((i + 1)); \ done @test -f $@ || ($(DOCKER_COMPOSE) logs step-ca >&2; echo "step-ca root CA not ready" >&2; exit 1) - @chmod -R a+rX compose/step-ca + @$(DOCKER_COMPOSE) exec -T -u 0 step-ca chmod -R a+rX /home/step compose/keycloak/certs/cert.pem: $(MKDIR) ./compose/keycloak/certs diff --git a/pkg/certmanager/provision_worker.go b/pkg/certmanager/provision_worker.go index 6da73b30c..2c298a465 100644 --- a/pkg/certmanager/provision_worker.go +++ b/pkg/certmanager/provision_worker.go @@ -296,6 +296,7 @@ func (h *provisionHandler) skipsDNSChecks( } domain := &coredata.CustomDomain{} + err := domain.LoadByDomain(ctx, conn, coredata.NewNoScope(), hostname) if errors.Is(err, coredata.ErrResourceNotFound) { return true, nil diff --git a/pkg/complianceportal/management/domain.go b/pkg/complianceportal/management/domain.go index 692d065ed..40d7180a0 100644 --- a/pkg/complianceportal/management/domain.go +++ b/pkg/complianceportal/management/domain.go @@ -104,6 +104,7 @@ func loadDomains( } var certificateIDs []gid.GID + domainByCertificate := make(map[gid.GID]gid.GID) for _, d := range domains { diff --git a/pkg/complianceportal/management/domain_service.go b/pkg/complianceportal/management/domain_service.go index d2fbb6726..c68b70755 100644 --- a/pkg/complianceportal/management/domain_service.go +++ b/pkg/complianceportal/management/domain_service.go @@ -37,6 +37,7 @@ func (s *Service) AddCustomDomain( v := validator.New() v.Check(compliancePageID, "compliance_page_id", validator.Required(), validator.GID(coredata.TrustCenterEntityType)) v.Check(domain, "domain", validator.Required(), validator.NotEmpty(), validator.Domain()) + if err := v.Error(); err != nil { return nil, fmt.Errorf("invalid request: %w", err) } @@ -107,6 +108,7 @@ func (s *Service) RemoveCustomDomain( } compliancePage := &coredata.TrustCenter{} + err := compliancePage.LoadByDomainID(ctx, tx, customDomainID) switch { case err == nil: @@ -181,6 +183,7 @@ func (s *Service) PublicURL( } var err error + publicURL, err = s.PublicURLForCompliancePage(ctx, conn, scope, compliancePage) if err != nil { return fmt.Errorf("cannot resolve public url: %w", err) diff --git a/pkg/complianceportal/management/file_service.go b/pkg/complianceportal/management/file_service.go index 0679df7d6..47f7c087c 100644 --- a/pkg/complianceportal/management/file_service.go +++ b/pkg/complianceportal/management/file_service.go @@ -97,7 +97,6 @@ func (s *Service) ListFilesForOrganizationID( return nil }) - if err != nil { return nil, err } @@ -124,7 +123,6 @@ func (s *Service) CountFilesForOrganizationID( return nil }) - if err != nil { return 0, err } diff --git a/pkg/complianceportal/visitor/document_service.go b/pkg/complianceportal/visitor/document_service.go index b728f80ca..d5b226171 100644 --- a/pkg/complianceportal/visitor/document_service.go +++ b/pkg/complianceportal/visitor/document_service.go @@ -290,13 +290,10 @@ func (s *Service) generateDocumentPDFOnTheFly( fileRecord := &coredata.File{} fileErr := s.pg.WithConn( - ctx, - func(ctx context.Context, conn pg.Querier) error { return fileRecord.LoadByID(ctx, conn, scope, *organization.HorizontalLogoFileID) }) - if fileErr == nil { base64Data, mimeType, logoErr := s.fileManager.GetFileBase64(ctx, fileRecord) if logoErr == nil { diff --git a/pkg/coredata/oauth2_client.go b/pkg/coredata/oauth2_client.go index b33bab3e4..d443de1be 100644 --- a/pkg/coredata/oauth2_client.go +++ b/pkg/coredata/oauth2_client.go @@ -651,6 +651,7 @@ func NewCIMDClient( if err != nil { return nil, fmt.Errorf("cannot parse logo_uri: %w", err) } + if !u.IsHTTP() { return nil, fmt.Errorf("logo_uri must be an absolute http or https URL") } @@ -663,6 +664,7 @@ func NewCIMDClient( if err != nil { return nil, fmt.Errorf("cannot parse client_uri: %w", err) } + if !u.IsHTTP() { return nil, fmt.Errorf("client_uri must be an absolute http or https URL") } diff --git a/pkg/iam/oauth2/discovery.go b/pkg/iam/oauth2/discovery.go index a71e2a1bd..4aa3d3fe1 100644 --- a/pkg/iam/oauth2/discovery.go +++ b/pkg/iam/oauth2/discovery.go @@ -84,6 +84,7 @@ func AuthorizationURLWithQuery( } merged := u.Query() + for key, values := range query { for _, value := range values { merged.Add(key, value) diff --git a/pkg/iam/oauth2/service.go b/pkg/iam/oauth2/service.go index ca12d7a6d..1ff824590 100644 --- a/pkg/iam/oauth2/service.go +++ b/pkg/iam/oauth2/service.go @@ -1547,6 +1547,7 @@ func (s *Service) Authorize( } } else { var existingConsent coredata.OAuth2Consent + skipConsent = existingConsent.LoadMatchingConsent( ctx, tx, diff --git a/pkg/probod/probod.go b/pkg/probod/probod.go index 53769fdd3..7fa7482f6 100644 --- a/pkg/probod/probod.go +++ b/pkg/probod/probod.go @@ -686,6 +686,7 @@ func (impl *Implm) Run( ) staticCIMDAllow := oauth2.CIMDAllowFromClientIDs(impl.cfg.Auth.OAuth2Server.CIMDAllowedClientIDs) + iamService.OAuth2ServerService.SetCIMDAllow( func(ctx context.Context, clientIDURL string) (oauth2.CIMDAllowance, error) { host, ok := oauth2.CIMDClientIDHost(clientIDURL) @@ -1322,6 +1323,7 @@ func newTrustCenterHTTPRedirectHandler(trustService *visitor.Service, l *log.Log } httpserver.RenderError(w, http.StatusInternalServerError, errors.New("internal server error")) + return } diff --git a/pkg/server/api/complianceportal/session.go b/pkg/server/api/complianceportal/session.go index ca044a01f..08021f61d 100644 --- a/pkg/server/api/complianceportal/session.go +++ b/pkg/server/api/complianceportal/session.go @@ -39,6 +39,7 @@ func NewSessionHostMiddleware(cookieConfig securecookie.Config) func(next http.H return http.HandlerFunc( func(w http.ResponseWriter, r *http.Request) { ctx := r.Context() + session := authn.SessionFromContext(ctx) if session == nil { next.ServeHTTP(w, r) @@ -52,6 +53,7 @@ func NewSessionHostMiddleware(cookieConfig securecookie.Config) func(next http.H } securecookie.Clear(w, cookieConfig) + ctx = authn.ContextWithSession(ctx, nil) ctx = authn.ContextWithIdentity(ctx, nil) next.ServeHTTP(w, r.WithContext(ctx)) diff --git a/pkg/server/api/complianceportal/session_test.go b/pkg/server/api/complianceportal/session_test.go index 57569f3c0..34d032edc 100644 --- a/pkg/server/api/complianceportal/session_test.go +++ b/pkg/server/api/complianceportal/session_test.go @@ -49,6 +49,7 @@ func TestSessionHostMiddleware_RejectsMismatchedHost(t *testing.T) { handler := NewSessionHostMiddleware(securecookie.Config{Name: "ssid"})( http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { authenticated = authn.IdentityFromContext(r.Context()) != nil + w.WriteHeader(http.StatusOK) }), ) @@ -80,6 +81,7 @@ func TestSessionHostMiddleware_AllowsMatchingTLSHost(t *testing.T) { handler := NewSessionHostMiddleware(securecookie.Config{Name: "ssid"})( http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { authenticated = authn.IdentityFromContext(r.Context()) != nil + w.WriteHeader(http.StatusOK) }), ) @@ -111,6 +113,7 @@ func TestSessionHostMiddleware_RejectsSpoofedHostHeader(t *testing.T) { handler := NewSessionHostMiddleware(securecookie.Config{Name: "ssid"})( http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { authenticated = authn.IdentityFromContext(r.Context()) != nil + w.WriteHeader(http.StatusOK) }), ) diff --git a/pkg/server/api/complianceportal/v1/brand_logo_handler.go b/pkg/server/api/complianceportal/v1/brand_logo_handler.go index a9b876249..4e773ca72 100644 --- a/pkg/server/api/complianceportal/v1/brand_logo_handler.go +++ b/pkg/server/api/complianceportal/v1/brand_logo_handler.go @@ -63,6 +63,7 @@ func (h *brandLogoHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { } var fileID *gid.GID + switch h.variant { case brandLogoVariantLogo: fileID = compliancePage.LogoFileID diff --git a/pkg/server/api/complianceportal/v1/oauth_callback_handler.go b/pkg/server/api/complianceportal/v1/oauth_callback_handler.go index 63439edc9..fa6ab1ce3 100644 --- a/pkg/server/api/complianceportal/v1/oauth_callback_handler.go +++ b/pkg/server/api/complianceportal/v1/oauth_callback_handler.go @@ -77,6 +77,7 @@ func (h *OAuthCallbackHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) } code := r.URL.Query().Get("code") + stateToken := r.URL.Query().Get("state") if code == "" || stateToken == "" { httpserver.RenderError(w, http.StatusBadRequest, errInvalidOAuthRequest) @@ -92,6 +93,7 @@ func (h *OAuthCallbackHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) } portal := complianceportal.CompliancePageFromContext(ctx) + portalBaseURL := complianceportal.CompliancePageBaseURLFromContext(ctx) if portal == nil || portalBaseURL == nil { httpserver.RenderError(w, http.StatusNotFound, errNotFound) diff --git a/pkg/server/api/connect/v1/magic_link_handler_test.go b/pkg/server/api/connect/v1/magic_link_handler_test.go index 2e697f3ec..a5162f62f 100644 --- a/pkg/server/api/connect/v1/magic_link_handler_test.go +++ b/pkg/server/api/connect/v1/magic_link_handler_test.go @@ -105,5 +105,4 @@ func TestMagicLinkHandler_SendHandler_Validation(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) }) - } diff --git a/pkg/server/api/console/v1/trust_center_resolvers.go b/pkg/server/api/console/v1/trust_center_resolvers.go index 54fb430bf..cceb1dcfe 100644 --- a/pkg/server/api/console/v1/trust_center_resolvers.go +++ b/pkg/server/api/console/v1/trust_center_resolvers.go @@ -142,6 +142,7 @@ func (r *customDomainResolver) Certificate(ctx context.Context, obj *types.Custo } r.logger.ErrorCtx(ctx, "cannot load certificate", log.Error(err)) + return nil, gqlutils.Internal(ctx) } @@ -1204,6 +1205,7 @@ func (r *trustCenterResolver) DefaultDomain(ctx context.Context, obj *types.Trus } r.logger.ErrorCtx(ctx, "cannot load default domain", log.Error(err)) + return nil, gqlutils.Internal(ctx) } @@ -1228,6 +1230,7 @@ func (r *trustCenterResolver) CustomDomain(ctx context.Context, obj *types.Trust } r.logger.ErrorCtx(ctx, "cannot load custom domain", log.Error(err)) + return nil, gqlutils.Internal(ctx) } diff --git a/pkg/server/api/mcp/v1/schema.resolvers.go b/pkg/server/api/mcp/v1/schema.resolvers.go index d316a15ac..94b95c63b 100644 --- a/pkg/server/api/mcp/v1/schema.resolvers.go +++ b/pkg/server/api/mcp/v1/schema.resolvers.go @@ -4953,6 +4953,7 @@ func (r *Resolver) UpdateTrustCenterTool(ctx context.Context, req *mcp.CallToolR updateReq.WebsiteURL = UnwrapOmittable(input.WebsiteURL) updateReq.Email = UnwrapOmittable(input.Email) updateReq.HeadquarterAddress = UnwrapOmittable(input.HeadquarterAddress) + if title := UnwrapOmittable(input.Title); title != nil { updateReq.Title = *title }