Remove deprecated features and entitlement backfills (#59618)

This commit is contained in:
Michelle Bergquist
2026-03-02 19:08:42 +00:00
committed by GitHub
parent 1e55d0a493
commit 534c011ae0
13 changed files with 1077 additions and 3173 deletions
File diff suppressed because it is too large Load Diff
+1 -57
View File
@@ -87,54 +87,13 @@ type WebConfig struct {
SessionSummarizerEnabled bool `json:"sessionSummarizerEnabled,omitempty"`
// entitlements define a customers access to a specific features
Entitlements map[string]EntitlementInfo `json:"entitlements,omitempty"`
// Deprecated Fields
// Deprecated: IsTeam is true if [Features.ProductType] = Team
// Prefer checking the cluster features over this flag, as this will be removed.
IsTeam bool `json:"isTeam"`
// HideInaccessibleFeatures is true when features should be undiscoverable to users without the necessary permissions.
// Usually, in order to encourage discoverability of features, we show UI elements even if the user doesn't have permission to access them,
// this flag disables that behavior.
// Deprecated, use entitlements
HideInaccessibleFeatures bool `json:"hideInaccessibleFeatures"`
// IsIGSEnabled is true if [Features.IdentityGovernance] = true
// Deprecated, use entitlements
IsIGSEnabled bool `json:"isIgsEnabled"`
// IsPolicyEnabled is true if [Features.Policy] = true
// Deprecated, use entitlements
IsPolicyEnabled bool `json:"isPolicyEnabled"`
// TODO (avatus) delete in v18
// IsPolicyRoleVisualizerEnabled is the graph visualizer for diffs made
// when editing roles in the Web UI. This defaults to true, but has an environment
// variable to turn off if needed TELEPORT_UNSTABLE_DISABLE_ROLE_VISUALIZER=true
IsPolicyRoleVisualizerEnabled bool `json:"isPolicyRoleVisualizerEnabled"`
// featureLimits define limits for features.
// Typically used with feature teasers if feature is not enabled for the
// product type eg: Team product contains teasers to upgrade to Enterprise.
// Deprecated, use entitlements
FeatureLimits FeatureLimits `json:"featureLimits"`
// ExternalAuditStorage indicates whether the EAS feature is enabled in the cluster.
// Deprecated, use entitlements
ExternalAuditStorage bool `json:"externalAuditStorage"`
// JoinActiveSessions indicates whether joining active sessions via web UI is enabled
// Deprecated, use entitlements
JoinActiveSessions bool `json:"joinActiveSessions"`
// AccessRequests indicates whether access requests are enabled
// Deprecated, use entitlements
AccessRequests bool `json:"accessRequests"`
// TrustedDevices indicates whether trusted devices page is enabled
// Deprecated, use entitlements
TrustedDevices bool `json:"trustedDevices"`
// OIDC indicates whether the OIDC integration flow is enabled
// Deprecated, use entitlements
OIDC bool `json:"oidc"`
// SAML indicates whether the SAML integration flow is enabled
// Deprecated, use entitlements
SAML bool `json:"saml"`
// MobileDeviceManagement indicates whether adding Jamf plugin is enabled
// Deprecated, use entitlements
MobileDeviceManagement bool `json:"mobileDeviceManagement"`
// IdentitySecurity contains identity security features and settings.
// The individual identity security entitlements should be read from the Entitlements field.
IdentitySecurity IdentitySecurity `json:"identitySecurity"`
}
@@ -161,21 +120,6 @@ type EntitlementInfo struct {
Limit int32 `json:"limit"`
}
// featureLimits define limits for features.
// Typically used with feature teasers if feature is not enabled for the
// product type eg: Team product contains teasers to upgrade to Enterprise.
type FeatureLimits struct {
// Limit for the number of access list creatable when feature is
// not enabled.
AccessListCreateLimit int `json:"accessListCreateLimit"`
// Defines the max number of days to include in an access report if
// feature is not enabled.
AccessMonitoringMaxReportRangeLimit int `json:"accessMonitoringMaxReportRangeLimit"`
// AccessRequestMonthlyRequestLimit is the usage-based limit for the number of
// access requests created in a calendar month.
AccessRequestMonthlyRequestLimit int `json:"AccessRequestMonthlyRequestLimit"`
}
// UIConfig provides config options for the web UI served by the proxy service.
type UIConfig struct {
// ScrollbackLines is the max number of lines the UI terminal can display in its history
@@ -541,33 +541,16 @@ enum SupportType {
// Features are auth server features.
message Features {
// Kubernetes enables Kubernetes Access product
// Deprecated remove in v18; leverage entitlements
bool Kubernetes = 1 [(gogoproto.jsontag) = "kubernetes"];
// App enables Application Access product
// Deprecated remove in v18; leverage entitlements
bool App = 2 [(gogoproto.jsontag) = "app"];
// DB enables database access product
// Deprecated remove in v18; leverage entitlements
bool DB = 3 [(gogoproto.jsontag) = "db"];
// OIDC enables OIDC connectors
// Deprecated remove in v18; leverage entitlements
bool OIDC = 4 [(gogoproto.jsontag) = "oidc"];
// SAML enables SAML connectors
// Deprecated remove in v18; leverage entitlements
bool SAML = 5 [(gogoproto.jsontag) = "saml"];
// Deprecated features, use entitlements
reserved 1, 2, 3, 4, 5, 9, 10, 18, 19, 20, 21, 23, 25, 26, 31, 33, 34;
reserved "Kubernetes", "App", "DB", "OIDC", "SAML", "HSM", "Desktop", "Assist", "DeviceTrust", "FeatureHiding", "AccessRequests", "IdentityGovernance", "AccessList", "AccessMonitoring", "ExternalAuditStorage", "JoinActiveSessions", "MobileDeviceManagement";
// AccessControls enables FIPS access controls
bool AccessControls = 6 [(gogoproto.jsontag) = "access_controls"];
// AdvancedAccessWorkflows is currently set to the value of the Cloud AccessRequests entitlement
bool AdvancedAccessWorkflows = 7 [(gogoproto.jsontag) = "advanced_access_workflows"];
// Cloud enables some cloud-related features
bool Cloud = 8 [(gogoproto.jsontag) = "cloud"];
// HSM enables PKCS#11 HSM support
// Deprecated remove in v18; leverage entitlements
bool HSM = 9 [(gogoproto.jsontag) = "hsm"];
// Desktop enables desktop access product
// Deprecated remove in v18; leverage entitlements
bool Desktop = 10 [(gogoproto.jsontag) = "desktop"];
reserved 11; // bool ModeratedSessions
reserved 12; // bool MachineID
reserved 13; // bool ResourceAccessRequests
@@ -579,57 +562,27 @@ message Features {
bool AutomaticUpgrades = 16 [(gogoproto.jsontag) = "automatic_upgrades"];
// IsUsageBased enables some usage-based billing features
bool IsUsageBased = 17 [(gogoproto.jsontag) = "is_usage_based"];
// Assist enables the Assistant feature
// Deprecated remove in v18; leverage entitlements
bool Assist = 18 [(gogoproto.jsontag) = "assist"];
// DeviceTrust holds its namesake feature settings.
// Deprecated remove in v18; leverage entitlements
DeviceTrustFeature DeviceTrust = 19 [(gogoproto.jsontag) = "device_trust,omitempty"];
// FeatureHiding enables hiding features from being discoverable for users who don't have the necessary permissions.
// Deprecated remove in v18; leverage entitlements
bool FeatureHiding = 20 [(gogoproto.jsontag) = "feature_hiding,omitempty"];
// AccessRequests holds its namesake feature settings.
// Deprecated remove in v18; leverage entitlements
AccessRequestsFeature AccessRequests = 21 [(gogoproto.jsontag) = "access_requests,omitempty"];
// CustomTheme holds the name of WebUI custom theme.
string CustomTheme = 22 [(gogoproto.jsontag) = "custom_theme,omitempty"];
// IdentityGovernance indicates whether IGS related features are enabled:
// access list, access request, access monitoring, device trust.
// Deprecated remove in v18; leverage entitlements
bool IdentityGovernance = 23 [(gogoproto.jsontag) = "identity_governance,omitempty"];
// AccessGraph enables the usage of access graph.
// NOTE: this is a legacy flag that is currently used to signal
// that Access Graph integration is *enabled* on a cluster.
// *Access* to the feature is gated on the `Policy` flag.
// *Access* to the feature is gated on the `Policy` entitlement.
// TODO(justinas): remove this field once "TAG enabled" status is moved to a resource in the backend.
bool AccessGraph = 24 [(gogoproto.jsontag) = "access_graph,omitempty"];
// AccessListFeature holds its namesake feature settings.
// Deprecated remove in v18; leverage entitlements
AccessListFeature AccessList = 25 [(gogoproto.jsontag) = "access_list,omitempty"];
// AccessMonitoringFeature holds its namesake feature settings.
// Deprecated remove in v18; leverage entitlements for access and AccessMonitoringConfigured for enabled
AccessMonitoringFeature AccessMonitoring = 26 [(gogoproto.jsontag) = "access_monitoring,omitempty"];
// ProductType describes the product being used.
ProductType ProductType = 27 [(gogoproto.jsontag) = "product_type,omitempty"];
// Policy enables the Teleport Policy feature set.
// At the time of writing, this includes Teleport Access Graph (TAG).
// Deprecated remove in v18; leverage entitlements
// TODO(michellescripts) DELETE IN v21.0.0
// Deprecated, use entitlements
PolicyFeature Policy = 28 [(gogoproto.jsontag) = "policy,omitempty"];
// Questionnaire indicates whether cluster users should get an onboarding questionnaire
bool Questionnaire = 29 [(gogoproto.jsontag) = "questionnaire,omitempty"];
// IsStripeManaged indicates if the cluster billing is managed via Stripe
bool IsStripeManaged = 30 [(gogoproto.jsontag) = "is_stripe_managed,omitempty"];
// ExternalAuditStorage indicates whether the EAS feature is enabled in the cluster.
// Deprecated remove in v18; leverage entitlements
bool ExternalAuditStorage = 31 [(gogoproto.jsontag) = "external_audit_storage,omitempty"];
// SupportType indicates the type of the customer's support
SupportType SupportType = 32 [(gogoproto.jsontag) = "support_type,omitempty"];
// JoinActiveSessions indicates whether joining active sessions via web UI is enabled
// Deprecated remove in v18; leverage entitlements
bool JoinActiveSessions = 33 [(gogoproto.jsontag) = "join_active_sessions,omitempty"];
// MobileDeviceManagement indicates whether endpoint management (like Jamf Plugin) can be used in the cluster
// Deprecated remove in v18; leverage entitlements
bool MobileDeviceManagement = 34 [(gogoproto.jsontag) = "mobile_device_management,omitempty"];
// entitlements define a customers access to a specific features
map<string, EntitlementInfo> entitlements = 35;
// AccessMonitoringConfigured contributes to the enablement of access monitoring.
@@ -639,8 +592,12 @@ message Features {
reserved 37;
reserved "CloudAnonymizationKey";
// AccessGraphDemoMode enables the ability to opt-in to a demo mode of Access Graph with limited features.
// TODO(michellescripts) DELETE IN v21.0.0
// Deprecated, use entitlements
bool AccessGraphDemoMode = 38 [(gogoproto.jsontag) = "access_graph_demo_mode,omitempty"];
// ClientIPRestrictions allows Cloud users to setup a client IP allowlist
// TODO(michellescripts) DELETE IN v21.0.0
// Deprecated, use entitlements
bool ClientIPRestrictions = 39 [(gogoproto.jsontag) = "client_ip_restrictions,omitempty"];
}
-67
View File
@@ -16,8 +16,6 @@
package entitlements
import "github.com/gravitational/teleport/api/client/proto"
type EntitlementKind string
// The EntitlementKind list should be 1:1 with the Features & FeatureStrings in salescenter/product/product.go,
@@ -64,68 +62,3 @@ var AllEntitlements = []EntitlementKind{
OktaUserSync, Policy, SAML, SessionLocks, UnrestrictedManagedUpdates, UpsellAlert, UsageReporting, LicenseAutoUpdate, AccessGraphDemoMode,
ClientIPRestrictions, WorkloadClusters,
}
// BackfillFeatures ensures entitlements are backwards compatible.
// If Entitlements are present, there are no changes.
// If Entitlements are not present, it sets the entitlements based on legacy field values.
// TODO(michellescripts) DELETE IN 18.0.0
func BackfillFeatures(features *proto.Features) {
if len(features.Entitlements) > 0 {
return
}
features.Entitlements = getBaseEntitlements(features.GetEntitlements())
// Entitlements: All records are {enabled: false}; update to equal legacy feature value
features.Entitlements[string(ExternalAuditStorage)] = &proto.EntitlementInfo{Enabled: features.GetExternalAuditStorage()}
features.Entitlements[string(FeatureHiding)] = &proto.EntitlementInfo{Enabled: features.GetFeatureHiding()}
features.Entitlements[string(Identity)] = &proto.EntitlementInfo{Enabled: features.GetIdentityGovernance()}
features.Entitlements[string(JoinActiveSessions)] = &proto.EntitlementInfo{Enabled: features.GetJoinActiveSessions()}
features.Entitlements[string(MobileDeviceManagement)] = &proto.EntitlementInfo{Enabled: features.GetMobileDeviceManagement()}
features.Entitlements[string(OIDC)] = &proto.EntitlementInfo{Enabled: features.GetOIDC()}
features.Entitlements[string(Policy)] = &proto.EntitlementInfo{Enabled: features.GetPolicy().GetEnabled()}
features.Entitlements[string(SAML)] = &proto.EntitlementInfo{Enabled: features.GetSAML()}
features.Entitlements[string(K8s)] = &proto.EntitlementInfo{Enabled: features.GetKubernetes()}
features.Entitlements[string(App)] = &proto.EntitlementInfo{Enabled: features.GetApp()}
features.Entitlements[string(DB)] = &proto.EntitlementInfo{Enabled: features.GetDB()}
features.Entitlements[string(Desktop)] = &proto.EntitlementInfo{Enabled: features.GetDesktop()}
features.Entitlements[string(HSM)] = &proto.EntitlementInfo{Enabled: features.GetHSM()}
features.Entitlements[string(AccessGraphDemoMode)] = &proto.EntitlementInfo{Enabled: features.GetAccessGraphDemoMode()}
// set default Identity fields to legacy feature value
features.Entitlements[string(AccessLists)] = &proto.EntitlementInfo{Enabled: true, Limit: features.GetAccessList().GetCreateLimit()}
features.Entitlements[string(AccessMonitoring)] = &proto.EntitlementInfo{Enabled: features.GetAccessMonitoring().GetEnabled(), Limit: features.GetAccessMonitoring().GetMaxReportRangeLimit()}
features.Entitlements[string(AccessRequests)] = &proto.EntitlementInfo{Enabled: features.GetAccessRequests().GetMonthlyRequestLimit() > 0, Limit: features.GetAccessRequests().GetMonthlyRequestLimit()}
features.Entitlements[string(DeviceTrust)] = &proto.EntitlementInfo{Enabled: features.GetDeviceTrust().GetEnabled(), Limit: features.GetDeviceTrust().GetDevicesUsageLimit()}
// override Identity Package features if Identity is enabled: set true and clear limit
if features.GetIdentityGovernance() {
features.Entitlements[string(AccessLists)] = &proto.EntitlementInfo{Enabled: true}
features.Entitlements[string(AccessMonitoring)] = &proto.EntitlementInfo{Enabled: true}
features.Entitlements[string(AccessRequests)] = &proto.EntitlementInfo{Enabled: true}
features.Entitlements[string(DeviceTrust)] = &proto.EntitlementInfo{Enabled: true}
features.Entitlements[string(OktaSCIM)] = &proto.EntitlementInfo{Enabled: true}
features.Entitlements[string(OktaUserSync)] = &proto.EntitlementInfo{Enabled: true}
features.Entitlements[string(SessionLocks)] = &proto.EntitlementInfo{Enabled: true}
}
}
// getBaseEntitlements takes a cloud entitlement set and returns a modules Entitlement set
func getBaseEntitlements(protoEntitlements map[string]*proto.EntitlementInfo) map[string]*proto.EntitlementInfo {
all := AllEntitlements
result := make(map[string]*proto.EntitlementInfo, len(all))
for _, e := range all {
al, ok := protoEntitlements[string(e)]
if !ok {
result[string(e)] = &proto.EntitlementInfo{}
continue
}
result[string(e)] = &proto.EntitlementInfo{
Enabled: al.Enabled,
Limit: al.Limit,
}
}
return result
}
-319
View File
@@ -1,319 +0,0 @@
// Teleport
// Copyright (C) 2024 Gravitational, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package entitlements
import (
"testing"
"github.com/google/go-cmp/cmp"
"github.com/stretchr/testify/require"
"google.golang.org/protobuf/testing/protocmp"
"github.com/gravitational/teleport/api/client/proto"
apiutils "github.com/gravitational/teleport/api/utils"
)
func TestBackfillFeatures(t *testing.T) {
tests := []struct {
name string
features *proto.Features
expected map[string]*proto.EntitlementInfo
}{
{
name: "entitlements present; keeps entitlement values",
features: &proto.Features{
DeviceTrust: nil,
AccessRequests: nil,
AccessList: nil,
AccessMonitoring: nil,
Policy: nil,
CustomTheme: "",
ProductType: 0,
SupportType: 0,
Kubernetes: false,
App: false,
DB: false,
OIDC: false,
SAML: false,
AccessControls: false,
AdvancedAccessWorkflows: false,
Cloud: false,
HSM: false,
Desktop: false,
RecoveryCodes: false,
Plugins: false,
AutomaticUpgrades: false,
IsUsageBased: false,
Assist: false,
FeatureHiding: false,
IdentityGovernance: false,
AccessGraph: false,
Questionnaire: false,
IsStripeManaged: false,
ExternalAuditStorage: false,
JoinActiveSessions: false,
MobileDeviceManagement: false,
AccessMonitoringConfigured: false,
Entitlements: map[string]*proto.EntitlementInfo{
string(AccessLists): {Enabled: true, Limit: 111},
string(AccessMonitoring): {Enabled: true, Limit: 2113},
string(AccessRequests): {Enabled: true, Limit: 39},
string(App): {Enabled: false},
string(CloudAuditLogRetention): {Enabled: true},
string(DB): {Enabled: true},
string(Desktop): {Enabled: true},
string(DeviceTrust): {Enabled: true, Limit: 103},
string(ExternalAuditStorage): {Enabled: true},
string(FeatureHiding): {Enabled: true},
string(HSM): {Enabled: true},
string(Identity): {Enabled: true},
string(JoinActiveSessions): {Enabled: true},
string(K8s): {Enabled: true},
string(MobileDeviceManagement): {Enabled: true},
string(OIDC): {Enabled: true},
string(OktaSCIM): {Enabled: true},
string(OktaUserSync): {Enabled: true},
string(Policy): {Enabled: true},
string(SAML): {Enabled: true},
string(SessionLocks): {Enabled: true},
string(UpsellAlert): {Enabled: true},
string(UsageReporting): {Enabled: true},
string(LicenseAutoUpdate): {Enabled: true},
string(AccessGraphDemoMode): {Enabled: true},
string(UnrestrictedManagedUpdates): {Enabled: true},
string(ClientIPRestrictions): {Enabled: true},
string(WorkloadClusters): {Enabled: true},
},
},
expected: map[string]*proto.EntitlementInfo{
string(AccessLists): {Enabled: true, Limit: 111},
string(AccessMonitoring): {Enabled: true, Limit: 2113},
string(AccessRequests): {Enabled: true, Limit: 39},
string(App): {Enabled: false},
string(CloudAuditLogRetention): {Enabled: true},
string(DB): {Enabled: true},
string(Desktop): {Enabled: true},
string(DeviceTrust): {Enabled: true, Limit: 103},
string(ExternalAuditStorage): {Enabled: true},
string(FeatureHiding): {Enabled: true},
string(HSM): {Enabled: true},
string(Identity): {Enabled: true},
string(JoinActiveSessions): {Enabled: true},
string(K8s): {Enabled: true},
string(MobileDeviceManagement): {Enabled: true},
string(OIDC): {Enabled: true},
string(OktaSCIM): {Enabled: true},
string(OktaUserSync): {Enabled: true},
string(Policy): {Enabled: true},
string(SAML): {Enabled: true},
string(SessionLocks): {Enabled: true},
string(UpsellAlert): {Enabled: true},
string(UsageReporting): {Enabled: true},
string(LicenseAutoUpdate): {Enabled: true},
string(AccessGraphDemoMode): {Enabled: true},
string(UnrestrictedManagedUpdates): {Enabled: true},
string(ClientIPRestrictions): {Enabled: true},
string(WorkloadClusters): {Enabled: true},
},
},
{
name: "entitlements not present; identity on - sets legacy fields & drops limits",
features: &proto.Features{
DeviceTrust: &proto.DeviceTrustFeature{
Enabled: true,
DevicesUsageLimit: 33,
},
AccessRequests: &proto.AccessRequestsFeature{
MonthlyRequestLimit: 22,
},
AccessList: &proto.AccessListFeature{
CreateLimit: 44,
},
AccessMonitoring: &proto.AccessMonitoringFeature{
Enabled: true,
MaxReportRangeLimit: 55,
},
Policy: &proto.PolicyFeature{
Enabled: true,
},
CustomTheme: "",
ProductType: 0,
SupportType: 0,
Kubernetes: true,
App: true,
DB: true,
OIDC: true,
SAML: true,
AccessControls: true,
AdvancedAccessWorkflows: true,
Cloud: true,
HSM: true,
Desktop: true,
RecoveryCodes: true,
Plugins: true,
AutomaticUpgrades: true,
IsUsageBased: true,
Assist: true,
FeatureHiding: true,
IdentityGovernance: true,
AccessGraph: true,
Questionnaire: true,
IsStripeManaged: true,
ExternalAuditStorage: true,
JoinActiveSessions: true,
MobileDeviceManagement: true,
AccessMonitoringConfigured: true,
},
expected: map[string]*proto.EntitlementInfo{
string(AccessLists): {Enabled: true},
string(AccessMonitoring): {Enabled: true},
string(AccessRequests): {Enabled: true},
string(App): {Enabled: true},
string(DB): {Enabled: true},
string(Desktop): {Enabled: true},
string(DeviceTrust): {Enabled: true},
string(ExternalAuditStorage): {Enabled: true},
string(FeatureHiding): {Enabled: true},
string(HSM): {Enabled: true},
string(Identity): {Enabled: true},
string(JoinActiveSessions): {Enabled: true},
string(K8s): {Enabled: true},
string(MobileDeviceManagement): {Enabled: true},
string(OIDC): {Enabled: true},
string(OktaSCIM): {Enabled: true},
string(OktaUserSync): {Enabled: true},
string(Policy): {Enabled: true},
string(SAML): {Enabled: true},
string(SessionLocks): {Enabled: true},
// defaults, no legacy equivalent
string(UsageReporting): {Enabled: false},
string(UpsellAlert): {Enabled: false},
string(CloudAuditLogRetention): {Enabled: false},
string(LicenseAutoUpdate): {Enabled: false},
string(AccessGraphDemoMode): {Enabled: false},
string(UnrestrictedManagedUpdates): {Enabled: false},
string(ClientIPRestrictions): {Enabled: false},
string(WorkloadClusters): {Enabled: false},
},
},
{
name: "entitlements not present; identity off - sets legacy fields",
features: &proto.Features{
DeviceTrust: &proto.DeviceTrustFeature{
Enabled: true,
DevicesUsageLimit: 33,
},
AccessRequests: &proto.AccessRequestsFeature{
MonthlyRequestLimit: 22,
},
AccessList: &proto.AccessListFeature{
CreateLimit: 44,
},
AccessMonitoring: &proto.AccessMonitoringFeature{
Enabled: true,
MaxReportRangeLimit: 55,
},
Policy: &proto.PolicyFeature{
Enabled: true,
},
CustomTheme: "",
ProductType: 0,
SupportType: 0,
Kubernetes: true,
App: true,
DB: true,
OIDC: true,
SAML: true,
AccessControls: true,
AdvancedAccessWorkflows: true,
Cloud: true,
HSM: true,
Desktop: true,
RecoveryCodes: true,
Plugins: true,
AutomaticUpgrades: true,
IsUsageBased: true,
Assist: true,
FeatureHiding: true,
IdentityGovernance: false,
AccessGraph: true,
Questionnaire: true,
IsStripeManaged: true,
ExternalAuditStorage: true,
JoinActiveSessions: true,
MobileDeviceManagement: true,
AccessMonitoringConfigured: true,
},
expected: map[string]*proto.EntitlementInfo{
string(AccessLists): {Enabled: true, Limit: 44},
string(AccessMonitoring): {Enabled: true, Limit: 55},
string(AccessRequests): {Enabled: true, Limit: 22},
string(DeviceTrust): {Enabled: true, Limit: 33},
string(App): {Enabled: true},
string(DB): {Enabled: true},
string(Desktop): {Enabled: true},
string(ExternalAuditStorage): {Enabled: true},
string(FeatureHiding): {Enabled: true},
string(HSM): {Enabled: true},
string(JoinActiveSessions): {Enabled: true},
string(K8s): {Enabled: true},
string(MobileDeviceManagement): {Enabled: true},
string(OIDC): {Enabled: true},
string(Policy): {Enabled: true},
string(SAML): {Enabled: true},
// defaults, no legacy equivalent
string(UsageReporting): {Enabled: false},
string(UpsellAlert): {Enabled: false},
string(CloudAuditLogRetention): {Enabled: false},
string(LicenseAutoUpdate): {Enabled: false},
string(AccessGraphDemoMode): {Enabled: false},
string(UnrestrictedManagedUpdates): {Enabled: false},
string(ClientIPRestrictions): {Enabled: false},
string(WorkloadClusters): {Enabled: false},
// Identity off, fields false
string(Identity): {Enabled: false},
string(SessionLocks): {Enabled: false},
string(OktaSCIM): {Enabled: false},
string(OktaUserSync): {Enabled: false},
},
},
{
name: "no entitlements",
features: &proto.Features{},
expected: func() map[string]*proto.EntitlementInfo {
out := map[string]*proto.EntitlementInfo{
string(AccessLists): {Enabled: true},
}
for _, e := range AllEntitlements {
if _, ok := out[string(e)]; !ok {
out[string(e)] = &proto.EntitlementInfo{}
}
}
return out
}(),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
cloned := apiutils.CloneProtoMsg(tt.features)
BackfillFeatures(cloned)
require.Empty(t, cmp.Diff(tt.expected, cloned.Entitlements, protocmp.Transform()))
})
}
}
+8 -36
View File
@@ -117,7 +117,7 @@ func (e EntitlementInfo) UnderLimit(count int) bool {
// ToProto converts Features into proto.Features
func (f Features) ToProto() *proto.Features {
protoF := &proto.Features{
return &proto.Features{
Cloud: f.Cloud,
CustomTheme: f.CustomTheme,
IsStripeManaged: f.IsStripeManaged,
@@ -133,42 +133,14 @@ func (f Features) ToProto() *proto.Features {
RecoveryCodes: f.RecoveryCodes,
AccessMonitoringConfigured: f.AccessMonitoringConfigured,
Entitlements: f.EntitlementsToProto(),
}
// remove setLegacyLogic in v18
setLegacyLogic(protoF, f)
return protoF
}
// setLegacyLogic sets the deprecated fields; to be removed in v18 - use entitlements
func setLegacyLogic(protoF *proto.Features, f Features) {
protoF.Kubernetes = f.GetEntitlement(entitlements.K8s).Enabled
protoF.App = f.GetEntitlement(entitlements.App).Enabled
protoF.DB = f.GetEntitlement(entitlements.DB).Enabled
protoF.OIDC = f.GetEntitlement(entitlements.OIDC).Enabled
protoF.SAML = f.GetEntitlement(entitlements.SAML).Enabled
protoF.HSM = f.GetEntitlement(entitlements.HSM).Enabled
protoF.Desktop = f.GetEntitlement(entitlements.Desktop).Enabled
protoF.FeatureHiding = f.GetEntitlement(entitlements.FeatureHiding).Enabled
protoF.IdentityGovernance = f.GetEntitlement(entitlements.Identity).Enabled
protoF.ExternalAuditStorage = f.GetEntitlement(entitlements.ExternalAuditStorage).Enabled
protoF.JoinActiveSessions = f.GetEntitlement(entitlements.JoinActiveSessions).Enabled
protoF.MobileDeviceManagement = f.GetEntitlement(entitlements.MobileDeviceManagement).Enabled
protoF.DeviceTrust = &proto.DeviceTrustFeature{
Enabled: f.GetEntitlement(entitlements.DeviceTrust).Enabled, DevicesUsageLimit: f.GetEntitlement(entitlements.DeviceTrust).Limit,
}
protoF.AccessRequests = &proto.AccessRequestsFeature{
MonthlyRequestLimit: f.GetEntitlement(entitlements.AccessRequests).Limit,
}
protoF.AccessMonitoring = &proto.AccessMonitoringFeature{
Enabled: f.AccessMonitoringConfigured, MaxReportRangeLimit: f.GetEntitlement(entitlements.AccessMonitoring).Limit,
}
protoF.AccessList = &proto.AccessListFeature{
CreateLimit: f.GetEntitlement(entitlements.AccessLists).Limit,
}
protoF.Policy = &proto.PolicyFeature{
Enabled: f.GetEntitlement(entitlements.Policy).Enabled,
// TODO(michellescripts) DELETE IN v21.0.0
// Deprecated, use entitlements
Policy: &proto.PolicyFeature{
Enabled: f.GetEntitlement(entitlements.Policy).Enabled,
},
AccessGraphDemoMode: f.GetEntitlement(entitlements.AccessGraphDemoMode).Enabled,
ClientIPRestrictions: f.GetEntitlement(entitlements.ClientIPRestrictions).Enabled,
}
}
+4 -27
View File
@@ -167,36 +167,13 @@ func TestFeatures_ToProto(t *testing.T) {
string(entitlements.ClientIPRestrictions): {Enabled: true},
string(entitlements.WorkloadClusters): {Enabled: true},
},
// Legacy Fields; remove in v18
Kubernetes: true,
App: false,
DB: true,
OIDC: true,
SAML: true,
HSM: true,
Desktop: true,
FeatureHiding: true,
IdentityGovernance: true,
ExternalAuditStorage: true,
JoinActiveSessions: true,
MobileDeviceManagement: true,
DeviceTrust: &proto.DeviceTrustFeature{
Enabled: true,
DevicesUsageLimit: 103,
},
AccessRequests: &proto.AccessRequestsFeature{
MonthlyRequestLimit: 39,
},
AccessMonitoring: &proto.AccessMonitoringFeature{
Enabled: false, // set to value of AccessMonitoringConfigured
MaxReportRangeLimit: 2113,
},
AccessList: &proto.AccessListFeature{
CreateLimit: 111,
},
// Deprecated fields
// TODO(michellescripts) DELETE IN v21.0.0
Policy: &proto.PolicyFeature{
Enabled: true,
},
AccessGraphDemoMode: true,
ClientIPRestrictions: true,
}
f := modules.Features{
+1 -5
View File
@@ -48,7 +48,6 @@ import (
apiutils "github.com/gravitational/teleport/api/utils"
"github.com/gravitational/teleport/api/utils/keys"
"github.com/gravitational/teleport/api/utils/retryutils"
"github.com/gravitational/teleport/entitlements"
"github.com/gravitational/teleport/lib"
"github.com/gravitational/teleport/lib/auth"
"github.com/gravitational/teleport/lib/auth/authclient"
@@ -1363,10 +1362,7 @@ func (process *TeleportProcess) getConnector(clientIdentity, serverIdentity *sta
}
// Set cluster features and return successfully with a working connector.
// TODO(michellescripts) remove clone & compatibility check in v18
cloned := apiutils.CloneProtoMsg(pingResponse.GetServerFeatures())
entitlements.BackfillFeatures(cloned)
process.setClusterFeatures(cloned)
process.setClusterFeatures(pingResponse.GetServerFeatures())
process.setAuthSubjectiveAddr(pingResponse.RemoteAddr)
process.logger.InfoContext(process.ExitContext(), "features loaded from auth server", "identity", clientIdentity.ID.Role, "features", pingResponse.GetServerFeatures())
+2 -82
View File
@@ -2034,7 +2034,6 @@ func (h *Handler) getWebConfig(w http.ResponseWriter, r *http.Request, p httprou
UI: h.getUIConfig(r.Context()),
IsPolicyRoleVisualizerEnabled: !disableRoleVisualizer,
IsDashboard: services.IsDashboard(clusterFeatures),
IsTeam: false,
IsUsageBasedBilling: clusterFeatures.GetIsUsageBased(),
AutomaticUpgrades: automaticUpgradesEnabled,
AutomaticUpgradesTargetVersion: automaticUpgradesTargetVersion,
@@ -2044,7 +2043,8 @@ func (h *Handler) getWebConfig(w http.ResponseWriter, r *http.Request, p httprou
PremiumSupport: clusterFeatures.GetSupportType() == proto.SupportType_SUPPORT_TYPE_PREMIUM,
PlayableDatabaseProtocols: player.SupportedDatabaseProtocols,
SessionSummarizerEnabled: sessionSummarizerEnabled,
// Entitlements are reset/overridden in setEntitlementsWithLegacyLogic until setEntitlementsWithLegacyLogic is removed in v18
// 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
Entitlements: GetWebCfgEntitlements(clusterFeatures.GetEntitlements()),
IdentitySecurity: webclient.IdentitySecurity{
IsClusterLicensed: modules.GetProtoEntitlement(&clusterFeatures, entitlements.Policy).Enabled,
@@ -2053,9 +2053,6 @@ func (h *Handler) getWebConfig(w http.ResponseWriter, r *http.Request, p httprou
},
}
// Set entitlements with backwards field compatibility
setEntitlementsWithLegacyLogic(&webCfg, clusterFeatures)
resource, err := h.cfg.ProxyClient.GetClusterName(r.Context())
if err != nil {
h.logger.WarnContext(r.Context(), "Failed to query cluster name", "error", err)
@@ -2220,83 +2217,6 @@ func (h *Handler) getUserMatchedAuthConnectors(w http.ResponseWriter, r *http.Re
}, 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 ent := clusterFeatures.GetEntitlements(); len(ent) > 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().GetMonthlyRequestLimit() > 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().GetMonthlyRequestLimit() > 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
+5 -610
View File
@@ -4900,12 +4900,11 @@ func TestGetWebConfig_WithEntitlements(t *testing.T) {
PrivateKeyPolicy: keys.PrivateKeyPolicyNone,
MOTD: MOTD,
},
CanJoinSessions: true,
ProxyClusterName: env.server.ClusterName(),
IsCloud: false,
AutomaticUpgrades: false,
JoinActiveSessions: true,
Edition: testModules.BuildType(),
CanJoinSessions: true,
ProxyClusterName: env.server.ClusterName(),
IsCloud: false,
AutomaticUpgrades: false,
Edition: testModules.BuildType(),
Entitlements: map[string]webclient.EntitlementInfo{
string(entitlements.AccessLists): {Enabled: false},
string(entitlements.AccessMonitoring): {Enabled: false},
@@ -4996,9 +4995,7 @@ func TestGetWebConfig_WithEntitlements(t *testing.T) {
expectedCfg.IsUsageBasedBilling = true
expectedCfg.AutomaticUpgrades = true
expectedCfg.AutomaticUpgradesTargetVersion = "v" + teleport.Version
expectedCfg.JoinActiveSessions = false
expectedCfg.Edition = testModules.BuildType()
expectedCfg.TrustedDevices = true
expectedCfg.Entitlements[string(entitlements.App)] = webclient.EntitlementInfo{Enabled: false}
expectedCfg.Entitlements[string(entitlements.DB)] = webclient.EntitlementInfo{Enabled: true, Limit: 22}
expectedCfg.Entitlements[string(entitlements.DeviceTrust)] = webclient.EntitlementInfo{Enabled: true, Limit: 33}
@@ -5027,7 +5024,6 @@ func TestGetWebConfig_WithEntitlements(t *testing.T) {
}
env.proxies[0].client = mockClient
expectedCfg.AutomaticUpgrades = false
expectedCfg.TrustedDevices = false
expectedCfg.Entitlements[string(entitlements.DB)] = webclient.EntitlementInfo{Enabled: false}
expectedCfg.Entitlements[string(entitlements.Desktop)] = webclient.EntitlementInfo{Enabled: false}
expectedCfg.Entitlements[string(entitlements.DeviceTrust)] = webclient.EntitlementInfo{Enabled: false}
@@ -5056,94 +5052,6 @@ func TestGetWebConfig_WithEntitlements(t *testing.T) {
}, time.Second*5, time.Millisecond*50)
}
func TestGetWebConfig_LegacyFeatureLimits(t *testing.T) {
ctx := context.Background()
testModules := &modulestest.Modules{
TestBuildType: modules.BuildOSS,
TestFeatures: modules.Features{
ProductType: modules.ProductTypeTeam,
IsUsageBasedBilling: true,
IsStripeManaged: true,
Questionnaire: true,
Entitlements: map[entitlements.EntitlementKind]modules.EntitlementInfo{
entitlements.Identity: {Enabled: true},
entitlements.AccessLists: {Enabled: true, Limit: 5},
entitlements.AccessMonitoring: {Enabled: true, Limit: 10},
},
},
}
env := newWebPack(t, 1, withModules(testModules))
expectedCfg := webclient.WebConfig{
Auth: webclient.WebConfigAuthSettings{
SecondFactor: constants.SecondFactorOff,
LocalAuthEnabled: true,
AuthType: constants.Local,
PrivateKeyPolicy: keys.PrivateKeyPolicyNone,
},
CanJoinSessions: true,
Edition: testModules.TestBuildType,
ProxyClusterName: env.server.ClusterName(),
FeatureLimits: webclient.FeatureLimits{
AccessListCreateLimit: 5,
AccessMonitoringMaxReportRangeLimit: 10,
},
IsTeam: false,
IsIGSEnabled: true,
IsStripeManaged: true,
Questionnaire: true,
IsUsageBasedBilling: true,
Entitlements: map[string]webclient.EntitlementInfo{
string(entitlements.AccessLists): {Enabled: true, Limit: 5},
string(entitlements.AccessMonitoring): {Enabled: true, Limit: 10},
string(entitlements.AccessRequests): {Enabled: false},
string(entitlements.App): {Enabled: false},
string(entitlements.CloudAuditLogRetention): {Enabled: false},
string(entitlements.DB): {Enabled: false},
string(entitlements.Desktop): {Enabled: false},
string(entitlements.DeviceTrust): {Enabled: false},
string(entitlements.ExternalAuditStorage): {Enabled: false},
string(entitlements.FeatureHiding): {Enabled: false},
string(entitlements.HSM): {Enabled: false},
string(entitlements.Identity): {Enabled: true},
string(entitlements.JoinActiveSessions): {Enabled: false},
string(entitlements.K8s): {Enabled: false},
string(entitlements.MobileDeviceManagement): {Enabled: false},
string(entitlements.OIDC): {Enabled: false},
string(entitlements.OktaSCIM): {Enabled: false},
string(entitlements.OktaUserSync): {Enabled: false},
string(entitlements.Policy): {Enabled: false},
string(entitlements.SAML): {Enabled: false},
string(entitlements.SessionLocks): {Enabled: false},
string(entitlements.UpsellAlert): {Enabled: false},
string(entitlements.UsageReporting): {Enabled: false},
string(entitlements.LicenseAutoUpdate): {Enabled: false},
string(entitlements.AccessGraphDemoMode): {Enabled: false},
string(entitlements.UnrestrictedManagedUpdates): {Enabled: false},
string(entitlements.ClientIPRestrictions): {Enabled: false},
string(entitlements.WorkloadClusters): {Enabled: false},
},
PlayableDatabaseProtocols: player.SupportedDatabaseProtocols,
IsPolicyRoleVisualizerEnabled: true,
}
clt := env.proxies[0].newClient(t)
// Make a request.
endpoint := clt.Endpoint("web", "config.js")
re, err := clt.Get(ctx, endpoint, nil)
require.NoError(t, err)
require.True(t, bytes.HasPrefix(re.Bytes(), []byte("var GRV_CONFIG")))
// Response is type application/javascript, we need to strip off the variable name
// and the semicolon at the end, then we are left with json like object.
var cfg webclient.WebConfig
res := bytes.ReplaceAll(re.Bytes(), []byte("var GRV_CONFIG = "), []byte{})
err = json.Unmarshal(res[:len(res)-1], &cfg)
require.NoError(t, err)
diff := cmp.Diff(expectedCfg, cfg)
require.Empty(t, diff)
}
func TestCreatePrivilegeToken(t *testing.T) {
t.Parallel()
env := newWebPack(t, 1)
@@ -11356,519 +11264,6 @@ func TestUnstartedServerShutdown(t *testing.T) {
require.NoError(t, srv.Shutdown(context.Background()))
}
func Test_setEntitlementsWithLegacyLogic(t *testing.T) {
tests := []struct {
name string
config *webclient.WebConfig
clusterFeatures authproto.Features
expected *webclient.WebConfig
}{
{
name: "sets entitlements",
config: &webclient.WebConfig{},
clusterFeatures: authproto.Features{
AccessControls: false,
AccessGraph: false,
AccessList: &authproto.AccessListFeature{
CreateLimit: 10,
},
AccessMonitoring: &authproto.AccessMonitoringFeature{
Enabled: false,
MaxReportRangeLimit: 20,
},
AccessMonitoringConfigured: false,
AccessRequests: &authproto.AccessRequestsFeature{
MonthlyRequestLimit: 30,
},
AdvancedAccessWorkflows: false,
App: false,
Assist: false,
AutomaticUpgrades: false,
Cloud: false,
CustomTheme: "theme",
DB: false,
Desktop: false,
DeviceTrust: &authproto.DeviceTrustFeature{
Enabled: false,
DevicesUsageLimit: 40,
},
ExternalAuditStorage: false,
FeatureHiding: false,
HSM: false,
IdentityGovernance: false,
IsStripeManaged: false,
IsUsageBased: false,
JoinActiveSessions: false,
Kubernetes: false,
MobileDeviceManagement: false,
OIDC: false,
Plugins: false,
Policy: nil,
ProductType: 0,
Questionnaire: false,
RecoveryCodes: false,
SAML: false,
SupportType: 0,
// since present, becomes source of truth for feature enablement
Entitlements: map[string]*authproto.EntitlementInfo{
string(entitlements.AccessLists): {Enabled: true, Limit: 99},
string(entitlements.AccessMonitoring): {Enabled: true, Limit: 99},
string(entitlements.AccessRequests): {Enabled: true, Limit: 99},
string(entitlements.App): {Enabled: true, Limit: 99},
string(entitlements.CloudAuditLogRetention): {Enabled: true, Limit: 99},
string(entitlements.DB): {Enabled: true, Limit: 99},
string(entitlements.Desktop): {Enabled: true, Limit: 99},
string(entitlements.DeviceTrust): {Enabled: true, Limit: 99},
string(entitlements.ExternalAuditStorage): {Enabled: true, Limit: 99},
string(entitlements.FeatureHiding): {Enabled: true, Limit: 99},
string(entitlements.HSM): {Enabled: true, Limit: 99},
string(entitlements.Identity): {Enabled: true, Limit: 99},
string(entitlements.JoinActiveSessions): {Enabled: true, Limit: 99},
string(entitlements.K8s): {Enabled: true, Limit: 99},
string(entitlements.MobileDeviceManagement): {Enabled: true, Limit: 99},
string(entitlements.OIDC): {Enabled: true, Limit: 99},
string(entitlements.OktaSCIM): {Enabled: true, Limit: 99},
string(entitlements.OktaUserSync): {Enabled: true, Limit: 99},
string(entitlements.Policy): {Enabled: true, Limit: 99},
string(entitlements.SAML): {Enabled: true, Limit: 99},
string(entitlements.SessionLocks): {Enabled: true, Limit: 99},
string(entitlements.UpsellAlert): {Enabled: true, Limit: 99},
string(entitlements.UsageReporting): {Enabled: true, Limit: 99},
string(entitlements.LicenseAutoUpdate): {Enabled: true, Limit: 99},
string(entitlements.AccessGraphDemoMode): {Enabled: true, Limit: 99},
string(entitlements.UnrestrictedManagedUpdates): {Enabled: true, Limit: 99},
string(entitlements.ClientIPRestrictions): {Enabled: true, Limit: 99},
string(entitlements.WorkloadClusters): {Enabled: true, Limit: 99},
},
},
expected: &webclient.WebConfig{
Auth: webclient.WebConfigAuthSettings{},
AutomaticUpgrades: false,
AutomaticUpgradesTargetVersion: "",
CanJoinSessions: false,
CustomTheme: "",
Edition: "",
IsCloud: false,
IsDashboard: false,
IsStripeManaged: false,
IsTeam: false,
IsUsageBasedBilling: false,
PlayableDatabaseProtocols: nil,
PremiumSupport: false,
ProxyClusterName: "",
Questionnaire: false,
RecoveryCodesEnabled: false,
TunnelPublicAddress: "",
UI: webclient.UIConfig{},
// set by the equivalent entitlement value
AccessRequests: true,
ExternalAuditStorage: true,
HideInaccessibleFeatures: true,
IsIGSEnabled: true,
IsPolicyEnabled: true,
JoinActiveSessions: true,
MobileDeviceManagement: true,
OIDC: true,
SAML: true,
TrustedDevices: true,
FeatureLimits: webclient.FeatureLimits{
AccessListCreateLimit: 99,
AccessMonitoringMaxReportRangeLimit: 99,
AccessRequestMonthlyRequestLimit: 99,
},
Entitlements: map[string]webclient.EntitlementInfo{
string(entitlements.AccessLists): {Enabled: true, Limit: 99},
string(entitlements.AccessMonitoring): {Enabled: true, Limit: 99},
string(entitlements.AccessRequests): {Enabled: true, Limit: 99},
string(entitlements.App): {Enabled: true, Limit: 99},
string(entitlements.CloudAuditLogRetention): {Enabled: true, Limit: 99},
string(entitlements.DB): {Enabled: true, Limit: 99},
string(entitlements.Desktop): {Enabled: true, Limit: 99},
string(entitlements.DeviceTrust): {Enabled: true, Limit: 99},
string(entitlements.ExternalAuditStorage): {Enabled: true, Limit: 99},
string(entitlements.FeatureHiding): {Enabled: true, Limit: 99},
string(entitlements.HSM): {Enabled: true, Limit: 99},
string(entitlements.Identity): {Enabled: true, Limit: 99},
string(entitlements.JoinActiveSessions): {Enabled: true, Limit: 99},
string(entitlements.K8s): {Enabled: true, Limit: 99},
string(entitlements.MobileDeviceManagement): {Enabled: true, Limit: 99},
string(entitlements.OIDC): {Enabled: true, Limit: 99},
string(entitlements.OktaSCIM): {Enabled: true, Limit: 99},
string(entitlements.OktaUserSync): {Enabled: true, Limit: 99},
string(entitlements.Policy): {Enabled: true, Limit: 99},
string(entitlements.SAML): {Enabled: true, Limit: 99},
string(entitlements.SessionLocks): {Enabled: true, Limit: 99},
string(entitlements.UpsellAlert): {Enabled: true, Limit: 99},
string(entitlements.UsageReporting): {Enabled: true, Limit: 99},
string(entitlements.LicenseAutoUpdate): {Enabled: true, Limit: 99},
string(entitlements.AccessGraphDemoMode): {Enabled: true, Limit: 99},
string(entitlements.UnrestrictedManagedUpdates): {Enabled: true, Limit: 99},
string(entitlements.ClientIPRestrictions): {Enabled: true, Limit: 99},
string(entitlements.WorkloadClusters): {Enabled: true, Limit: 99},
},
},
},
{
name: "sets legacy features when no entitlements are present (Identity true)",
config: &webclient.WebConfig{},
clusterFeatures: authproto.Features{
AccessControls: false,
AccessGraph: false,
AccessMonitoringConfigured: false,
AdvancedAccessWorkflows: false,
App: false,
Assist: false,
AutomaticUpgrades: false,
Cloud: false,
CustomTheme: "",
DB: false,
Desktop: false,
HSM: false,
IsStripeManaged: false,
IsUsageBased: false,
Kubernetes: false,
Plugins: false,
ProductType: 0,
Questionnaire: false,
RecoveryCodes: false,
SupportType: 0,
// not present
Entitlements: nil,
// will set equivalent entitlement values
ExternalAuditStorage: true,
FeatureHiding: true,
IdentityGovernance: true,
JoinActiveSessions: true,
MobileDeviceManagement: true,
OIDC: true,
SAML: true,
AccessRequests: &authproto.AccessRequestsFeature{
MonthlyRequestLimit: 88,
},
AccessList: &authproto.AccessListFeature{
CreateLimit: 88,
},
AccessMonitoring: &authproto.AccessMonitoringFeature{
Enabled: true,
MaxReportRangeLimit: 88,
},
DeviceTrust: &authproto.DeviceTrustFeature{
Enabled: true,
DevicesUsageLimit: 88,
},
Policy: &authproto.PolicyFeature{
Enabled: true,
},
},
expected: &webclient.WebConfig{
Auth: webclient.WebConfigAuthSettings{},
AutomaticUpgrades: false,
AutomaticUpgradesTargetVersion: "",
CanJoinSessions: false,
CustomTheme: "",
Edition: "",
IsCloud: false,
IsDashboard: false,
IsStripeManaged: false,
IsTeam: false,
IsUsageBasedBilling: false,
PlayableDatabaseProtocols: nil,
PremiumSupport: false,
ProxyClusterName: "",
Questionnaire: false,
RecoveryCodesEnabled: false,
TunnelPublicAddress: "",
UI: webclient.UIConfig{},
// set to legacy feature
AccessRequests: true,
ExternalAuditStorage: true,
HideInaccessibleFeatures: true,
IsIGSEnabled: true,
IsPolicyEnabled: true,
JoinActiveSessions: true,
MobileDeviceManagement: true,
OIDC: true,
SAML: true,
TrustedDevices: true,
FeatureLimits: webclient.FeatureLimits{
AccessListCreateLimit: 88,
AccessMonitoringMaxReportRangeLimit: 88,
AccessRequestMonthlyRequestLimit: 88,
},
Entitlements: map[string]webclient.EntitlementInfo{
// no equivalent legacy feature; defaults to false
string(entitlements.App): {Enabled: false},
string(entitlements.CloudAuditLogRetention): {Enabled: false},
string(entitlements.DB): {Enabled: false},
string(entitlements.Desktop): {Enabled: false},
string(entitlements.HSM): {Enabled: false},
string(entitlements.K8s): {Enabled: false},
string(entitlements.UpsellAlert): {Enabled: false},
string(entitlements.UsageReporting): {Enabled: false},
string(entitlements.LicenseAutoUpdate): {Enabled: false},
string(entitlements.AccessGraphDemoMode): {Enabled: false},
string(entitlements.UnrestrictedManagedUpdates): {Enabled: false},
string(entitlements.ClientIPRestrictions): {Enabled: false},
string(entitlements.WorkloadClusters): {Enabled: false},
// set to equivalent legacy feature
string(entitlements.ExternalAuditStorage): {Enabled: true},
string(entitlements.FeatureHiding): {Enabled: true},
string(entitlements.Identity): {Enabled: true},
string(entitlements.JoinActiveSessions): {Enabled: true},
string(entitlements.MobileDeviceManagement): {Enabled: true},
string(entitlements.OIDC): {Enabled: true},
string(entitlements.Policy): {Enabled: true},
string(entitlements.SAML): {Enabled: true},
// set to legacy feature "IsIGSEnabled"; true so set true and clear limits
string(entitlements.AccessLists): {Enabled: true},
string(entitlements.AccessMonitoring): {Enabled: true},
string(entitlements.AccessRequests): {Enabled: true},
string(entitlements.DeviceTrust): {Enabled: true},
string(entitlements.OktaSCIM): {Enabled: true},
string(entitlements.OktaUserSync): {Enabled: true},
string(entitlements.SessionLocks): {Enabled: true},
},
},
},
{
name: "sets legacy features when no entitlements are present (Identity false)",
config: &webclient.WebConfig{},
clusterFeatures: authproto.Features{
AccessControls: false,
AccessGraph: false,
AccessMonitoringConfigured: false,
AdvancedAccessWorkflows: false,
App: false,
Assist: false,
AutomaticUpgrades: false,
Cloud: false,
CustomTheme: "",
DB: false,
Desktop: false,
HSM: false,
IsStripeManaged: false,
IsUsageBased: false,
Kubernetes: false,
Plugins: false,
ProductType: 0,
Questionnaire: false,
RecoveryCodes: false,
SupportType: 0,
// not present
Entitlements: nil,
// will set equivalent entitlement values
ExternalAuditStorage: true,
FeatureHiding: true,
IdentityGovernance: false,
JoinActiveSessions: true,
MobileDeviceManagement: true,
OIDC: true,
SAML: true,
AccessRequests: &authproto.AccessRequestsFeature{
MonthlyRequestLimit: 88,
},
AccessList: &authproto.AccessListFeature{
CreateLimit: 88,
},
AccessMonitoring: &authproto.AccessMonitoringFeature{
Enabled: true,
MaxReportRangeLimit: 88,
},
DeviceTrust: &authproto.DeviceTrustFeature{
Enabled: true,
DevicesUsageLimit: 88,
},
Policy: &authproto.PolicyFeature{
Enabled: true,
},
},
expected: &webclient.WebConfig{
Auth: webclient.WebConfigAuthSettings{},
AutomaticUpgrades: false,
AutomaticUpgradesTargetVersion: "",
CanJoinSessions: false,
CustomTheme: "",
Edition: "",
IsCloud: false,
IsDashboard: false,
IsStripeManaged: false,
IsTeam: false,
IsUsageBasedBilling: false,
PlayableDatabaseProtocols: nil,
PremiumSupport: false,
ProxyClusterName: "",
Questionnaire: false,
RecoveryCodesEnabled: false,
TunnelPublicAddress: "",
UI: webclient.UIConfig{},
// set to legacy feature
AccessRequests: true,
ExternalAuditStorage: true,
HideInaccessibleFeatures: true,
IsIGSEnabled: false,
IsPolicyEnabled: true,
JoinActiveSessions: true,
MobileDeviceManagement: true,
OIDC: true,
SAML: true,
TrustedDevices: true,
FeatureLimits: webclient.FeatureLimits{
AccessListCreateLimit: 88,
AccessMonitoringMaxReportRangeLimit: 88,
AccessRequestMonthlyRequestLimit: 88,
},
Entitlements: map[string]webclient.EntitlementInfo{
// no equivalent legacy feature; defaults to false
string(entitlements.App): {Enabled: false},
string(entitlements.CloudAuditLogRetention): {Enabled: false},
string(entitlements.DB): {Enabled: false},
string(entitlements.Desktop): {Enabled: false},
string(entitlements.HSM): {Enabled: false},
string(entitlements.K8s): {Enabled: false},
string(entitlements.UpsellAlert): {Enabled: false},
string(entitlements.UsageReporting): {Enabled: false},
// set to equivalent legacy feature
string(entitlements.ExternalAuditStorage): {Enabled: true},
string(entitlements.FeatureHiding): {Enabled: true},
string(entitlements.Identity): {Enabled: false},
string(entitlements.JoinActiveSessions): {Enabled: true},
string(entitlements.MobileDeviceManagement): {Enabled: true},
string(entitlements.OIDC): {Enabled: true},
string(entitlements.Policy): {Enabled: true},
string(entitlements.SAML): {Enabled: true},
string(entitlements.AccessGraphDemoMode): {Enabled: false},
string(entitlements.UnrestrictedManagedUpdates): {Enabled: false},
string(entitlements.ClientIPRestrictions): {Enabled: false},
string(entitlements.WorkloadClusters): {Enabled: false},
// set to legacy feature "IsIGSEnabled"; false so set value and keep limits
string(entitlements.AccessLists): {Enabled: true, Limit: 88},
string(entitlements.AccessMonitoring): {Enabled: true, Limit: 88},
string(entitlements.AccessRequests): {Enabled: true, Limit: 88},
string(entitlements.DeviceTrust): {Enabled: true, Limit: 88},
string(entitlements.OktaSCIM): {Enabled: false},
string(entitlements.OktaUserSync): {Enabled: false},
string(entitlements.SessionLocks): {Enabled: false},
string(entitlements.LicenseAutoUpdate): {Enabled: false},
},
},
},
{
name: "retains non-feature field values",
config: &webclient.WebConfig{
Auth: webclient.WebConfigAuthSettings{
LocalAuthEnabled: true,
AllowPasswordless: true,
MOTD: "some-message",
},
PlayableDatabaseProtocols: []string{"play-able"},
UI: webclient.UIConfig{
ScrollbackLines: 10,
ShowResources: "foo",
},
Edition: "edition",
TunnelPublicAddress: "0000",
AutomaticUpgradesTargetVersion: "99",
CustomTheme: "theme",
CanJoinSessions: true,
IsCloud: true,
RecoveryCodesEnabled: true,
IsDashboard: true,
IsUsageBasedBilling: true,
AutomaticUpgrades: true,
Questionnaire: true,
IsStripeManaged: true,
PremiumSupport: true,
},
clusterFeatures: authproto.Features{
DeviceTrust: &authproto.DeviceTrustFeature{},
AccessRequests: &authproto.AccessRequestsFeature{},
AccessList: &authproto.AccessListFeature{},
AccessMonitoring: &authproto.AccessMonitoringFeature{},
Policy: &authproto.PolicyFeature{},
},
expected: &webclient.WebConfig{
Auth: webclient.WebConfigAuthSettings{
LocalAuthEnabled: true,
AllowPasswordless: true,
MOTD: "some-message",
},
PlayableDatabaseProtocols: []string{"play-able"},
UI: webclient.UIConfig{
ScrollbackLines: 10,
ShowResources: "foo",
},
Edition: "edition",
TunnelPublicAddress: "0000",
AutomaticUpgradesTargetVersion: "99",
CustomTheme: "theme",
CanJoinSessions: true,
IsCloud: true,
RecoveryCodesEnabled: true,
IsDashboard: true,
IsUsageBasedBilling: true,
AutomaticUpgrades: true,
Questionnaire: true,
IsStripeManaged: true,
PremiumSupport: true,
// Default; not under test
ProxyClusterName: "",
FeatureLimits: webclient.FeatureLimits{},
IsTeam: false,
HideInaccessibleFeatures: false,
IsIGSEnabled: false,
IsPolicyEnabled: false,
ExternalAuditStorage: false,
JoinActiveSessions: false,
AccessRequests: false,
TrustedDevices: false,
OIDC: false,
SAML: false,
MobileDeviceManagement: false,
Entitlements: map[string]webclient.EntitlementInfo{
string(entitlements.AccessLists): {Enabled: true}, // AccessLists had no previous behavior from an enablement perspective; so we default to true
string(entitlements.AccessMonitoring): {Enabled: false},
string(entitlements.AccessRequests): {Enabled: false},
string(entitlements.App): {Enabled: false},
string(entitlements.CloudAuditLogRetention): {Enabled: false},
string(entitlements.DB): {Enabled: false},
string(entitlements.Desktop): {Enabled: false},
string(entitlements.DeviceTrust): {Enabled: false},
string(entitlements.ExternalAuditStorage): {Enabled: false},
string(entitlements.FeatureHiding): {Enabled: false},
string(entitlements.HSM): {Enabled: false},
string(entitlements.Identity): {Enabled: false},
string(entitlements.JoinActiveSessions): {Enabled: false},
string(entitlements.K8s): {Enabled: false},
string(entitlements.MobileDeviceManagement): {Enabled: false},
string(entitlements.OIDC): {Enabled: false},
string(entitlements.OktaSCIM): {Enabled: false},
string(entitlements.OktaUserSync): {Enabled: false},
string(entitlements.Policy): {Enabled: false},
string(entitlements.SAML): {Enabled: false},
string(entitlements.SessionLocks): {Enabled: false},
string(entitlements.UpsellAlert): {Enabled: false},
string(entitlements.UsageReporting): {Enabled: false},
string(entitlements.LicenseAutoUpdate): {Enabled: false},
string(entitlements.AccessGraphDemoMode): {Enabled: false},
string(entitlements.UnrestrictedManagedUpdates): {Enabled: false},
string(entitlements.ClientIPRestrictions): {Enabled: false},
string(entitlements.WorkloadClusters): {Enabled: false},
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
setEntitlementsWithLegacyLogic(tt.config, tt.clusterFeatures)
assert.Equal(t, tt.expected, tt.config)
})
}
}
// TestPingWithSAMLURL asserts that /webapi/ping and other endpoints necessary
// for local user login return successfully even when a SAML connector is
// configured with an entity descriptor URL that hangs when requested.
-2
View File
@@ -20,7 +20,6 @@ package web
import (
"github.com/gravitational/teleport/api/client/proto"
"github.com/gravitational/teleport/entitlements"
)
// SetClusterFeatures sets the flags for supported and unsupported features.
@@ -30,7 +29,6 @@ func (h *Handler) SetClusterFeatures(features proto.Features) {
h.Mutex.Lock()
defer h.Mutex.Unlock()
entitlements.BackfillFeatures(&features)
h.clusterFeatures = features
}
+4 -23
View File
@@ -62,9 +62,7 @@ func (m *mockedFeatureGetter) setFeatures(f proto.Features) {
func TestFeaturesWatcher(t *testing.T) {
synctest.Test(t, func(t *testing.T) {
mockClient := &mockedFeatureGetter{features: proto.Features{
Kubernetes: true,
Entitlements: map[string]*proto.EntitlementInfo{},
AccessRequests: &proto.AccessRequestsFeature{},
Entitlements: map[string]*proto.EntitlementInfo{},
}}
ctx, cancel := context.WithCancel(t.Context())
@@ -94,21 +92,15 @@ func TestFeaturesWatcher(t *testing.T) {
// after starting the watcher, handler.GetClusterFeatures should return
// values matching the client's response
features := proto.Features{
Kubernetes: true,
Entitlements: map[string]*proto.EntitlementInfo{},
AccessRequests: &proto.AccessRequestsFeature{},
Entitlements: map[string]*proto.EntitlementInfo{},
}
entitlements.BackfillFeatures(&features)
expected := utils.CloneProtoMsg(&features)
require.Equal(t, *expected, handler.GetClusterFeatures())
// update values once again and check if the features are properly updated
features = proto.Features{
Kubernetes: false,
Entitlements: map[string]*proto.EntitlementInfo{},
AccessRequests: &proto.AccessRequestsFeature{},
Entitlements: map[string]*proto.EntitlementInfo{},
}
entitlements.BackfillFeatures(&features)
mockClient.setFeatures(features)
time.Sleep(handler.cfg.FeatureWatchInterval)
@@ -119,7 +111,6 @@ func TestFeaturesWatcher(t *testing.T) {
// test updating entitlements
features = proto.Features{
Kubernetes: true,
Entitlements: map[string]*proto.EntitlementInfo{
string(entitlements.ExternalAuditStorage): {Enabled: true},
string(entitlements.AccessLists): {Enabled: true},
@@ -127,16 +118,13 @@ func TestFeaturesWatcher(t *testing.T) {
string(entitlements.App): {Enabled: true},
string(entitlements.CloudAuditLogRetention): {Enabled: true},
},
AccessRequests: &proto.AccessRequestsFeature{},
}
entitlements.BackfillFeatures(&features)
mockClient.setFeatures(features)
time.Sleep(handler.cfg.FeatureWatchInterval)
synctest.Wait()
expected = &proto.Features{
Kubernetes: true,
Entitlements: map[string]*proto.EntitlementInfo{
string(entitlements.ExternalAuditStorage): {Enabled: true},
string(entitlements.AccessLists): {Enabled: true},
@@ -144,9 +132,7 @@ func TestFeaturesWatcher(t *testing.T) {
string(entitlements.App): {Enabled: true},
string(entitlements.CloudAuditLogRetention): {Enabled: true},
},
AccessRequests: &proto.AccessRequestsFeature{},
}
entitlements.BackfillFeatures(expected)
require.Equal(t, *expected, handler.GetClusterFeatures())
// stop watcher and ensure it stops updating features
@@ -154,13 +140,8 @@ func TestFeaturesWatcher(t *testing.T) {
synctest.Wait()
features = proto.Features{
Kubernetes: !features.Kubernetes,
App: !features.App,
DB: true,
Entitlements: map[string]*proto.EntitlementInfo{},
AccessRequests: &proto.AccessRequestsFeature{},
Entitlements: map[string]*proto.EntitlementInfo{},
}
entitlements.BackfillFeatures(&features)
mockClient.setFeatures(features)
notExpected := utils.CloneProtoMsg(&features)
+10 -27
View File
@@ -76,26 +76,10 @@ const cfg = {
isUsageBasedBilling: false,
hideInaccessibleFeatures: false,
customTheme: '',
/** @deprecated */
isTeam: false,
isStripeManaged: false,
hasQuestionnaire: false,
externalAuditStorage: false,
premiumSupport: false,
accessRequests: false,
/** @deprecated Use entitlements instead. */
trustedDevices: false,
oidc: false,
saml: false,
/** @deprecated Use entitlements instead. */
joinActiveSessions: false,
/** @deprecated Use entitlements instead. */
mobileDeviceManagement: false,
/** @deprecated Use entitlements instead. */
isIgsEnabled: false,
// isPolicyEnabled refers to the Teleport Policy product
isPolicyEnabled: false,
// sessionSummarizerEnabled refers to the AI session summary feature
sessionSummarizerEnabled: false,
@@ -114,20 +98,19 @@ const cfg = {
// see `getNonExactRoutes` for details about non-exact routes
nonExactRoutes: [],
// featureLimits define limits for features.
/** @deprecated Use entitlements instead. */
featureLimits: {
/** @deprecated Use entitlements instead. */
accessListCreateLimit: 0,
/** @deprecated Use entitlements instead. */
accessMonitoringMaxReportRangeLimit: 0,
/** @deprecated Use entitlements instead. */
AccessRequestMonthlyRequestLimit: 0,
},
// default entitlements to false
entitlements: defaultEntitlements,
/** @deprecated Use entitlements instead; remove in v20 */
accessRequests: false,
/** @deprecated Use entitlements instead; remove in v20 */
oidc: false,
/** @deprecated Use entitlements instead; remove in v20 */
saml: false,
// isPolicyEnabled refers to the Teleport Policy product
/** @deprecated Use entitlements instead; remove in v20 */
isPolicyEnabled: false,
ui: {
scrollbackLines: 1000,
showResources: 'requestable',