Add device enrollment API and agent protocol

Expose ITAM REST endpoints for agents, console GraphQL for device
management, and wire probod bootstrap with enrollment e2e coverage.

Signed-off-by: Ludovic Vielle <ludovic@probo.com>
This commit is contained in:
Ludovic Vielle
2026-07-14 20:39:45 +02:00
parent 1f79453386
commit e767dd8377
30 changed files with 2129 additions and 6 deletions

View File

@@ -44,11 +44,13 @@ import (
"go.probo.inc/probo/pkg/filemanager"
"go.probo.inc/probo/pkg/geoloc"
"go.probo.inc/probo/pkg/iam"
"go.probo.inc/probo/pkg/itam"
"go.probo.inc/probo/pkg/mailman"
"go.probo.inc/probo/pkg/probo"
"go.probo.inc/probo/pkg/resourcealias"
"go.probo.inc/probo/pkg/riskmanagement"
"go.probo.inc/probo/pkg/securecookie"
agent_v1 "go.probo.inc/probo/pkg/server/api/agent/v1"
connect_v1 "go.probo.inc/probo/pkg/server/api/connect/v1"
console_v1 "go.probo.inc/probo/pkg/server/api/console/v1"
cookiebanner_v1 "go.probo.inc/probo/pkg/server/api/cookiebanner/v1"
@@ -80,6 +82,7 @@ type (
Geoloc *geoloc.Service
ThirdParty *thirdparty.Service
RiskManagement *riskmanagement.Service
ITAM *itam.Service
Cookie securecookie.Config
TokenSecret string
ConnectorRegistry *connector.ConnectorRegistry
@@ -104,6 +107,7 @@ type (
mcpHandler http.Handler
slackHandler http.Handler
connectHandler http.Handler
agentHandler http.Handler
}
)
@@ -111,6 +115,7 @@ var (
ErrMissingProboService = errors.New("server configuration requires a valid probo.Service instance")
ErrMissingIAMService = errors.New("server configuration requires a valid iam.Service instance")
ErrMissingSlackService = errors.New("server configuration requires a valid slack.Service instance")
ErrMissingITAMService = errors.New("server configuration requires a valid itam.Service instance")
)
func methodNotAllowed(w http.ResponseWriter, r *http.Request) {
@@ -150,6 +155,10 @@ func NewServer(cfg Config) (*Server, error) {
return nil, ErrMissingSlackService
}
if cfg.ITAM == nil {
return nil, ErrMissingITAMService
}
csrf := http.NewCrossOriginProtection()
for _, origin := range cfg.AllowedOrigins {
if err := csrf.AddTrustedOrigin(origin); err != nil {
@@ -209,6 +218,7 @@ func NewServer(cfg Config) (*Server, error) {
cfg.ThirdParty,
cfg.RiskManagement,
cfg.GraphQLLimits,
cfg.ITAM,
),
cookieBannerHandler: cookiebanner_v1.NewMux(
cfg.Logger.Named("cookiebanner.v1"),
@@ -261,6 +271,10 @@ func NewServer(cfg Config) (*Server, error) {
},
cfg.GraphQLLimits,
),
agentHandler: agent_v1.NewMux(
cfg.Logger.Named("agent.v1"),
cfg.ITAM,
),
}, nil
}
@@ -293,6 +307,10 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// list that applies to console/connect routes.
router.Mount("/cookie-banner/v1", http.StripPrefix("/cookie-banner/v1", s.cookieBannerHandler))
// Agent API should never be called from a browser; mount it outside
// to avoid CORS headers being set on it.
router.Mount("/agent/v1", http.StripPrefix("/agent/v1", s.agentHandler))
router.Group(func(r chi.Router) {
r.Use(cors.Handler(corsOpts))
r.Mount("/console/v1", http.StripPrefix("/console/v1", s.consoleHandler))