diff --git a/lib/web/apiserver.go b/lib/web/apiserver.go index bbc957e4de71f..91491831a6fb1 100644 --- a/lib/web/apiserver.go +++ b/lib/web/apiserver.go @@ -629,7 +629,7 @@ func NewHandler(cfg Config, opts ...HandlerOption) (*APIHandler, error) { // part[0] is empty space from leading slash "/" // part[1] is the prefix "v1" switch pathParts[2] { - case "webapi", "enterprise", "scripts", ".well-known", "workload-identity": + case "webapi", "enterprise", "scripts", ".well-known", "workload-identity", "web": http.StripPrefix(v1Prefix, h).ServeHTTP(w, r) return } @@ -1930,7 +1930,7 @@ func setEntitlementsWithLegacyLogic(webCfg *webclient.WebConfig, clusterFeatures // 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.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() { @@ -1944,7 +1944,7 @@ func setEntitlementsWithLegacyLogic(webCfg *webclient.WebConfig, clusterFeatures } // webCfg.: set equal to legacy feature value - webCfg.AccessRequests = clusterFeatures.GetAccessRequests().MonthlyRequestLimit > 0 + webCfg.AccessRequests = clusterFeatures.GetAccessRequests().GetMonthlyRequestLimit() > 0 webCfg.ExternalAuditStorage = clusterFeatures.GetExternalAuditStorage() webCfg.HideInaccessibleFeatures = clusterFeatures.GetFeatureHiding() webCfg.IsIGSEnabled = clusterFeatures.GetIdentityGovernance() diff --git a/lib/web/apiserver_test.go b/lib/web/apiserver_test.go index cd446223478e7..58c0d1132f3d2 100644 --- a/lib/web/apiserver_test.go +++ b/lib/web/apiserver_test.go @@ -3565,6 +3565,89 @@ func TestEndpointNotFoundHandling(t *testing.T) { } } +func TestKnownWebPathsWithAndWithoutV1Prefix(t *testing.T) { + t.Parallel() + const username = "test-user@example.com" + // Allow user to create tokens. + roleTokenCRD, err := types.NewRole(services.RoleNameForUser(username), types.RoleSpecV6{ + Allow: types.RoleConditions{ + Rules: []types.Rule{ + types.NewRule(types.KindToken, + []string{types.VerbCreate}), + }, + }, + }) + require.NoError(t, err) + + env := newWebPack(t, 1) + proxy := env.proxies[0] + pack := proxy.authPack(t, username, []types.Role{roleTokenCRD}) + + res, err := pack.clt.PostJSON(context.Background(), pack.clt.Endpoint("webapi", "token"), types.ProvisionTokenSpecV2{ + Roles: types.SystemRoles{types.RoleNode}, + }) + require.NoError(t, err) + + var responseToken nodeJoinToken + err = json.Unmarshal(res.Bytes(), &responseToken) + require.NoError(t, err) + + tt := []struct { + name string + endpoint string + }{ + { + name: "web path with prefix", + endpoint: "v1/web/config.js", + }, + { + name: "web path without prefix", + endpoint: "web/config.js", + }, + { + name: "webapi path with prefix", + endpoint: "v1/webapi/spiffe/bundle.json", + }, + { + name: "webapi path without prefix", + endpoint: "webapi/spiffe/bundle.json", + }, + { + name: ".well-known path with prefix", + endpoint: "v1/.well-known/jwks.json", + }, + { + name: ".well-known path without prefix", + endpoint: ".well-known/jwks.json", + }, + { + name: "workload-identity path with prefix", + endpoint: "v1/workload-identity/jwt-jwks.json", + }, + { + name: "workload-identity path without prefix", + endpoint: "workload-identity/jwt-jwks.json", + }, + { + name: "scripts path with prefix", + endpoint: fmt.Sprintf("v1/scripts/%s/install-node.sh", responseToken.ID), + }, + { + name: "scripts path without prefix", + endpoint: fmt.Sprintf("scripts/%s/install-node.sh", responseToken.ID), + }, + } + + for _, tc := range tt { + tc := tc + t.Run(tc.name, func(t *testing.T) { + _, err := pack.clt.Get(context.Background(), fmt.Sprintf("%s/%s", proxy.web.URL, tc.endpoint), url.Values{}) + + require.NoError(t, err) + }) + } +} + func TestInstallDatabaseScriptGeneration(t *testing.T) { const username = "test-user@example.com"