key-cape/src/cmd/lldap-export/main.go

66 lines
1.9 KiB
Go
Raw Normal View History

// lldap-export exports the LLDAP directory as a canonical YAML snapshot
// for use with the validator and migration tools.
package main
import (
"context"
"flag"
"fmt"
"os"
"keycape/internal/adapters/lldap"
"keycape/internal/migration/lldapexport"
"keycape/internal/server/telemetry"
"keycape/internal/validator"
"github.com/rs/zerolog"
)
func main() {
// Flags.
url := flag.String("url", "ldap://localhost:389", "LLDAP server URL (ldap:// or ldaps://)")
bindDN := flag.String("bind-dn", "", "Service account bind DN (required)")
bindPW := flag.String("bind-pw", "", "Service account password (required)")
baseDN := flag.String("base-dn", "", "LDAP search base DN (required)")
output := flag.String("output", "canonical-export.yaml", "Output file path")
tlsSkip := flag.Bool("tls-skip-verify", false, "Skip TLS certificate verification (dev only)")
flag.Parse()
if *bindDN == "" || *baseDN == "" {
fmt.Fprintln(os.Stderr, "lldap-export: --bind-dn and --base-dn are required")
flag.Usage()
os.Exit(1)
}
log := zerolog.New(os.Stderr).With().Timestamp().Logger()
emitter := telemetry.NewLogEmitter(log)
cfg := lldap.Config{
URL: *url,
BindDN: *bindDN,
BindPW: *bindPW,
BaseDN: *baseDN,
TLSSkipVerify: *tlsSkip,
}
repo := lldap.New(cfg)
exp := lldapexport.New(repo, validator.ModeProvisioning, emitter)
result, err := exp.Export(context.Background(), *output)
if err != nil {
fmt.Fprintf(os.Stderr, "lldap-export: export failed: %v\n", err)
os.Exit(1)
}
fmt.Fprintf(os.Stdout, "Exported %d users, %d groups to %s\n",
len(result.Users), len(result.Groups), *output)
if len(result.IncompatibilityReport) > 0 {
fmt.Fprintln(os.Stderr, "Incompatibility report:")
for _, item := range result.IncompatibilityReport {
fmt.Fprintln(os.Stderr, " -", item)
}
os.Exit(2) // partial success: exported with warnings
}
}