Initial import — snapshot from admin host /srv/gosec/gsc-ops-api

This repo had no version control prior to this commit. The import is a
straight snapshot of the working tree at 2026-05-03; the deployed
binary on fihelvop01 was being rebuilt from this source via `make
build` + scp into place, with no upstream review path.

The snapshot already includes one in-flight fix made on 2026-05-03 to
internal/service/persona.go:GetSelfModel — the handler queried
`source` and `strength` columns plus an `is_active = true` filter on
persona.persona_commitments, none of which exist on that table (its
shape is session-bound commitments with `status`, `commitment_meta`,
etc.). The query returned a 500 every time SynapseHub bootstrapped a
persona's self-model, dropping the IdentityConstraints / Commitments /
ConscienceStandards layer from the assembled prompt. The patched
query reads existing columns only (commitment_text, commitment_type),
filters on `status='active'`, and synthesises Source="learned" /
Strength=1.0 to keep the SelfModel response shape stable for callers.

Verified live: `GET /api/v1/personas/70f7cfd9-.../self-model` now
returns 200 with `{identityConstraints:[],commitments:[],
conscienceStandards:[]}` instead of 500.

Future changes go through PRs against this repo — no more bin-only
deploys.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Claude (gsc-ops-api init)
2026-05-03 20:06:02 +02:00
commit 3847eb2036
68 changed files with 12982 additions and 0 deletions

View File

