Skip to content

Commit

Permalink
Harden backwards compatibility for entitlements
Browse files Browse the repository at this point in the history
  • Loading branch information
michellescripts committed Jul 30, 2024
1 parent 736e497 commit 3536b9b
Show file tree
Hide file tree
Showing 2 changed files with 605 additions and 54 deletions.
102 changes: 82 additions & 20 deletions lib/web/apiserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -1665,36 +1665,20 @@ func (h *Handler) getWebConfig(w http.ResponseWriter, r *http.Request, p httprou
RecoveryCodesEnabled: clusterFeatures.GetRecoveryCodes(),
UI: h.getUIConfig(r.Context()),
IsDashboard: services.IsDashboard(clusterFeatures),
IsTeam: false,
IsUsageBasedBilling: clusterFeatures.GetIsUsageBased(),
AutomaticUpgrades: automaticUpgradesEnabled,
AutomaticUpgradesTargetVersion: automaticUpgradesTargetVersion,
CustomTheme: clusterFeatures.GetCustomTheme(),
Questionnaire: clusterFeatures.GetQuestionnaire(),
IsStripeManaged: clusterFeatures.GetIsStripeManaged(),
PremiumSupport: clusterFeatures.GetSupportType() == proto.SupportType_SUPPORT_TYPE_PREMIUM,
Entitlements: GetWebCfgEntitlements(clusterFeatures.GetEntitlements()),
PlayableDatabaseProtocols: player.SupportedDatabaseProtocols,

// Set legacy fields
// TODO(mcbattirola): remove isTeam when it is no longer used
IsTeam: clusterFeatures.GetProductType() == proto.ProductType_PRODUCT_TYPE_TEAM,
AccessRequests: modules.GetProtoEntitlement(&clusterFeatures, entitlements.AccessRequests).Enabled,
ExternalAuditStorage: modules.GetProtoEntitlement(&clusterFeatures, entitlements.ExternalAuditStorage).Enabled,
HideInaccessibleFeatures: modules.GetProtoEntitlement(&clusterFeatures, entitlements.FeatureHiding).Enabled,
IsIGSEnabled: modules.GetProtoEntitlement(&clusterFeatures, entitlements.Identity).Enabled,
IsPolicyEnabled: modules.GetProtoEntitlement(&clusterFeatures, entitlements.Policy).Enabled,
JoinActiveSessions: modules.GetProtoEntitlement(&clusterFeatures, entitlements.JoinActiveSessions).Enabled,
MobileDeviceManagement: modules.GetProtoEntitlement(&clusterFeatures, entitlements.MobileDeviceManagement).Enabled,
OIDC: modules.GetProtoEntitlement(&clusterFeatures, entitlements.OIDC).Enabled,
SAML: modules.GetProtoEntitlement(&clusterFeatures, entitlements.SAML).Enabled,
TrustedDevices: modules.GetProtoEntitlement(&clusterFeatures, entitlements.DeviceTrust).Enabled,
FeatureLimits: webclient.FeatureLimits{
AccessListCreateLimit: int(modules.GetProtoEntitlement(&clusterFeatures, entitlements.AccessLists).Limit),
AccessMonitoringMaxReportRangeLimit: int(modules.GetProtoEntitlement(&clusterFeatures, entitlements.AccessMonitoring).Limit),
AccessRequestMonthlyRequestLimit: int(modules.GetProtoEntitlement(&clusterFeatures, entitlements.AccessRequests).Limit),
},
}

// Set entitlements with backwards field compatibility
setEntitlementsWithLegacyLogic(&webCfg, clusterFeatures)

