Building Enterprise Active Directory, LDAP & Dynamic RBAC in Go & Flutter with Google Antigravity Gubernator v2.20.0 introduces an enterprise security engine with Active Directory and LDAP integration, dynamic RBAC, and a Flutter Web UI, developed using Google Antigravity as an AI pair programmer. The feature supports multi-server directory dialers, LDAPS/StartTLS, and HMAC-SHA256 JWT tokens, with three operational tiers: admin, operator, and readonly. When building a lightweight container orchestrator like Gubernator gbnt — designed to strike the perfect balance between the While a default admin credential works well for local dev environments, moving into enterprise production with multi-disciplinary engineering teams demands: memberOf to orchestrator roles.In this article, we explore the complete architecture of the enterprise security engine introduced in Gubernator v2.20.0 , and how we leveraged Google Antigravity AGY as an autonomous AI pair programmer to design, implement, test, and verify this Full-Stack feature Go + Flutter Web across a live 3-node cluster. We designed a decoupled, asymmetric architecture connecting identity providers, REST API middleware, and the Flutter Web UI: ┌────────────────────────────────────────────────────────┐ │ GUBERNATOR WEB UI │ │ - Modern Login Screen with Domain / AD Selector │ │ - Header Role Badge: Admin | Ops | Read-Only. │ └──────────────────────────┬─────────────────────────────┘ │ REST /api/auth/login ▼ ┌────────────────────────────────────────────────────────┐ │ GUBERNATOR CORE AUTH ENGINE Go │ │ - Local Emergency Admin admin / admin fallback │ │ - Multi-Server Active Directory / OpenLDAP Dialers │ │ - LDAPS Port 636 & StartTLS Port 389 Handshake │ │ - Dynamic Group DN - RBAC Role Resolution │ │ - Cryptographic HMAC-SHA256 JWT Token Signing │ └─────────────┬────────────────────────────┬─────────────┘ │ │ ▼ ▼ ┌───────────────────────────┐ ┌──────────────────────────┐ │ Primary Active Directory │ │ Secondary LDAP Server │ │ dc1.corporate.local │ │ dc2.dr-site.local │ └───────────────────────────┘ └──────────────────────────┘ We established three distinct operational tiers: | Operational Capability | admin | operator | readonly | |---|---|---|---| Overview, Metrics & SRE Telemetry | ✅ Full | ✅ Full | ✅ Full | Deploy Stacks docker-compose.yml | ✅ Full | ✅ Full | ❌ Restricted | Redeploy & Duplicate Stacks | ✅ Full | ✅ Full | ❌ Restricted | Delete Stacks | ✅ Full | ❌ Restricted | ❌ Restricted | Task Lifecycle Start / Stop / Restart | ✅ Full | ✅ Full | ❌ Restricted | Container & Node Terminal Shell | ✅ Full | ✅ Full | ❌ Restricted | Node Fleet Management Drain / Activate / Leave | ✅ Full | ❌ Restricted | ❌ Restricted | Caddy TLS Certificates & Ingress Routes | ✅ Full | ❌ Restricted | ❌ Restricted | Active Directory & LDAP Directory Settings | ✅ Full | ❌ Restricted | ❌ Restricted | Grafana, Jaeger & Weave Scope Dashboards | ✅ Full | ✅ Full | ✅ Full | internal/auth/ For LDAP/Active Directory interactions, we used github.com/go-ldap/ldap/v3 , and for session management github.com/golang-jwt/jwt/v5 . Authentication follows a secure two-phase pattern: BindDN / BindPassword to query the directory. & objectClass=user sAMAccountName=%s . func AuthenticateLDAP cfg db.LDAPConfig, username, password string AuthResult, error { conn, err := ConnectLDAP cfg if err = nil { return nil, err } defer conn.Close // 1. Initial service account bind if cfg.BindDN = "" && cfg.BindPassword = "" { if err := conn.Bind cfg.BindDN, cfg.BindPassword ; err = nil { return nil, fmt.Errorf "service account bind failed: %w", err } } // 2. Search for the user filter := fmt.Sprintf cfg.UserFilter, ldap.EscapeFilter username searchReq := ldap.NewSearchRequest cfg.BaseDN, ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false, filter, string{"dn", "displayName", "mail", "memberOf"}, nil, sr, err := conn.Search searchReq if err = nil || len sr.Entries == 0 { return nil, errors.New "user not found in directory" } userEntry := sr.Entries 0 // 3. Direct user bind to verify password userConn, err := ConnectLDAP cfg if err = nil { return nil, err } defer userConn.Close if err := userConn.Bind userEntry.DN, password ; err = nil { return nil, errors.New "invalid credentials" } // 4. Map groups to RBAC role groups := userEntry.GetAttributeValues "memberOf" role := ResolveRole cfg, groups return &AuthResult{ UserDN: userEntry.DN, Username: username, DisplayName: userEntry.GetAttributeValue "displayName" , Email: userEntry.GetAttributeValue "mail" , Groups: groups, Role: role, }, nil } Gubernator inspects the user's memberOf group list and matches them against the configured group DNs: func ResolveRole cfg db.LDAPConfig, userGroups string Role { matchesGroup := func targetGroup string bool { if targetGroup == "" { return false } target := strings.ToLower strings.TrimSpace targetGroup for , g := range userGroups { if strings.ToLower strings.TrimSpace g == target { return true } } return false } if matchesGroup cfg.AdminGroupDN { return RoleAdmin } if matchesGroup cfg.OperatorGroupDN { return RoleOperator } if matchesGroup cfg.ReadOnlyGroupDN { return RoleReadOnly } return NormalizeRole cfg.DefaultRole } Gubernator's Web Dashboard is built with Flutter Web and Material Design 3 , compiled and embedded directly into the Go binary go:embed . Operators can select their target authentication provider Corporate Active Directory , DR Site LDAP , or Local Administrator : In the new Seguridad & AD tab, cluster administrators can configure directory servers, TLS certificates, and run a live "Test Connection" diagnostic tool: The dashboard header displays the active user and their assigned role ADMIN , ⚡ OPERATOR , READ-ONLY . Mutating actions e.g., Delete Stack, Drain Node, Shell are automatically disabled for read-only audit accounts. We utilized Google Antigravity AGY as an autonomous AI pair programmer to build this feature end-to-end. AGY accelerated the development cycle through several key workflows: Architectural Planning : Before writing code, Antigravity produced a comprehensive implementation plan implementation plan.md outlining the GORM schema changes LDAPConfig , RBAC authorization matrix, and API routes. Synchronized Full-Stack Implementation : In a single coordinated session, Antigravity: internal/auth/ engine with LDAP dialers, JWT session handlers, and Gin middlewares. login screen.dart , security page.dart , and state models . legions page.dart , tasks page.dart , centurions page.dart with RBAC permission guards. Live Cluster Testing & Verification : Using automated commands across a 3-node multipass cluster gbnt-manager , gbnt-worker1 , gbnt-worker2 , Antigravity: curl valid login, invalid login, LDAP connection tests, configuration lifecycle . go test ./internal/auth/... with 100% pass rates. Automated Documentation & Release : docs/auth-rbac.md v2.20.0 , created git release tags, and triggered GitHub Pages publishing.Adding Active Directory SSO and RBAC allows teams to deploy Gubernator in enterprise production environments that require enterprise security compliance without the operational overhead of Kubernetes. Check out Gubernator and try it out: What do you think about this hybrid approach to container orchestration? Let us know your thoughts and suggestions in the comments