@@ -0,0 +1,341 @@
package schema
// registerAttributes registers all 292 GoSec LDAP attribute definitions
// organized by OID branch/domain.
func (r *Registry) registerAttributes() {
// ── common (7) ──────────────────────────────────────────────────
r.addAttr("gscCreatedAt", "createdAt", AttrTime, "common", true)
r.addAttr("gscModifiedAt", "modifiedAt", AttrTime, "common", true)
r.addAttr("gscCreatedBy", "createdBy", AttrDN, "common", true)
r.addAttr("gscModifiedBy", "modifiedBy", AttrDN, "common", true)
r.addAttr("gscDescription", "description", AttrString, "common", false)
r.addAttr("gscEnabled", "enabled", AttrBool, "common", false)
r.addAttr("gscNotes", "notes", AttrString, "common", false)
// ── tenant (10) ─────────────────────────────────────────────────
r.addAttr("gscTenantId", "tenantId", AttrString, "tenant", false)
r.addAttr("gscTenantName", "tenantName", AttrString, "tenant", false)
r.addAttr("gscTenantDomain", "tenantDomain", AttrString, "tenant", false)
r.addAttr("gscTenantStatus", "tenantStatus", AttrString, "tenant", false)
r.addAttr("gscTenantQuota", "tenantQuota", AttrInt, "tenant", false)
r.addAttr("gscTenantMaxUsers", "tenantMaxUsers", AttrInt, "tenant", false)
r.addAttr("gscTenantCreatedAt", "tenantCreatedAt", AttrTime, "tenant", true)
r.addAttr("gscTenantServices", "tenantServices", AttrStringMulti, "tenant", false)
r.addAttr("gscTenantAdminDN", "tenantAdminDN", AttrDN, "tenant", false)
r.addAttr("gscTenantParentDN", "tenantParentDN", AttrDN, "tenant", false)
// ── hash (5) ────────────────────────────────────────────────────
r.addAttr("gscUserTenantHash", "tenantHash", AttrString, "hash", true)
r.addAttr("gscUserTenantHashSalt", "tenantHashSalt", AttrString, "hash", true)
r.addAttr("gscUserTenantHashVersion", "tenantHashVersion", AttrInt, "hash", true)
r.addAttr("gscUserTenantHashCreatedAt", "tenantHashCreatedAt", AttrTime, "hash", true)
r.addAttr("gscUserTenantHashVerifiedAt", "tenantHashVerifiedAt", AttrTime, "hash", true)
// ── customer (7) ────────────────────────────────────────────────
r.addAttr("gscCustomerId", "customerId", AttrString, "customer", false)
r.addAttr("gscSID", "sid", AttrString, "customer", false)
r.addAttr("gscSIDCustomerPart", "sidCustomerPart", AttrString, "customer", false)
r.addAttr("gscSIDTenantPart", "sidTenantPart", AttrString, "customer", false)
r.addAttr("gscSIDSpecial1", "sidSpecial1", AttrString, "customer", false)
r.addAttr("gscSIDSpecial2", "sidSpecial2", AttrString, "customer", false)
r.addAttr("gscSIDUserPart", "sidUserPart", AttrString, "customer", false)
// ── mail (8) ────────────────────────────────────────────────────
r.addAttr("gscMailEnabled", "enabled", AttrBool, "mail", false)
r.addAttr("gscMailQuota", "quota", AttrInt, "mail", false)
r.addAttr("gscMailAlias", "alias", AttrStringMulti, "mail", false)
r.addAttr("gscMailForward", "forward", AttrString, "mail", false)
r.addAttr("gscMailAutoReply", "autoReply", AttrBool, "mail", false)
r.addAttr("gscMailAutoReplyMessage", "autoReplyMessage", AttrString, "mail", false)
r.addAttr("gscMailTransport", "transport", AttrString, "mail", false)
r.addAttr("gscMailDomain", "domain", AttrString, "mail", false)
// ── conf (5) ────────────────────────────────────────────────────
r.addAttr("gscConfEnabled", "enabled", AttrBool, "conf", false)
r.addAttr("gscConfRole", "role", AttrString, "conf", false)
r.addAttr("gscConfMaxParticipants", "maxParticipants", AttrInt, "conf", false)
r.addAttr("gscConfRecordingEnabled", "recordingEnabled", AttrBool, "conf", false)
r.addAttr("gscConfDefaultRoom", "defaultRoom", AttrString, "conf", false)
// ── ftp (6) ─────────────────────────────────────────────────────
r.addAttr("gscFtpEnabled", "enabled", AttrBool, "ftp", false)
r.addAttr("gscFtpQuota", "quota", AttrInt, "ftp", false)
r.addAttr("gscFtpHomeDir", "homeDir", AttrString, "ftp", false)
r.addAttr("gscFtpUploadBandwidth", "uploadBandwidth", AttrInt, "ftp", false)
r.addAttr("gscFtpDownloadBandwidth", "downloadBandwidth", AttrInt, "ftp", false)
r.addAttr("gscFtpAllowedIPs", "allowedIPs", AttrStringMulti, "ftp", false)
// ── file (5) ────────────────────────────────────────────────────
r.addAttr("gscFileEnabled", "enabled", AttrBool, "file", false)
r.addAttr("gscFileQuota", "quota", AttrInt, "file", false)
r.addAttr("gscFileHomeDir", "homeDir", AttrString, "file", false)
r.addAttr("gscFileVersioning", "versioning", AttrBool, "file", false)
r.addAttr("gscFileMaxFileSize", "maxFileSize", AttrInt, "file", false)
// ── sharing (5) ────────────────────────────────────────────────
r.addAttr("gscShareEnabled", "enabled", AttrBool, "sharing", false)
r.addAttr("gscShareExternalEnabled", "externalEnabled", AttrBool, "sharing", false)
r.addAttr("gscShareMaxRecipients", "maxRecipients", AttrInt, "sharing", false)
r.addAttr("gscShareDefaultExpiry", "defaultExpiry", AttrInt, "sharing", false)
r.addAttr("gscSharePasswordRequired", "passwordRequired", AttrBool, "sharing", false)
// ── calendar (5) ───────────────────────────────────────────────
r.addAttr("gscCalEnabled", "enabled", AttrBool, "calendar", false)
r.addAttr("gscCalDefaultCalendar", "defaultCalendar", AttrString, "calendar", false)
r.addAttr("gscCalTimezone", "timezone", AttrString, "calendar", false)
r.addAttr("gscCalFreeBusyPublic", "freeBusyPublic", AttrBool, "calendar", false)
r.addAttr("gscCalDelegates", "delegates", AttrDNMulti, "calendar", false)
// ── telephony (8) ──────────────────────────────────────────────
r.addAttr("gscTelEnabled", "enabled", AttrBool, "telephony", false)
r.addAttr("gscTelExtension", "extension", AttrString, "telephony", false)
r.addAttr("gscTelDID", "did", AttrString, "telephony", false)
r.addAttr("gscTelVoicemailEnabled", "voicemailEnabled", AttrBool, "telephony", false)
r.addAttr("gscTelVoicemailPin", "voicemailPin", AttrString, "telephony", false)
r.addAttr("gscTelCallForward", "callForward", AttrString, "telephony", false)
r.addAttr("gscTelCallGroup", "callGroup", AttrString, "telephony", false)
r.addAttr("gscTelRecordCalls", "recordCalls", AttrBool, "telephony", false)
// ── contacts (4) ──────────────────────────────────────────────
r.addAttr("gscContactsEnabled", "enabled", AttrBool, "contacts", false)
r.addAttr("gscContactsShared", "shared", AttrBool, "contacts", false)
r.addAttr("gscContactsMaxContacts", "maxContacts", AttrInt, "contacts", false)
r.addAttr("gscContactsExportEnabled", "exportEnabled", AttrBool, "contacts", false)
// ── ai (5) ─────────────────────────────────────────────────────
r.addAttr("gscAIEnabled", "enabled", AttrBool, "ai", false)
r.addAttr("gscAIModel", "model", AttrString, "ai", false)
r.addAttr("gscAIMaxTokens", "maxTokens", AttrInt, "ai", false)
r.addAttr("gscAIFeatures", "features", AttrStringMulti, "ai", false)
r.addAttr("gscAIUsageQuota", "usageQuota", AttrInt, "ai", false)
// ── resource (9) ──────────────────────────────────────────────
r.addAttr("gscResourceId", "resourceId", AttrString, "resource", false)
r.addAttr("gscResourceName", "resourceName", AttrString, "resource", false)
r.addAttr("gscResourceType", "resourceType", AttrString, "resource", false)
r.addAttr("gscResourceEmail", "resourceEmail", AttrString, "resource", false)
r.addAttr("gscResourceCapacity", "capacity", AttrInt, "resource", false)
r.addAttr("gscResourceLocation", "location", AttrString, "resource", false)
r.addAttr("gscResourceBookable", "bookable", AttrBool, "resource", false)
r.addAttr("gscResourceApprovalRequired", "approvalRequired", AttrBool, "resource", false)
r.addAttr("gscResourceOwnerDN", "ownerDN", AttrDN, "resource", false)
// ── dlp (10) ──────────────────────────────────────────────────
r.addAttr("gscDlpEnabled", "enabled", AttrBool, "dlp", false)
r.addAttr("gscDlpPolicyDN", "policyDN", AttrDNMulti, "dlp", false)
r.addAttr("gscDlpExempt", "exempt", AttrBool, "dlp", false)
r.addAttr("gscDlpPolicyName", "policyName", AttrString, "dlp", false)
r.addAttr("gscDlpPolicyType", "policyType", AttrString, "dlp", false)
r.addAttr("gscDlpPolicyRules", "policyRules", AttrStringMulti, "dlp", false)
r.addAttr("gscDlpPolicyAction", "policyAction", AttrString, "dlp", false)
r.addAttr("gscDlpPolicyPriority", "policyPriority", AttrInt, "dlp", false)
r.addAttr("gscDlpPolicyScope", "policyScope", AttrStringMulti, "dlp", false)
r.addAttr("gscDlpPolicyStatus", "policyStatus", AttrString, "dlp", false)
// ── sensitivity (9) ──────────────────────────────────────────
r.addAttr("gscSensitivityEnabled", "enabled", AttrBool, "sensitivity", false)
r.addAttr("gscSensitivityDefaultLabel", "defaultLabel", AttrString, "sensitivity", false)
r.addAttr("gscSensitivityLabelName", "labelName", AttrString, "sensitivity", false)
r.addAttr("gscSensitivityLabelPriority", "labelPriority", AttrInt, "sensitivity", false)
r.addAttr("gscSensitivityLabelColor", "labelColor", AttrString, "sensitivity", false)
r.addAttr("gscSensitivityLabelTooltip", "labelTooltip", AttrString, "sensitivity", false)
r.addAttr("gscSensitivityLabelScope", "labelScope", AttrStringMulti, "sensitivity", false)
r.addAttr("gscSensitivityEncryptionRequired", "encryptionRequired", AttrBool, "sensitivity", false)
r.addAttr("gscSensitivityWatermark", "watermark", AttrBool, "sensitivity", false)
// ── encryption (8) ──────────────────────────────────────────
r.addAttr("gscEncryptionEnabled", "enabled", AttrBool, "encryption", false)
r.addAttr("gscEncryptionKeyDN", "keyDN", AttrDN, "encryption", false)
r.addAttr("gscEncryptionPolicyName", "policyName", AttrString, "encryption", false)
r.addAttr("gscEncryptionPolicyType", "policyType", AttrString, "encryption", false)
r.addAttr("gscEncryptionAlgorithm", "algorithm", AttrString, "encryption", false)
r.addAttr("gscEncryptionKeyLength", "keyLength", AttrInt, "encryption", false)
r.addAttr("gscEncryptionScope", "scope", AttrStringMulti, "encryption", false)
r.addAttr("gscEncryptionPolicyStatus", "policyStatus", AttrString, "encryption", false)
// ── retention (10) ──────────────────────────────────────────
r.addAttr("gscRetentionEnabled", "enabled", AttrBool, "retention", false)
r.addAttr("gscRetentionPolicyDN", "policyDN", AttrDNMulti, "retention", false)
r.addAttr("gscRetentionPolicyName", "policyName", AttrString, "retention", false)
r.addAttr("gscRetentionPolicyType", "policyType", AttrString, "retention", false)
r.addAttr("gscRetentionDuration", "duration", AttrInt, "retention", false)
r.addAttr("gscRetentionAction", "action", AttrString, "retention", false)
r.addAttr("gscRetentionScope", "scope", AttrStringMulti, "retention", false)
r.addAttr("gscRetentionPolicyStatus", "policyStatus", AttrString, "retention", false)
r.addAttr("gscRetentionExcludeFolders", "excludeFolders", AttrStringMulti, "retention", false)
r.addAttr("gscRetentionLegalHold", "legalHold", AttrBool, "retention", false)
// ── ediscovery (11) ─────────────────────────────────────────
r.addAttr("gscEDiscoveryEnabled", "enabled", AttrBool, "ediscovery", false)
r.addAttr("gscEDiscoveryCustodian", "custodian", AttrBool, "ediscovery", false)
r.addAttr("gscEDiscoveryCaseName", "caseName", AttrString, "ediscovery", false)
r.addAttr("gscEDiscoveryCaseStatus", "caseStatus", AttrString, "ediscovery", false)
r.addAttr("gscEDiscoveryCaseCreatedAt", "caseCreatedAt", AttrTime, "ediscovery", false)
r.addAttr("gscEDiscoveryCaseClosedAt", "caseClosedAt", AttrTime, "ediscovery", false)
r.addAttr("gscEDiscoveryHoldName", "holdName", AttrString, "ediscovery", false)
r.addAttr("gscEDiscoveryHoldScope", "holdScope", AttrStringMulti, "ediscovery", false)
r.addAttr("gscEDiscoveryHoldStatus", "holdStatus", AttrString, "ediscovery", false)
r.addAttr("gscEDiscoveryHoldCreatedAt", "holdCreatedAt", AttrTime, "ediscovery", false)
r.addAttr("gscEDiscoverySearchQuery", "searchQuery", AttrString, "ediscovery", false)
// ── audit (9) ───────────────────────────────────────────────
r.addAttr("gscAuditEnabled", "enabled", AttrBool, "audit", false)
r.addAttr("gscAuditLevel", "level", AttrString, "audit", false)
r.addAttr("gscAuditPolicyName", "policyName", AttrString, "audit", false)
r.addAttr("gscAuditPolicyScope", "policyScope", AttrStringMulti, "audit", false)
r.addAttr("gscAuditPolicyActions", "policyActions", AttrStringMulti, "audit", false)
r.addAttr("gscAuditPolicyStatus", "policyStatus", AttrString, "audit", false)
r.addAttr("gscAuditRetentionDays", "retentionDays", AttrInt, "audit", false)
r.addAttr("gscAuditAlertEnabled", "alertEnabled", AttrBool, "audit", false)
r.addAttr("gscAuditAlertRecipients", "alertRecipients", AttrStringMulti, "audit", false)
// ── iam (12) ────────────────────────────────────────────────
r.addAttr("gscIAMEnabled", "enabled", AttrBool, "iam", false)
r.addAttr("gscIAMMFARequired", "mfaRequired", AttrBool, "iam", false)
r.addAttr("gscIAMMFAMethod", "mfaMethod", AttrString, "iam", false)
r.addAttr("gscIAMPasswordPolicy", "passwordPolicy", AttrString, "iam", false)
r.addAttr("gscIAMSessionTimeout", "sessionTimeout", AttrInt, "iam", false)
r.addAttr("gscIAMMaxSessions", "maxSessions", AttrInt, "iam", false)
r.addAttr("gscIAMIPRestrictions", "ipRestrictions", AttrStringMulti, "iam", false)
r.addAttr("gscIAMRiskLevel", "riskLevel", AttrString, "iam", false)
r.addAttr("gscIAMCAPolicyName", "caPolicyName", AttrString, "iam", false)
r.addAttr("gscIAMCAPolicyConditions", "caPolicyConditions", AttrStringMulti, "iam", false)
r.addAttr("gscIAMCAPolicyActions", "caPolicyActions", AttrStringMulti, "iam", false)
r.addAttr("gscIAMCAPolicyStatus", "caPolicyStatus", AttrString, "iam", false)
// ── collaboration (10) ──────────────────────────────────────
r.addAttr("gscCollabEnabled", "enabled", AttrBool, "collaboration", false)
r.addAttr("gscCollabTeamsEnabled", "teamsEnabled", AttrBool, "collaboration", false)
r.addAttr("gscCollabChannelsEnabled", "channelsEnabled", AttrBool, "collaboration", false)
r.addAttr("gscCollabExternalEnabled", "externalEnabled", AttrBool, "collaboration", false)
r.addAttr("gscCollabPolicyName", "policyName", AttrString, "collaboration", false)
r.addAttr("gscCollabPolicyScope", "policyScope", AttrStringMulti, "collaboration", false)
r.addAttr("gscCollabPolicyActions", "policyActions", AttrStringMulti, "collaboration", false)
r.addAttr("gscCollabPolicyStatus", "policyStatus", AttrString, "collaboration", false)
r.addAttr("gscCollabMaxTeamSize", "maxTeamSize", AttrInt, "collaboration", false)
r.addAttr("gscCollabGuestAccessEnabled", "guestAccessEnabled", AttrBool, "collaboration", false)
// ── barriers (9) ───────────────────────────────────────────
r.addAttr("gscBarrierEnabled", "enabled", AttrBool, "barriers", false)
r.addAttr("gscBarrierSegmentDN", "segmentDN", AttrDNMulti, "barriers", false)
r.addAttr("gscBarrierSegmentName", "segmentName", AttrString, "barriers", false)
r.addAttr("gscBarrierSegmentMembers", "segmentMembers", AttrDNMulti, "barriers", false)
r.addAttr("gscBarrierPolicyName", "policyName", AttrString, "barriers", false)
r.addAttr("gscBarrierPolicyType", "policyType", AttrString, "barriers", false)
r.addAttr("gscBarrierPolicySegments", "policySegments", AttrStringMulti, "barriers", false)
r.addAttr("gscBarrierPolicyAction", "policyAction", AttrString, "barriers", false)
r.addAttr("gscBarrierPolicyStatus", "policyStatus", AttrString, "barriers", false)
// ── guest (26) ─────────────────────────────────────────────
// identity core
r.addAttr("gscGuestEnabled", "enabled", AttrBool, "guest", false)
r.addAttr("gscGuestType", "type", AttrString, "guest", false)
r.addAttr("gscGuestOrganization", "organization", AttrString, "guest", false)
r.addAttr("gscGuestExternalEmail", "externalEmail", AttrString, "guest", false)
r.addAttr("gscGuestVerified", "verified", AttrBool, "guest", false)
// federation
r.addAttr("gscGuestFederatedIdpDN", "federatedIdpDN", AttrDN, "guest", false)
r.addAttr("gscGuestFederatedId", "federatedId", AttrString, "guest", false)
r.addAttr("gscGuestIdpName", "idpName", AttrString, "guest", false)
r.addAttr("gscGuestIdpType", "idpType", AttrString, "guest", false)
r.addAttr("gscGuestIdpEntityId", "idpEntityId", AttrString, "guest", false)
r.addAttr("gscGuestIdpMetadataURL", "idpMetadataURL", AttrString, "guest", false)
r.addAttr("gscGuestIdpDomains", "idpDomains", AttrStringMulti, "guest", false)
r.addAttr("gscGuestIdpStatus", "idpStatus", AttrString, "guest", false)
// access control
r.addAttr("gscGuestAccessScope", "accessScope", AttrStringMulti, "guest", false)
r.addAttr("gscGuestPermissionLevel", "permissionLevel", AttrString, "guest", false)
r.addAttr("gscGuestResourceDN", "resourceDN", AttrDNMulti, "guest", false)
// invitation/audit
r.addAttr("gscGuestInvitedBy", "invitedBy", AttrDN, "guest", true)
r.addAttr("gscGuestInvitedAt", "invitedAt", AttrTime, "guest", true)
r.addAttr("gscGuestExpiresAt", "expiresAt", AttrTime, "guest", false)
r.addAttr("gscGuestLastAccessAt", "lastAccessAt", AttrTime, "guest", true)
r.addAttr("gscGuestAccessCount", "accessCount", AttrInt, "guest", true)
// policy/restrictions
r.addAttr("gscGuestPolicyName", "policyName", AttrString, "guest", false)
r.addAttr("gscGuestPolicyScope", "policyScope", AttrStringMulti, "guest", false)
r.addAttr("gscGuestPolicyAction", "policyAction", AttrString, "guest", false)
r.addAttr("gscGuestPolicyStatus", "policyStatus", AttrString, "guest", false)
r.addAttr("gscGuestMaxDuration", "maxDuration", AttrInt, "guest", false)
// ── kms-user (12) ──────────────────────────────────────────
r.addAttr("gscKmsEnabled", "enabled", AttrBool, "kms-user", false)
r.addAttr("gscKmsRole", "role", AttrString, "kms-user", false)
r.addAttr("gscKmsKeyAccess", "keyAccess", AttrStringMulti, "kms-user", false)
r.addAttr("gscKmsMaxKeys", "maxKeys", AttrInt, "kms-user", false)
r.addAttr("gscKmsAllowedAlgorithms", "allowedAlgorithms", AttrStringMulti, "kms-user", false)
r.addAttr("gscKmsAllowedOperations", "allowedOperations", AttrStringMulti, "kms-user", false)
r.addAttr("gscKmsApprovalRequired", "approvalRequired", AttrBool, "kms-user", false)
r.addAttr("gscKmsAuditEnabled", "auditEnabled", AttrBool, "kms-user", false)
r.addAttr("gscKmsLastKeyAccess", "lastKeyAccess", AttrTime, "kms-user", true)
r.addAttr("gscKmsKeyCount", "keyCount", AttrInt, "kms-user", true)
r.addAttr("gscKmsPolicyDN", "policyDN", AttrDNMulti, "kms-user", false)
r.addAttr("gscKmsHsmAccess", "hsmAccess", AttrBool, "kms-user", false)
// ── kms-tenant (12) ────────────────────────────────────────
r.addAttr("gscKmsTenantEnabled", "enabled", AttrBool, "kms-tenant", false)
r.addAttr("gscKmsTenantMaxKeys", "maxKeys", AttrInt, "kms-tenant", false)
r.addAttr("gscKmsTenantAllowedAlgorithms", "allowedAlgorithms", AttrStringMulti, "kms-tenant", false)
r.addAttr("gscKmsTenantKeyRotationDays", "keyRotationDays", AttrInt, "kms-tenant", false)
r.addAttr("gscKmsTenantHsmEnabled", "hsmEnabled", AttrBool, "kms-tenant", false)
r.addAttr("gscKmsTenantHsmPartition", "hsmPartition", AttrString, "kms-tenant", false)
r.addAttr("gscKmsTenantAutoRotate", "autoRotate", AttrBool, "kms-tenant", false)
r.addAttr("gscKmsTenantKeyCount", "keyCount", AttrInt, "kms-tenant", true)
r.addAttr("gscKmsTenantQuota", "quota", AttrInt, "kms-tenant", false)
r.addAttr("gscKmsTenantDefaultAlgorithm", "defaultAlgorithm", AttrString, "kms-tenant", false)
r.addAttr("gscKmsTenantDefaultKeyLength", "defaultKeyLength", AttrInt, "kms-tenant", false)
r.addAttr("gscKmsTenantPolicyDN", "policyDN", AttrDNMulti, "kms-tenant", false)
// ── managed-key (21) ───────────────────────────────────────
r.addAttr("gscKeyId", "keyId", AttrString, "managed-key", false)
r.addAttr("gscKeyName", "keyName", AttrString, "managed-key", false)
r.addAttr("gscKeyAlgorithm", "algorithm", AttrString, "managed-key", false)
r.addAttr("gscKeyLength", "keyLength", AttrInt, "managed-key", false)
r.addAttr("gscKeyType", "keyType", AttrString, "managed-key", false)
r.addAttr("gscKeyStatus", "status", AttrString, "managed-key", false)
r.addAttr("gscKeyCreatedAt", "createdAt", AttrTime, "managed-key", true)
r.addAttr("gscKeyExpiresAt", "expiresAt", AttrTime, "managed-key", false)
r.addAttr("gscKeyRotatedAt", "rotatedAt", AttrTime, "managed-key", true)
r.addAttr("gscKeyOwnerDN", "ownerDN", AttrDN, "managed-key", false)
r.addAttr("gscKeyTenantDN", "tenantDN", AttrDN, "managed-key", false)
r.addAttr("gscKeyOperations", "operations", AttrStringMulti, "managed-key", false)
r.addAttr("gscKeyMaterial", "material", AttrString, "managed-key", false)
r.addAttr("gscKeyPublicKey", "publicKey", AttrString, "managed-key", false)
r.addAttr("gscKeyFingerprint", "fingerprint", AttrString, "managed-key", true)
r.addAttr("gscKeyVersion", "version", AttrInt, "managed-key", false)
r.addAttr("gscKeyPreviousVersionDN", "previousVersionDN", AttrDN, "managed-key", false)
r.addAttr("gscKeyHsmBacked", "hsmBacked", AttrBool, "managed-key", false)
r.addAttr("gscKeyHsmSlot", "hsmSlot", AttrString, "managed-key", false)
r.addAttr("gscKeyAutoRotate", "autoRotate", AttrBool, "managed-key", false)
r.addAttr("gscKeyRotationDays", "rotationDays", AttrInt, "managed-key", false)
// ── kms-policy (15) ────────────────────────────────────────
r.addAttr("gscKmsPolicyId", "policyId", AttrString, "kms-policy", false)
r.addAttr("gscKmsPolicyName", "policyName", AttrString, "kms-policy", false)
r.addAttr("gscKmsPolicyType", "policyType", AttrString, "kms-policy", false)
r.addAttr("gscKmsPolicyEffect", "effect", AttrString, "kms-policy", false)
r.addAttr("gscKmsPolicyPrincipalDN", "principalDN", AttrDNMulti, "kms-policy", false)
r.addAttr("gscKmsPolicyResourceDN", "resourceDN", AttrDNMulti, "kms-policy", false)
r.addAttr("gscKmsPolicyOperations", "operations", AttrStringMulti, "kms-policy", false)
r.addAttr("gscKmsPolicyConditions", "conditions", AttrStringMulti, "kms-policy", false)
r.addAttr("gscKmsPolicyPriority", "priority", AttrInt, "kms-policy", false)
r.addAttr("gscKmsPolicyStatus", "status", AttrString, "kms-policy", false)
r.addAttr("gscKmsPolicyCreatedAt", "createdAt", AttrTime, "kms-policy", true)
r.addAttr("gscKmsPolicyModifiedAt", "modifiedAt", AttrTime, "kms-policy", true)
r.addAttr("gscKmsPolicyTenantDN", "tenantDN", AttrDN, "kms-policy", false)
r.addAttr("gscKmsPolicyMaxKeyAge", "maxKeyAge", AttrInt, "kms-policy", false)
r.addAttr("gscKmsPolicyRequireHsm", "requireHsm", AttrBool, "kms-policy", false)
// ── hsm-config (10) ────────────────────────────────────────
r.addAttr("gscHsmConfigId", "configId", AttrString, "hsm-config", false)
r.addAttr("gscHsmConfigName", "configName", AttrString, "hsm-config", false)
r.addAttr("gscHsmConfigType", "type", AttrString, "hsm-config", false)
r.addAttr("gscHsmConfigVendor", "vendor", AttrString, "hsm-config", false)
r.addAttr("gscHsmConfigModel", "model", AttrString, "hsm-config", false)
r.addAttr("gscHsmConfigConnectionString", "connectionString", AttrString, "hsm-config", false)
r.addAttr("gscHsmConfigSlots", "slots", AttrStringMulti, "hsm-config", false)
r.addAttr("gscHsmConfigStatus", "status", AttrString, "hsm-config", false)
r.addAttr("gscHsmConfigMaxKeys", "maxKeys", AttrInt, "hsm-config", false)
r.addAttr("gscHsmConfigTenantDN", "tenantDN", AttrDNMulti, "hsm-config", false)
}

