feat(identity): 接入认证中心多租户登录
支持 Manifest V2 动态 tid 验证、Tenant Context 同步和租户内 JIT 投影,并保留 Manifest V1 与旧 Session 兼容。\n\n增加 tenantHint、租户切换、普通注册关闭及 application/principal/tenant 两级 SSF 撤销;迁移、定向安全测试和本地双租户跨仓 E2E 已通过。\n\nrelease_required=true;未执行 Release、Staging 或真实链路。
This commit is contained in:
@@ -50,6 +50,8 @@ type ConnectionManagerConfig struct {
|
||||
OIDCEnabled bool
|
||||
OIDCIssuer string
|
||||
OIDCTenantID string
|
||||
OIDCApplicationID string
|
||||
OIDCTenantMode string
|
||||
ManagementClientID string
|
||||
ManagementClientSecret string
|
||||
ExpectedTransmitterIssuer string
|
||||
@@ -145,7 +147,9 @@ func (err safeConnectionError) Unwrap() error { return err.cause }
|
||||
func (err safeConnectionError) SafeErrorCategory() string { return err.category }
|
||||
|
||||
func NewConnectionManager(ctx context.Context, repository ConnectionRepository, secrets SecretStore, config ConnectionManagerConfig, metrics *Metrics) (*ConnectionManager, error) {
|
||||
if repository == nil || secrets == nil || !config.OIDCEnabled || config.OIDCIssuer == "" || config.OIDCTenantID == "" {
|
||||
validIdentityBinding := config.OIDCTenantMode == "multi_tenant" && uuid.Validate(config.OIDCApplicationID) == nil ||
|
||||
config.OIDCTenantMode != "multi_tenant" && uuid.Validate(config.OIDCTenantID) == nil
|
||||
if repository == nil || secrets == nil || !config.OIDCEnabled || config.OIDCIssuer == "" || !validIdentityBinding {
|
||||
return nil, errors.New("security event connection prerequisites are incomplete")
|
||||
}
|
||||
if config.HeartbeatInterval <= 0 {
|
||||
@@ -773,7 +777,8 @@ func (m *ConnectionManager) Evaluate(ctx context.Context, identity auth.OIDCSecu
|
||||
return auth.OIDCSecurityEventEvaluation{Enabled: true, RequireIntrospection: true}, nil
|
||||
}
|
||||
result, evaluateErr := m.repository.EvaluateOIDCSecurityEvent(
|
||||
ctx, connection.TransmitterIssuer, *connection.Audience, identity.Issuer, identity.TenantID, identity.Subject,
|
||||
ctx, connection.TransmitterIssuer, *connection.Audience, identity.Issuer, identity.ApplicationID,
|
||||
identity.TenantID, identity.Subject,
|
||||
identity.IssuedAt, time.Now().UTC(), m.config.StaleAfter,
|
||||
)
|
||||
if result.Revoked && m.metrics != nil {
|
||||
@@ -821,7 +826,9 @@ func (m *ConnectionManager) activate(ctx context.Context, connection store.Secur
|
||||
}
|
||||
verifier, err := NewVerifier(VerifierConfig{
|
||||
TransmitterIssuer: connection.TransmitterIssuer, Audience: *connection.Audience,
|
||||
SubjectIssuer: m.config.OIDCIssuer, TenantID: m.config.OIDCTenantID, StreamID: *connection.StreamID,
|
||||
SubjectIssuer: m.config.OIDCIssuer, TenantID: m.config.OIDCTenantID,
|
||||
ApplicationID: m.config.OIDCApplicationID, TenantMode: m.config.OIDCTenantMode,
|
||||
StreamID: *connection.StreamID,
|
||||
ClockSkew: m.config.ClockSkew, HTTPClient: safeClient,
|
||||
})
|
||||
if err != nil {
|
||||
@@ -1038,7 +1045,11 @@ func (m *ConnectionManager) validatePrerequisites(issuer, managementClientID str
|
||||
if !m.config.OIDCEnabled || strings.TrimSpace(managementClientID) == "" || len(managementSecret) < 16 {
|
||||
return errors.New("OIDC and RFC 7662 machine client must be configured")
|
||||
}
|
||||
if _, err := uuid.Parse(m.config.OIDCTenantID); err != nil {
|
||||
if m.config.OIDCTenantMode == "multi_tenant" {
|
||||
if uuid.Validate(m.config.OIDCApplicationID) != nil {
|
||||
return errors.New("OIDC application id is invalid")
|
||||
}
|
||||
} else if uuid.Validate(m.config.OIDCTenantID) != nil {
|
||||
return errors.New("OIDC tenant id is invalid")
|
||||
}
|
||||
if _, err := validatedIssuerURL(issuer, m.config.AppEnv); err != nil {
|
||||
|
||||
Reference in New Issue
Block a user