From c34e938a028b667074237abb7d614efe014b1858 Mon Sep 17 00:00:00 2001 From: Maxim Dietz Date: Fri, 20 Dec 2024 15:20:21 -0500 Subject: [PATCH] feat: Backend/type changes for Okta Integration enrolment improvements --- lib/web/apiserver.go | 2 +- lib/web/oidcidp.go | 2 + .../src/Notifications/Notification.tsx | 2 +- web/packages/teleport/src/config.ts | 16 +++++--- .../src/services/integrations/types.ts | 39 +++++++++++++++---- 5 files changed, 45 insertions(+), 16 deletions(-) diff --git a/lib/web/apiserver.go b/lib/web/apiserver.go index fef4f06dbeea1..723e26cc2a15c 100644 --- a/lib/web/apiserver.go +++ b/lib/web/apiserver.go @@ -1054,7 +1054,7 @@ func (h *Handler) bindDefaultEndpoints() { h.GET("/webapi/scripts/integrations/configure/gcp-workforce-saml.sh", h.WithLimiter(h.gcpWorkforceConfigScript)) // Okta integration endpoints. - h.GET("/.well-known/jwks-okta", h.WithLimiter(h.jwksOkta)) + h.GET(OktaJWKSURI, h.WithLimiter(h.jwksOkta)) // Azure OIDC integration endpoints h.GET("/webapi/scripts/integrations/configure/azureoidc.sh", h.WithLimiter(h.azureOIDCConfigure)) diff --git a/lib/web/oidcidp.go b/lib/web/oidcidp.go index 7b9c433f378f7..cf9ae3955d4e1 100644 --- a/lib/web/oidcidp.go +++ b/lib/web/oidcidp.go @@ -32,6 +32,8 @@ import ( const ( // OIDCJWKWURI is the relative path where the OIDC IdP JWKS is located OIDCJWKWURI = "/.well-known/jwks-oidc" + // OktaJWKSURI is the relative path where the Okta JWKS is located + OktaJWKSURI = "/.well-known/jwks-okta" ) // openidConfiguration returns the openid-configuration for setting up the AWS OIDC Integration diff --git a/web/packages/teleport/src/Notifications/Notification.tsx b/web/packages/teleport/src/Notifications/Notification.tsx index 5278bfcf22c84..550dc2c88bc99 100644 --- a/web/packages/teleport/src/Notifications/Notification.tsx +++ b/web/packages/teleport/src/Notifications/Notification.tsx @@ -98,7 +98,7 @@ export function Notification({ if (view === 'Unread' && notification.clicked) { // If this is a text content notification, the dialog should still be renderable. This is to prevent the text content dialog immediately disappearing // when trying to open an unread text notification, since clicking on the notification instantly marks it as read. - if (content.kind == 'text') { + if (content.kind === 'text') { return ( diff --git a/web/packages/teleport/src/config.ts b/web/packages/teleport/src/config.ts index a5d3661efee56..212bbba8bc648 100644 --- a/web/packages/teleport/src/config.ts +++ b/web/packages/teleport/src/config.ts @@ -199,8 +199,8 @@ const cfg = { kubernetes: '/web/cluster/:clusterId/kubernetes', headlessSso: `/web/headless/:requestId`, integrations: '/web/integrations', - integrationStatus: '/web/integrations/status/:type/:name', - integrationEnroll: '/web/integrations/new/:type?', + integrationStatus: '/web/integrations/status/:type/:name/:page?', + integrationEnroll: '/web/integrations/new/:type?/:page?', locks: '/web/locks', newLock: '/web/locks/new', requests: '/web/requests/:requestId?', @@ -558,12 +558,16 @@ const cfg = { return generatePath(cfg.routes.audit, { clusterId }); }, - getIntegrationEnrollRoute(type?: string) { - return generatePath(cfg.routes.integrationEnroll, { type }); + getIntegrationEnrollRoute(type?: string, page?: string) { + return generatePath(cfg.routes.integrationEnroll, { type, page }); }, - getIntegrationStatusRoute(type: PluginKind | IntegrationKind, name: string) { - return generatePath(cfg.routes.integrationStatus, { type, name }); + getIntegrationStatusRoute( + type: PluginKind | IntegrationKind, + name: string, + page?: string + ) { + return generatePath(cfg.routes.integrationStatus, { type, name, page }); }, getMsTeamsAppZipRoute(clusterId: string, plugin: string) { diff --git a/web/packages/teleport/src/services/integrations/types.ts b/web/packages/teleport/src/services/integrations/types.ts index 9e631c7caf506..b7f120aecc977 100644 --- a/web/packages/teleport/src/services/integrations/types.ts +++ b/web/packages/teleport/src/services/integrations/types.ts @@ -16,6 +16,7 @@ * along with this program. If not, see . */ +import { PluginStatusOkta } from 'teleport/services/integrations/oktaStatusTypes'; import { Label } from 'teleport/types'; import { ResourceLabel } from '../agents'; @@ -185,14 +186,21 @@ export type PluginStatus = { details?: D; }; -export type PluginSpec = - | PluginOktaSpec - | PluginSlackSpec - | PluginMattermostSpec - | PluginOpsgenieSpec - | PluginDatadogSpec - | PluginEmailSpec - | PluginMsTeamsSpec; +export type PluginNameToSpec = { + okta: PluginOktaSpec; + slack: PluginSlackSpec; + mattermost: PluginMattermostSpec; + opsgenie: PluginOpsgenieSpec; + datadog: PluginDatadogSpec; + email: PluginEmailSpec; + msteams: PluginMsTeamsSpec; + [key: string]: any; +}; + +export type PluginNameToDetails = { + okta: PluginStatusOkta; + [key: string]: any; +}; // PluginKind represents the type of the plugin // and should be the same value as defined in the backend (check master branch for the latest): @@ -240,6 +248,21 @@ export type PluginOktaSpec = { * the Okta org's base URL */ orgUrl: string; + + enableUserSync?: boolean; + enableAccessListSync?: boolean; + enableAppGroupSync?: boolean; + + /** + * contains currently configured credentials for the plugin + */ + credentialsInfo?: CredentialsInfo; +}; + +export type CredentialsInfo = { + hasSSMSToken?: boolean; + hasConfiguredOauthCredentials?: boolean; + hasSCIMToken?: boolean; }; export type PluginSlackSpec = {