112
internal/schema/entities.go Normal file
View File

@@ -0,0 +1,112 @@
package schema
// registerEntities registers all 18 entity type definitions for generic CRUD.
func (r *Registry) registerEntities() {
r.addEntityType("tenant", "Organization tenant",
[]string{"top", "gscTenant"},
"ou=tenants", "gscTenantId",
"(objectClass=gscTenant)", "tenant",
[]string{"gscTenantId", "gscTenantName"})
r.addEntityType("resource", "Shared resource (room, equipment)",
[]string{"top", "gscResource"},
"ou=tenants", "gscResourceId",
"(objectClass=gscResource)", "resource",
[]string{"gscResourceId", "gscResourceName", "gscResourceType"})
r.addEntityType("dlp-policy", "Data loss prevention policy",
[]string{"top", "gscDlpPolicy"},
"ou=dlp,ou=compliance", "cn",
"(objectClass=gscDlpPolicy)", "dlp",
[]string{"gscDlpPolicyName"})
r.addEntityType("sensitivity-label", "Sensitivity classification label",
[]string{"top", "gscSensitivityLabel"},
"ou=sensitivity,ou=compliance", "cn",
"(objectClass=gscSensitivityLabel)", "sensitivity",
[]string{"gscSensitivityLabelName"})
r.addEntityType("encryption-policy", "Encryption policy",
[]string{"top", "gscEncryptionPolicy"},
"ou=encryption,ou=compliance", "cn",
"(objectClass=gscEncryptionPolicy)", "encryption",
[]string{"gscEncryptionPolicyName"})
r.addEntityType("retention-policy", "Data retention policy",
[]string{"top", "gscRetentionPolicy"},
"ou=retention,ou=compliance", "cn",
"(objectClass=gscRetentionPolicy)", "retention",
[]string{"gscRetentionPolicyName"})
r.addEntityType("ediscovery-case", "eDiscovery case",
[]string{"top", "gscEDiscoveryCase"},
"ou=ediscovery,ou=compliance", "cn",
"(objectClass=gscEDiscoveryCase)", "ediscovery",
[]string{"gscEDiscoveryCaseName"})
r.addEntityType("ediscovery-hold", "eDiscovery legal hold",
[]string{"top", "gscEDiscoveryHold"},
"ou=ediscovery,ou=compliance", "cn",
"(objectClass=gscEDiscoveryHold)", "ediscovery",
[]string{"gscEDiscoveryHoldName"})
r.addEntityType("audit-policy", "Audit logging policy",
[]string{"top", "gscAuditPolicy"},
"ou=audit,ou=compliance", "cn",
"(objectClass=gscAuditPolicy)", "audit",
[]string{"gscAuditPolicyName"})
r.addEntityType("ca-policy", "Conditional access policy",
[]string{"top", "gscConditionalAccessPolicy"},
"ou=iam,ou=compliance", "cn",
"(objectClass=gscConditionalAccessPolicy)", "iam",
[]string{"gscIAMCAPolicyName"})
r.addEntityType("collab-policy", "Collaboration policy",
[]string{"top", "gscCollaborationPolicy"},
"ou=collaboration,ou=compliance", "cn",
"(objectClass=gscCollaborationPolicy)", "collaboration",
[]string{"gscCollabPolicyName"})
r.addEntityType("barrier-segment", "Information barrier segment",
[]string{"top", "gscBarrierSegment"},
"ou=barriers,ou=compliance", "cn",
"(objectClass=gscBarrierSegment)", "barriers",
[]string{"gscBarrierSegmentName"})
r.addEntityType("barrier-policy", "Information barrier policy",
[]string{"top", "gscBarrierPolicy"},
"ou=barriers,ou=compliance", "cn",
"(objectClass=gscBarrierPolicy)", "barriers",
[]string{"gscBarrierPolicyName"})
r.addEntityType("guest-policy", "Guest access policy",
[]string{"top", "gscGuestPolicy"},
"ou=policies,ou=guests", "cn",
"(objectClass=gscGuestPolicy)", "guest",
[]string{"gscGuestPolicyName"})
r.addEntityType("federated-idp", "Federated identity provider",
[]string{"top", "gscFederatedIdp"},
"ou=idps,ou=guests", "cn",
"(objectClass=gscFederatedIdp)", "guest",
[]string{"gscGuestIdpName"})
r.addEntityType("managed-key", "Managed encryption key",
[]string{"top", "gscManagedKey"},
"ou=keys,ou=keymanagement", "gscKeyId",
"(objectClass=gscManagedKey)", "managed-key",
[]string{"gscKeyId", "gscKeyName", "gscKeyAlgorithm"})
r.addEntityType("kms-policy", "Key management policy",
[]string{"top", "gscKmsPolicy"},
"ou=policies,ou=keymanagement", "gscKmsPolicyId",
"(objectClass=gscKmsPolicy)", "kms-policy",
[]string{"gscKmsPolicyId", "gscKmsPolicyName"})
r.addEntityType("hsm-config", "HSM hardware configuration",
[]string{"top", "gscHsmConfig"},
"ou=hsmconfigs,ou=keymanagement", "gscHsmConfigId",
"(objectClass=gscHsmConfig)", "hsm-config",
[]string{"gscHsmConfigId", "gscHsmConfigName"})
}

