{"record":{"id":"e38b4a266bbb6ed7","repo":"thanos-io/thanos","slug":"could-not-get-organizationalunit-field-from-client","errorCode":null,"errorMessage":"could not get organizationalUnit field from client cert","messagePattern":"could not get organizationalUnit field from client cert","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/tenancy/tenancy.go","lineNumber":118,"sourceCode":"\n\tif len(r.TLS.PeerCertificates) == 0 {\n\t\treturn \"\", errors.New(\"could not get required certificate field from client cert\")\n\t}\n\n\t// First cert is the leaf authenticated against.\n\tcert := r.TLS.PeerCertificates[0]\n\n\tswitch certTenantField {\n\n\tcase CertificateFieldOrganization:\n\t\tif len(cert.Subject.Organization) == 0 {\n\t\t\treturn \"\", errors.New(\"could not get organization field from client cert\")\n\t\t}\n\t\ttenant = cert.Subject.Organization[0]\n\n\tcase CertificateFieldOrganizationalUnit:\n\t\tif len(cert.Subject.OrganizationalUnit) == 0 {\n\t\t\treturn \"\", errors.New(\"could not get organizationalUnit field from client cert\")\n\t\t}\n\t\ttenant = cert.Subject.OrganizationalUnit[0]\n\n\tcase CertificateFieldCommonName:\n\t\tif cert.Subject.CommonName == \"\" {\n\t\t\treturn \"\", errors.New(\"could not get commonName field from client cert\")\n\t\t}\n\t\ttenant = cert.Subject.CommonName\n\n\tdefault:\n\t\treturn \"\", errors.New(\"tls client cert field requested is not supported\")\n\t}\n\n\treturn tenant, nil\n}\n\nfunc GetTenantFromGRPCMetadata(ctx context.Context) (string, bool) {\n\tmd, ok := metadata.FromIncomingContext(ctx)","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/thanos-io/thanos/blob/35b8b991177def87ed52dcf10f9b6d87f07282c8/pkg/tenancy/tenancy.go#L100-L136","documentation":"Thrown by getTenantFromCertificate when tenancy is configured to use the certificate's OrganizationalUnit (OU) field as the tenant identifier, but the client certificate presented has no OrganizationalUnit entries. Tenancy cannot be determined so the request fails.","triggerScenarios":"GetTenantFromHTTP with certTenantField=CertificateFieldOrganizationalUnit against a client cert whose Subject.OrganizationalUnit slice is empty.","commonSituations":"Server started with --tenant-certificate-field=organizationalUnit but clients use certs with only CN/O populated; certs rotated to a new CA template that dropped the OU field; misconfiguration of the tenant field flag in multi-tenant deployments.","solutions":["Add an OrganizationalUnit to the client cert Subject and reissue it (e.g. -subj '/O=corp/OU=tenant-a/CN=client')","Or change the server flag to a field present in the cert: --tenant-certificate-field=organization or common-name","Inspect the client cert subject with 'openssl x509 -noout -subject' to see available fields","Document the required cert subject layout so all tenants issue compliant certs"],"exampleFix":"// before\n-subj '/CN=client'\n// after\n-subj '/OU=tenant-a/CN=client'","handlingStrategy":"validation","validationCode":"// Go, before issuing/connecting\nif len(cert.Subject.OrganizationalUnit) == 0 {\n    return errors.New(\"client cert must have OrganizationalUnit set for tenancy\")\n}","typeGuard":"func certHasOU(cert *x509.Certificate) bool {\n    return cert != nil && len(cert.Subject.OrganizationalUnit) > 0\n}","tryCatchPattern":null,"preventionTips":["Include OU in every client cert subject template","Verify cert contents after each CA/template change","Choose the tenant field once and enforce it org-wide"],"tags":["tls","tenancy","certificate","mtls"],"backgroundTag":"empty-required-field","analyzedSha":"35b8b991177def87ed52dcf10f9b6d87f07282c8","analyzedAt":"2026-09-07T01:49:59.689Z","contentChangedAt":"2026-09-07T01:49:59.689Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}