resource, err := h.cfg.ProxyClient.GetClusterName()
if err != nil {
h.log.WithError(err).Warn("Failed to query cluster name.")
Expand All @@ -1711,6 +1695,84 @@ func (h *Handler) getWebConfig(w http.ResponseWriter, r *http.Request, p httprou
return nil, nil
}

// setEntitlementsWithLegacyLogic ensures entitlements on webCfg are backwards compatible
// If Entitlements are present, will set the legacy fields equal to the equivalent entitlement value
// i.e. webCfg.IsIGSEnabled = clusterFeatures.Entitlements[entitlements.Identity].Enabled
// && webCfg.Entitlements[entitlements.Identity] = clusterFeatures.Entitlements[entitlements.Identity].Enabled
// If Entitlements are not present, will set the legacy fields AND the entitlement equal to the legacy feature
// i.e. webCfg.IsIGSEnabled = clusterFeatures.GetIdentityGovernance()
// && webCfg.Entitlements[entitlements.Identity] = clusterFeatures.GetIdentityGovernance()
// todo (michellescripts) remove in v18; & inline entitlement logic above
func setEntitlementsWithLegacyLogic(webCfg *webclient.WebConfig, clusterFeatures proto.Features) {
// if Entitlements are not present, GetWebCfgEntitlements will return a map of entitlement to {enabled:false}
// if Entitlements are present, GetWebCfgEntitlements will populate the fields appropriately
webCfg.Entitlements = GetWebCfgEntitlements(clusterFeatures.GetEntitlements())

if clusterFeatures.GetEntitlements() != nil && len(clusterFeatures.GetEntitlements()) > 0 {
// webCfg.Entitlements: No update as they are set above
// webCfg.<legacy fields>: set equal to entitlement value
webCfg.AccessRequests = modules.GetProtoEntitlement(&clusterFeatures, entitlements.AccessRequests).Enabled
webCfg.ExternalAuditStorage = modules.GetProtoEntitlement(&clusterFeatures, entitlements.ExternalAuditStorage).Enabled
webCfg.HideInaccessibleFeatures = modules.GetProtoEntitlement(&clusterFeatures, entitlements.FeatureHiding).Enabled
webCfg.IsIGSEnabled = modules.GetProtoEntitlement(&clusterFeatures, entitlements.Identity).Enabled
webCfg.IsPolicyEnabled = modules.GetProtoEntitlement(&clusterFeatures, entitlements.Policy).Enabled
webCfg.JoinActiveSessions = modules.GetProtoEntitlement(&clusterFeatures, entitlements.JoinActiveSessions).Enabled
webCfg.MobileDeviceManagement = modules.GetProtoEntitlement(&clusterFeatures, entitlements.MobileDeviceManagement).Enabled
webCfg.OIDC = modules.GetProtoEntitlement(&clusterFeatures, entitlements.OIDC).Enabled
webCfg.SAML = modules.GetProtoEntitlement(&clusterFeatures, entitlements.SAML).Enabled
webCfg.TrustedDevices = modules.GetProtoEntitlement(&clusterFeatures, entitlements.DeviceTrust).Enabled
webCfg.FeatureLimits = webclient.FeatureLimits{
AccessListCreateLimit: int(modules.GetProtoEntitlement(&clusterFeatures, entitlements.AccessLists).Limit),
AccessMonitoringMaxReportRangeLimit: int(modules.GetProtoEntitlement(&clusterFeatures, entitlements.AccessMonitoring).Limit),
AccessRequestMonthlyRequestLimit: int(modules.GetProtoEntitlement(&clusterFeatures, entitlements.AccessRequests).Limit),
}

} else {
// webCfg.Entitlements: All records are {enabled: false}; update to equal legacy feature value
webCfg.Entitlements[string(entitlements.ExternalAuditStorage)] = webclient.EntitlementInfo{Enabled: clusterFeatures.GetExternalAuditStorage()}
webCfg.Entitlements[string(entitlements.FeatureHiding)] = webclient.EntitlementInfo{Enabled: clusterFeatures.GetFeatureHiding()}
webCfg.Entitlements[string(entitlements.Identity)] = webclient.EntitlementInfo{Enabled: clusterFeatures.GetIdentityGovernance()}
webCfg.Entitlements[string(entitlements.JoinActiveSessions)] = webclient.EntitlementInfo{Enabled: clusterFeatures.GetJoinActiveSessions()}
webCfg.Entitlements[string(entitlements.MobileDeviceManagement)] = webclient.EntitlementInfo{Enabled: clusterFeatures.GetMobileDeviceManagement()}
webCfg.Entitlements[string(entitlements.OIDC)] = webclient.EntitlementInfo{Enabled: clusterFeatures.GetOIDC()}
webCfg.Entitlements[string(entitlements.Policy)] = webclient.EntitlementInfo{Enabled: clusterFeatures.GetPolicy() != nil && clusterFeatures.GetPolicy().Enabled}
webCfg.Entitlements[string(entitlements.SAML)] = webclient.EntitlementInfo{Enabled: clusterFeatures.GetSAML()}

// set default Identity fields to legacy feature value
webCfg.Entitlements[string(entitlements.AccessLists)] = webclient.EntitlementInfo{Enabled: true, Limit: clusterFeatures.GetAccessList().GetCreateLimit()}
webCfg.Entitlements[string(entitlements.AccessMonitoring)] = webclient.EntitlementInfo{Enabled: clusterFeatures.GetAccessMonitoring().GetEnabled(), Limit: clusterFeatures.GetAccessMonitoring().GetMaxReportRangeLimit()}
webCfg.Entitlements[string(entitlements.AccessRequests)] = webclient.EntitlementInfo{Enabled: clusterFeatures.GetAccessRequests().MonthlyRequestLimit > 0, Limit: clusterFeatures.GetAccessRequests().GetMonthlyRequestLimit()}
webCfg.Entitlements[string(entitlements.DeviceTrust)] = webclient.EntitlementInfo{Enabled: clusterFeatures.GetDeviceTrust().GetEnabled(), Limit: clusterFeatures.GetDeviceTrust().GetDevicesUsageLimit()}
// override Identity Package features if Identity is enabled: set true and clear limit
if clusterFeatures.GetIdentityGovernance() {
webCfg.Entitlements[string(entitlements.AccessLists)] = webclient.EntitlementInfo{Enabled: true}
webCfg.Entitlements[string(entitlements.AccessMonitoring)] = webclient.EntitlementInfo{Enabled: true}
webCfg.Entitlements[string(entitlements.AccessRequests)] = webclient.EntitlementInfo{Enabled: true}
webCfg.Entitlements[string(entitlements.DeviceTrust)] = webclient.EntitlementInfo{Enabled: true}
webCfg.Entitlements[string(entitlements.OktaSCIM)] = webclient.EntitlementInfo{Enabled: true}
webCfg.Entitlements[string(entitlements.OktaUserSync)] = webclient.EntitlementInfo{Enabled: true}
webCfg.Entitlements[string(entitlements.SessionLocks)] = webclient.EntitlementInfo{Enabled: true}
}

// webCfg.<legacy fields>: set equal to legacy feature value
webCfg.AccessRequests = clusterFeatures.GetAccessRequests().MonthlyRequestLimit > 0
webCfg.ExternalAuditStorage = clusterFeatures.GetExternalAuditStorage()
webCfg.HideInaccessibleFeatures = clusterFeatures.GetFeatureHiding()
webCfg.IsIGSEnabled = clusterFeatures.GetIdentityGovernance()
webCfg.IsPolicyEnabled = clusterFeatures.GetPolicy() != nil && clusterFeatures.GetPolicy().Enabled
webCfg.JoinActiveSessions = clusterFeatures.GetJoinActiveSessions()
webCfg.MobileDeviceManagement = clusterFeatures.GetMobileDeviceManagement()
webCfg.OIDC = clusterFeatures.GetOIDC()
webCfg.SAML = clusterFeatures.GetSAML()
webCfg.TrustedDevices = clusterFeatures.GetDeviceTrust().GetEnabled()
webCfg.FeatureLimits = webclient.FeatureLimits{
AccessListCreateLimit: int(clusterFeatures.GetAccessList().GetCreateLimit()),
AccessMonitoringMaxReportRangeLimit: int(clusterFeatures.GetAccessMonitoring().GetMaxReportRangeLimit()),
AccessRequestMonthlyRequestLimit: int(clusterFeatures.GetAccessRequests().GetMonthlyRequestLimit()),
}
}
}

// GetWebCfgEntitlements takes a cloud entitlement set and returns a modules Entitlement set
func GetWebCfgEntitlements(protoEntitlements map[string]*proto.EntitlementInfo) map[string]webclient.EntitlementInfo {
all := entitlements.AllEntitlements
Expand Down
Loading

0 comments on commit 3536b9b

Please sign in to comment.