View File

@@ -0,0 +1,230 @@
package schema
// registerObjectClasses registers all 45 GoSec LDAP objectClass definitions.
func (r *Registry) registerObjectClasses() {
// ── AUXILIARY user objectClasses (21) ────────────────────────
r.addObjectClass("gscTenantUser", "AUXILIARY",
[]string{"gscTenantId"},
[]string{"gscTenantName", "gscTenantDomain", "gscTenantStatus", "gscUserTenantHash", "gscUserTenantHashSalt", "gscUserTenantHashVersion", "gscUserTenantHashCreatedAt", "gscUserTenantHashVerifiedAt", "gscCustomerId", "gscSID", "gscSIDCustomerPart", "gscSIDTenantPart", "gscSIDSpecial1", "gscSIDSpecial2", "gscSIDUserPart", "gscCreatedAt", "gscModifiedAt", "gscCreatedBy", "gscModifiedBy"},
"tenant")
r.addObjectClass("gscMailUser", "AUXILIARY",
[]string{"gscMailEnabled"},
[]string{"gscMailQuota", "gscMailAlias", "gscMailForward", "gscMailAutoReply", "gscMailAutoReplyMessage", "gscMailTransport", "gscMailDomain"},
"mail")
r.addObjectClass("gscConfUser", "AUXILIARY",
[]string{"gscConfEnabled"},
[]string{"gscConfRole", "gscConfMaxParticipants", "gscConfRecordingEnabled", "gscConfDefaultRoom"},
"conf")
r.addObjectClass("gscFtpUser", "AUXILIARY",
[]string{"gscFtpEnabled"},
[]string{"gscFtpQuota", "gscFtpHomeDir", "gscFtpUploadBandwidth", "gscFtpDownloadBandwidth", "gscFtpAllowedIPs"},
"ftp")
r.addObjectClass("gscFileUser", "AUXILIARY",
[]string{"gscFileEnabled"},
[]string{"gscFileQuota", "gscFileHomeDir", "gscFileVersioning", "gscFileMaxFileSize"},
"file")
r.addObjectClass("gscShareUser", "AUXILIARY",
[]string{"gscShareEnabled"},
[]string{"gscShareExternalEnabled", "gscShareMaxRecipients", "gscShareDefaultExpiry", "gscSharePasswordRequired"},
"sharing")
r.addObjectClass("gscCalUser", "AUXILIARY",
[]string{"gscCalEnabled"},
[]string{"gscCalDefaultCalendar", "gscCalTimezone", "gscCalFreeBusyPublic", "gscCalDelegates"},
"calendar")
r.addObjectClass("gscTelUser", "AUXILIARY",
[]string{"gscTelEnabled"},
[]string{"gscTelExtension", "gscTelDID", "gscTelVoicemailEnabled", "gscTelVoicemailPin", "gscTelCallForward", "gscTelCallGroup", "gscTelRecordCalls"},
"telephony")
r.addObjectClass("gscContactsUser", "AUXILIARY",
[]string{"gscContactsEnabled"},
[]string{"gscContactsShared", "gscContactsMaxContacts", "gscContactsExportEnabled"},
"contacts")
r.addObjectClass("gscAIUser", "AUXILIARY",
[]string{"gscAIEnabled"},
[]string{"gscAIModel", "gscAIMaxTokens", "gscAIFeatures", "gscAIUsageQuota"},
"ai")
r.addObjectClass("gscDlpUser", "AUXILIARY",
[]string{"gscDlpEnabled"},
[]string{"gscDlpPolicyDN", "gscDlpExempt"},
"dlp")
r.addObjectClass("gscSensitivityUser", "AUXILIARY",
[]string{"gscSensitivityEnabled"},
[]string{"gscSensitivityDefaultLabel"},
"sensitivity")
r.addObjectClass("gscEncryptionUser", "AUXILIARY",
[]string{"gscEncryptionEnabled"},
[]string{"gscEncryptionKeyDN"},
"encryption")
r.addObjectClass("gscRetentionUser", "AUXILIARY",
[]string{"gscRetentionEnabled"},
[]string{"gscRetentionPolicyDN"},
"retention")
r.addObjectClass("gscEDiscoveryUser", "AUXILIARY",
[]string{"gscEDiscoveryEnabled"},
[]string{"gscEDiscoveryCustodian"},
"ediscovery")
r.addObjectClass("gscAdvancedAuditUser", "AUXILIARY",
[]string{"gscAuditEnabled"},
[]string{"gscAuditLevel"},
"audit")
r.addObjectClass("gscIAMUser", "AUXILIARY",
[]string{"gscIAMEnabled"},
[]string{"gscIAMMFARequired", "gscIAMMFAMethod", "gscIAMPasswordPolicy", "gscIAMSessionTimeout", "gscIAMMaxSessions", "gscIAMIPRestrictions", "gscIAMRiskLevel"},
"iam")
r.addObjectClass("gscCollaborationUser", "AUXILIARY",
[]string{"gscCollabEnabled"},
[]string{"gscCollabTeamsEnabled", "gscCollabChannelsEnabled", "gscCollabExternalEnabled"},
"collaboration")
r.addObjectClass("gscBarrierUser", "AUXILIARY",
[]string{"gscBarrierEnabled"},
[]string{"gscBarrierSegmentDN"},
"barriers")
r.addObjectClass("gscGuestUser", "AUXILIARY",
[]string{"gscGuestEnabled"},
[]string{"gscGuestType", "gscGuestOrganization", "gscGuestExternalEmail", "gscGuestVerified", "gscGuestFederatedIdpDN", "gscGuestFederatedId", "gscGuestAccessScope", "gscGuestPermissionLevel", "gscGuestResourceDN", "gscGuestInvitedBy", "gscGuestInvitedAt", "gscGuestExpiresAt", "gscGuestLastAccessAt", "gscGuestAccessCount"},
"guest")
r.addObjectClass("gscKmsUser", "AUXILIARY",
[]string{"gscKmsEnabled"},
[]string{"gscKmsRole", "gscKmsKeyAccess", "gscKmsMaxKeys", "gscKmsAllowedAlgorithms", "gscKmsAllowedOperations", "gscKmsApprovalRequired", "gscKmsAuditEnabled", "gscKmsLastKeyAccess", "gscKmsKeyCount", "gscKmsPolicyDN", "gscKmsHsmAccess"},
"kms-user")
// ── STRUCTURAL entity objectClasses (18) ────────────────────
r.addObjectClass("gscTenant", "STRUCTURAL",
[]string{"gscTenantId", "gscTenantName"},
[]string{"gscTenantDomain", "gscTenantStatus", "gscTenantQuota", "gscTenantMaxUsers", "gscTenantCreatedAt", "gscTenantServices", "gscTenantAdminDN", "gscTenantParentDN", "gscDescription", "gscEnabled", "gscNotes", "gscCreatedAt", "gscModifiedAt", "gscCreatedBy", "gscModifiedBy"},
"tenant")
r.addObjectClass("gscResource", "STRUCTURAL",
[]string{"gscResourceId", "gscResourceName", "gscResourceType"},
[]string{"gscResourceEmail", "gscResourceCapacity", "gscResourceLocation", "gscResourceBookable", "gscResourceApprovalRequired", "gscResourceOwnerDN", "gscDescription", "gscEnabled", "gscCreatedAt", "gscModifiedAt"},
"resource")
r.addObjectClass("gscDlpPolicy", "STRUCTURAL",
[]string{"gscDlpPolicyName"},
[]string{"gscDlpPolicyType", "gscDlpPolicyRules", "gscDlpPolicyAction", "gscDlpPolicyPriority", "gscDlpPolicyScope", "gscDlpPolicyStatus", "gscDescription", "gscEnabled", "gscCreatedAt", "gscModifiedAt"},
"dlp")
r.addObjectClass("gscSensitivityLabel", "STRUCTURAL",
[]string{"gscSensitivityLabelName"},
[]string{"gscSensitivityLabelPriority", "gscSensitivityLabelColor", "gscSensitivityLabelTooltip", "gscSensitivityLabelScope", "gscSensitivityEncryptionRequired", "gscSensitivityWatermark", "gscDescription", "gscEnabled", "gscCreatedAt", "gscModifiedAt"},
"sensitivity")
r.addObjectClass("gscEncryptionPolicy", "STRUCTURAL",
[]string{"gscEncryptionPolicyName"},
[]string{"gscEncryptionPolicyType", "gscEncryptionAlgorithm", "gscEncryptionKeyLength", "gscEncryptionScope", "gscEncryptionPolicyStatus", "gscDescription", "gscEnabled", "gscCreatedAt", "gscModifiedAt"},
"encryption")
r.addObjectClass("gscRetentionPolicy", "STRUCTURAL",
[]string{"gscRetentionPolicyName"},
[]string{"gscRetentionPolicyType", "gscRetentionDuration", "gscRetentionAction", "gscRetentionScope", "gscRetentionPolicyStatus", "gscRetentionExcludeFolders", "gscRetentionLegalHold", "gscDescription", "gscEnabled", "gscCreatedAt", "gscModifiedAt"},
"retention")
r.addObjectClass("gscEDiscoveryCase", "STRUCTURAL",
[]string{"gscEDiscoveryCaseName"},
[]string{"gscEDiscoveryCaseStatus", "gscEDiscoveryCaseCreatedAt", "gscEDiscoveryCaseClosedAt", "gscDescription", "gscEnabled", "gscCreatedAt", "gscModifiedAt"},
"ediscovery")
r.addObjectClass("gscEDiscoveryHold", "STRUCTURAL",
[]string{"gscEDiscoveryHoldName"},
[]string{"gscEDiscoveryHoldScope", "gscEDiscoveryHoldStatus", "gscEDiscoveryHoldCreatedAt", "gscEDiscoverySearchQuery", "gscDescription", "gscEnabled", "gscCreatedAt", "gscModifiedAt"},
"ediscovery")
r.addObjectClass("gscAuditPolicy", "STRUCTURAL",
[]string{"gscAuditPolicyName"},
[]string{"gscAuditPolicyScope", "gscAuditPolicyActions", "gscAuditPolicyStatus", "gscAuditRetentionDays", "gscAuditAlertEnabled", "gscAuditAlertRecipients", "gscDescription", "gscEnabled", "gscCreatedAt", "gscModifiedAt"},
"audit")
r.addObjectClass("gscConditionalAccessPolicy", "STRUCTURAL",
[]string{"gscIAMCAPolicyName"},
[]string{"gscIAMCAPolicyConditions", "gscIAMCAPolicyActions", "gscIAMCAPolicyStatus", "gscDescription", "gscEnabled", "gscCreatedAt", "gscModifiedAt"},
"iam")
r.addObjectClass("gscCollaborationPolicy", "STRUCTURAL",
[]string{"gscCollabPolicyName"},
[]string{"gscCollabPolicyScope", "gscCollabPolicyActions", "gscCollabPolicyStatus", "gscCollabMaxTeamSize", "gscCollabGuestAccessEnabled", "gscDescription", "gscEnabled", "gscCreatedAt", "gscModifiedAt"},
"collaboration")
r.addObjectClass("gscBarrierSegment", "STRUCTURAL",
[]string{"gscBarrierSegmentName"},
[]string{"gscBarrierSegmentMembers", "gscDescription", "gscEnabled", "gscCreatedAt", "gscModifiedAt"},
"barriers")
r.addObjectClass("gscBarrierPolicy", "STRUCTURAL",
[]string{"gscBarrierPolicyName"},
[]string{"gscBarrierPolicyType", "gscBarrierPolicySegments", "gscBarrierPolicyAction", "gscBarrierPolicyStatus", "gscDescription", "gscEnabled", "gscCreatedAt", "gscModifiedAt"},
"barriers")
r.addObjectClass("gscGuestPolicy", "STRUCTURAL",
[]string{"gscGuestPolicyName"},
[]string{"gscGuestPolicyScope", "gscGuestPolicyAction", "gscGuestPolicyStatus", "gscGuestMaxDuration", "gscDescription", "gscEnabled", "gscCreatedAt", "gscModifiedAt"},
"guest")
r.addObjectClass("gscFederatedIdp", "STRUCTURAL",
[]string{"gscGuestIdpName"},
[]string{"gscGuestIdpType", "gscGuestIdpEntityId", "gscGuestIdpMetadataURL", "gscGuestIdpDomains", "gscGuestIdpStatus", "gscDescription", "gscEnabled", "gscCreatedAt", "gscModifiedAt"},
"guest")
r.addObjectClass("gscManagedKey", "STRUCTURAL",
[]string{"gscKeyId", "gscKeyName", "gscKeyAlgorithm"},
[]string{"gscKeyLength", "gscKeyType", "gscKeyStatus", "gscKeyCreatedAt", "gscKeyExpiresAt", "gscKeyRotatedAt", "gscKeyOwnerDN", "gscKeyTenantDN", "gscKeyOperations", "gscKeyMaterial", "gscKeyPublicKey", "gscKeyFingerprint", "gscKeyVersion", "gscKeyPreviousVersionDN", "gscKeyHsmBacked", "gscKeyHsmSlot", "gscKeyAutoRotate", "gscKeyRotationDays"},
"managed-key")
r.addObjectClass("gscKmsPolicy", "STRUCTURAL",
[]string{"gscKmsPolicyId", "gscKmsPolicyName"},
[]string{"gscKmsPolicyType", "gscKmsPolicyEffect", "gscKmsPolicyPrincipalDN", "gscKmsPolicyResourceDN", "gscKmsPolicyOperations", "gscKmsPolicyConditions", "gscKmsPolicyPriority", "gscKmsPolicyStatus", "gscKmsPolicyCreatedAt", "gscKmsPolicyModifiedAt", "gscKmsPolicyTenantDN", "gscKmsPolicyMaxKeyAge", "gscKmsPolicyRequireHsm"},
"kms-policy")
r.addObjectClass("gscHsmConfig", "STRUCTURAL",
[]string{"gscHsmConfigId", "gscHsmConfigName"},
[]string{"gscHsmConfigType", "gscHsmConfigVendor", "gscHsmConfigModel", "gscHsmConfigConnectionString", "gscHsmConfigSlots", "gscHsmConfigStatus", "gscHsmConfigMaxKeys", "gscHsmConfigTenantDN"},
"hsm-config")
// ── AUXILIARY object objectClasses (6) ──────────────────────
r.addObjectClass("gscAuditObject", "AUXILIARY",
[]string{"gscAuditEnabled"},
[]string{"gscAuditLevel", "gscAuditPolicyName"},
"audit")
r.addObjectClass("gscMeetingRoom", "AUXILIARY",
[]string{"gscResourceId", "gscResourceType"},
[]string{"gscResourceCapacity", "gscResourceLocation", "gscResourceBookable"},
"resource")
r.addObjectClass("gscSharedMailbox", "AUXILIARY",
[]string{"gscMailEnabled"},
[]string{"gscMailQuota", "gscMailAlias", "gscMailDomain"},
"mail")
r.addObjectClass("gscEquipment", "AUXILIARY",
[]string{"gscResourceId", "gscResourceType"},
[]string{"gscResourceName", "gscResourceLocation", "gscResourceBookable"},
"resource")
r.addObjectClass("gscKmsTenant", "AUXILIARY",
[]string{"gscKmsTenantEnabled"},
[]string{"gscKmsTenantMaxKeys", "gscKmsTenantAllowedAlgorithms", "gscKmsTenantKeyRotationDays", "gscKmsTenantHsmEnabled", "gscKmsTenantHsmPartition", "gscKmsTenantAutoRotate", "gscKmsTenantKeyCount", "gscKmsTenantQuota", "gscKmsTenantDefaultAlgorithm", "gscKmsTenantDefaultKeyLength", "gscKmsTenantPolicyDN"},
"kms-tenant")
}

