Fix step-ca root CA access on Linux CI

Host chmod cannot open 0700 dirs owned by UID 1000, so
`-f` never sees root_ca.crt. Chmod from inside the
container as root while waiting for the cert.

Signed-off-by: Bryan Frimin <bryan@probo.com>
This commit is contained in:
Bryan Frimin
2026-07-19 16:43:44 +02:00
parent cb1d7c274b
commit b03acbd029
17 changed files with 28 additions and 9 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -104,6 +104,7 @@ func loadDomains(
}
var certificateIDs []gid.GID
domainByCertificate := make(map[gid.GID]gid.GID)
for _, d := range domains {

View File

@@ -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)

View File

@@ -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
}

View File

@@ -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 {

View File

@@ -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")
}

View File

@@ -84,6 +84,7 @@ func AuthorizationURLWithQuery(
}
merged := u.Query()
for key, values := range query {
for _, value := range values {
merged.Add(key, value)

View File

@@ -1547,6 +1547,7 @@ func (s *Service) Authorize(
}
} else {
var existingConsent coredata.OAuth2Consent
skipConsent = existingConsent.LoadMatchingConsent(
ctx,
tx,

View File

@@ -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
}

View File

@@ -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))

View File

@@ -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)
}),
)

View File

@@ -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

View File

@@ -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)

View File

@@ -105,5 +105,4 @@ func TestMagicLinkHandler_SendHandler_Validation(t *testing.T) {
assert.Equal(t, http.StatusBadRequest, rec.Code)
})
}

View File

@@ -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)
}

View File

@@ -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
}