273
internal/schema/registry.go Normal file
View File

@@ -0,0 +1,273 @@
package schema
import (
"fmt"
"strconv"
"strings"
"time"
)
// Registry is the central schema registry for all GoSec LDAP attributes,
// objectClasses, and entity types.
type Registry struct {
attrs map[string]*AttrDef // ldapName → AttrDef
attrsByJSON map[string]*AttrDef // "domain:jsonName" → AttrDef
domainAttrs map[string][]*AttrDef // domain → list of attrs
objectClasses map[string]*ObjectClassDef // OC name → ObjectClassDef
domainOC map[string]string // domain → auxiliary user OC name
entityTypes map[string]*EntityTypeDef // entity name → EntityTypeDef
}
// NewRegistry creates and populates the schema registry
func NewRegistry() *Registry {
r := &Registry{
attrs: make(map[string]*AttrDef),
attrsByJSON: make(map[string]*AttrDef),
domainAttrs: make(map[string][]*AttrDef),
objectClasses: make(map[string]*ObjectClassDef),
domainOC: make(map[string]string),
entityTypes: make(map[string]*EntityTypeDef),
}
r.registerAttributes()
r.registerObjectClasses()
r.registerEntities()
return r
}
func (r *Registry) addAttr(ldapName, jsonName string, typ AttrType, domain string, readOnly bool) {
def := &AttrDef{
LDAPName: ldapName,
JSONName: jsonName,
Type: typ,
Domain: domain,
ReadOnly: readOnly,
}
r.attrs[ldapName] = def
r.attrsByJSON[domain+":"+jsonName] = def
r.domainAttrs[domain] = append(r.domainAttrs[domain], def)
}
func (r *Registry) addObjectClass(name, kind string, must, may []string, domain string) {
r.objectClasses[name] = &ObjectClassDef{
Name: name,
Kind: kind,
Must: must,
May: may,
Domain: domain,
}
// Map domain → auxiliary user objectClass (first AUXILIARY wins)
if kind == "AUXILIARY" {
if _, exists := r.domainOC[domain]; !exists {
r.domainOC[domain] = name
}
}
}
func (r *Registry) addEntityType(name, description string, objectClasses []string, baseDN, rdnAttr, searchFilter, domain string, requiredAttrs []string) {
r.entityTypes[name] = &EntityTypeDef{
Name: name,
Description: description,
ObjectClasses: objectClasses,
BaseDN: baseDN,
RDNAttribute: rdnAttr,
SearchFilter: searchFilter,
Domain: domain,
RequiredAttrs: requiredAttrs,
}
}
// GetAttr returns an attribute definition by LDAP name
func (r *Registry) GetAttr(ldapName string) *AttrDef {
return r.attrs[ldapName]
}
// GetAttrByJSON returns an attribute definition by domain and JSON name
func (r *Registry) GetAttrByJSON(domain, jsonName string) *AttrDef {
return r.attrsByJSON[domain+":"+jsonName]
}
// AttrsForDomain returns all attribute definitions for a domain
func (r *Registry) AttrsForDomain(domain string) []*AttrDef {
return r.domainAttrs[domain]
}
// AllDomains returns all registered domain names
func (r *Registry) AllDomains() []string {
domains := make([]string, 0, len(r.domainAttrs))
for d := range r.domainAttrs {
domains = append(domains, d)
}
return domains
}
// AllUserAttrs returns all gsc* LDAP attribute names for user search
func (r *Registry) AllUserAttrs() []string {
attrs := make([]string, 0, len(r.attrs))
for name := range r.attrs {
attrs = append(attrs, name)
}
return attrs
}
// UserOCForDomain returns the auxiliary objectClass name for a user service domain
func (r *Registry) UserOCForDomain(domain string) string {
return r.domainOC[domain]
}
// RequiredOCsForAttrs determines which objectClasses are needed for a set of LDAP attributes
func (r *Registry) RequiredOCsForAttrs(ldapAttrNames []string) []string {
needed := make(map[string]bool)
attrSet := make(map[string]bool, len(ldapAttrNames))
for _, a := range ldapAttrNames {
attrSet[a] = true
}
for _, oc := range r.objectClasses {
if oc.Kind != "AUXILIARY" {
continue
}
for _, must := range oc.Must {
if attrSet[must] {
needed[oc.Name] = true
break
}
}
if needed[oc.Name] {
continue
}
for _, may := range oc.May {
if attrSet[may] {
needed[oc.Name] = true
break
}
}
}
result := make([]string, 0, len(needed))
for name := range needed {
result = append(result, name)
}
return result
}
// GetObjectClass returns an objectClass definition by name
func (r *Registry) GetObjectClass(name string) *ObjectClassDef {
return r.objectClasses[name]
}
// LDAPValueToGo converts LDAP string values to Go typed values based on attribute type
func (r *Registry) LDAPValueToGo(attr *AttrDef, values []string) interface{} {
if len(values) == 0 {
return nil
}
switch attr.Type {
case AttrString, AttrDN:
return values[0]
case AttrStringMulti, AttrDNMulti:
return values
case AttrInt:
if v, err := strconv.Atoi(values[0]); err == nil {
return v
}
return values[0]
case AttrBool:
return strings.EqualFold(values[0], "TRUE")
case AttrTime:
// GeneralizedTime format: 20060102150405Z
if t, err := time.Parse("20060102150405Z", values[0]); err == nil {
return t.Format(time.RFC3339)
}
return values[0]
default:
return values[0]
}
}
// GoValueToLDAP converts a Go value to LDAP string(s) based on attribute type
func (r *Registry) GoValueToLDAP(attr *AttrDef, value interface{}) ([]string, error) {
if value == nil {
return nil, nil
}
switch attr.Type {
case AttrString, AttrDN:
s, ok := value.(string)
if !ok {
return nil, fmt.Errorf("attribute %s expects string, got %T", attr.LDAPName, value)
}
return []string{s}, nil
case AttrStringMulti, AttrDNMulti:
switch v := value.(type) {
case []string:
return v, nil
case []interface{}:
result := make([]string, 0, len(v))
for _, item := range v {
s, ok := item.(string)
if !ok {
return nil, fmt.Errorf("attribute %s expects string array, got %T in array", attr.LDAPName, item)
}
result = append(result, s)
}
return result, nil
default:
return nil, fmt.Errorf("attribute %s expects string array, got %T", attr.LDAPName, value)
}
case AttrInt:
switch v := value.(type) {
case float64:
return []string{strconv.Itoa(int(v))}, nil
case int:
return []string{strconv.Itoa(v)}, nil
case string:
return []string{v}, nil
default:
return nil, fmt.Errorf("attribute %s expects int, got %T", attr.LDAPName, value)
}
case AttrBool:
switch v := value.(type) {
case bool:
if v {
return []string{"TRUE"}, nil
}
return []string{"FALSE"}, nil
case string:
return []string{strings.ToUpper(v)}, nil
default:
return nil, fmt.Errorf("attribute %s expects bool, got %T", attr.LDAPName, value)
}
case AttrTime:
s, ok := value.(string)
if !ok {
return nil, fmt.Errorf("attribute %s expects time string, got %T", attr.LDAPName, value)
}
// Accept RFC3339 and convert to GeneralizedTime
if t, err := time.Parse(time.RFC3339, s); err == nil {
return []string{t.UTC().Format("20060102150405Z")}, nil
}
// Already GeneralizedTime format
return []string{s}, nil
default:
s, ok := value.(string)
if !ok {
return nil, fmt.Errorf("attribute %s: unsupported type %T", attr.LDAPName, value)
}
return []string{s}, nil
}
}
// GetEntityType returns an entity type definition by name
func (r *Registry) GetEntityType(name string) *EntityTypeDef {
return r.entityTypes[name]
}
// AllEntityTypes returns all registered entity type definitions
func (r *Registry) AllEntityTypes() map[string]*EntityTypeDef {
return r.entityTypes
}

44
internal/schema/types.go Normal file
View File

@@ -0,0 +1,44 @@
package schema
// AttrType represents the LDAP attribute value type
type AttrType int
const (
AttrString AttrType = iota // Single-value string
AttrStringMulti // Multi-value string
AttrInt // Integer (stored as string in LDAP)
AttrBool // Boolean (TRUE/FALSE in LDAP)
AttrDN // DN single
AttrDNMulti // DN multi
AttrTime // GeneralizedTime
)
// AttrDef defines an LDAP attribute with its JSON mapping and type info
type AttrDef struct {
LDAPName string // LDAP attribute name (e.g. "gscMailEnabled")
JSONName string // JSON field name (e.g. "enabled")
Type AttrType // Value type for conversion
Domain string // Service domain (e.g. "mail", "calendar")
ReadOnly bool // If true, not settable via API
}
// ObjectClassDef defines an LDAP objectClass
type ObjectClassDef struct {
Name string // ObjectClass name (e.g. "gscMailUser")
Kind string // "AUXILIARY" or "STRUCTURAL"
Must []string // Required LDAP attributes
May []string // Optional LDAP attributes
Domain string // Service domain this OC belongs to
}
// EntityTypeDef defines a standalone LDAP entity type for CRUD operations
type EntityTypeDef struct {
Name string // URL-safe name (e.g. "tenant", "dlp-policy")
Description string // Human-readable description
ObjectClasses []string // Required objectClasses
BaseDN string // Relative base DN (appended to LDAP base)
RDNAttribute string // Attribute used as RDN (e.g. "cn", "gscTenantId")
SearchFilter string // LDAP search filter for listing
Domain string // Logical domain grouping
RequiredAttrs []string // Attributes required on create
}