diff --git a/README.md b/README.md index dac836a7f650f..0c5f9179477e4 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Here is why you might use Teleport: Teleport works with SSH, Kubernetes, databases, RDP, and web services. -* Architecture: https://goteleport.com/docs/architecture/ +* Architecture: https://goteleport.com/docs/reference/architecture/architecture * Getting Started: https://goteleport.com/docs/getting-started/
diff --git a/docs/img/sso/onelogin/onelogin-saml-1a.png b/docs/img/sso/onelogin/onelogin-saml-1a.png index 61fe83b36f4b0..9de9aa229b522 100644 Binary files a/docs/img/sso/onelogin/onelogin-saml-1a.png and b/docs/img/sso/onelogin/onelogin-saml-1a.png differ diff --git a/docs/img/sso/onelogin/teleport.png b/docs/img/sso/onelogin/teleport.png index a8e29af374473..244c59b0d8260 100644 Binary files a/docs/img/sso/onelogin/teleport.png and b/docs/img/sso/onelogin/teleport.png differ diff --git a/docs/img/sso/onelogin/teleportlogo@2x.png b/docs/img/sso/onelogin/teleportlogo@2x.png index 7d83ede01ca40..c019d21091095 100644 Binary files a/docs/img/sso/onelogin/teleportlogo@2x.png and b/docs/img/sso/onelogin/teleportlogo@2x.png differ diff --git a/docs/pages/admin-guides/management/admin/troubleshooting.mdx b/docs/pages/admin-guides/management/admin/troubleshooting.mdx index afe00fccc1d02..2a22c219cc523 100644 --- a/docs/pages/admin-guides/management/admin/troubleshooting.mdx +++ b/docs/pages/admin-guides/management/admin/troubleshooting.mdx @@ -149,7 +149,8 @@ through the [Teleport support portal](https://support.goteleport.com). If you need help, please ask on our [community forum](https://github.com/gravitational/teleport/discussions). You can also open an [issue on GitHub](https://github.com/gravitational/teleport/issues). -For more information about custom features, or to try the [self-hosted Enterprise edition](../../deploy-a-cluster/deploy-a-cluster.mdx) of Teleport, reach out to us at [sales](https://goteleport.com/signup/enterprise/). +For more information about Enterprise features reach out to [the Teleport sales team](https://goteleport.com/signup/enterprise/). +You can also sign up for a [free trial](https://goteleport.com/signup) of Teleport Enterprise. diff --git a/docs/pages/core-concepts.mdx b/docs/pages/core-concepts.mdx index c7afd7338db53..011377dbe4285 100644 --- a/docs/pages/core-concepts.mdx +++ b/docs/pages/core-concepts.mdx @@ -39,7 +39,7 @@ Read our guides to how [authorization](reference/architecture/authorization.mdx) ### Teleport Proxy Service The **Teleport Proxy Service** allows for secure access to resources in your -infrastructure from the public internet without the need for a VPN. +infrastructure from the public internet without the need for a VPN. It establishes reverse tunnels to the **Teleport Auth Service** and **Teleport Services**, which can run in private networks. This means that, in the Proxy @@ -47,7 +47,7 @@ Service's minimal configuration, you can expose only port `443` to the internet and run the rest of your infrastructure in private networks. You can also configure clients to bypass Proxy Service instances and connect to -resources with Teleport-issued certificates directly. +resources with Teleport-issued certificates directly. Read our guide to [how the Teleport Proxy Service works](reference/architecture/proxy.mdx). @@ -73,7 +73,7 @@ Service](./enroll-resources/application-access/introduction.mdx). ### Teleport Database Service Proxies TCP traffic in the native protocols of popular databases, including -PostgreSQL and MySQL. +PostgreSQL and MySQL. Read more about the [Teleport Database Service](./enroll-resources/database-access/database-access.mdx). @@ -92,7 +92,7 @@ Proxies HTTP traffic to the Kubernetes API server. Read more about the [Teleport Kubernetes Service](./enroll-resources/kubernetes-access/introduction.mdx) -### Teleport SSH Service +### Teleport SSH Service An SSH server implementation that allows users to execute commands on remote machines while taking advantage of Teleport's built-in access controls, @@ -104,7 +104,7 @@ Read more about the [Teleport SSH Service](./enroll-resources/server-access/intr Allows machines and services—called bot users—to communicate securely with resources in your infrastructure by automatically provisioning and renewing -credentials. +credentials. Bot users can connect to resources in your infrastructure without relying on static credentials (e.g., certificates and private keys) that become more @@ -131,7 +131,7 @@ on GitHub. You can find a detailed comparison of the features available in each Teleport edition in [Frequently Asked -Questions](./faq.mdx#how-is-open-source-different-from-enterprise). +Questions](./faq.mdx#how-is-teleports-community-edition-different-from-enterprise). ### Teleport Enterprise Cloud @@ -193,7 +193,7 @@ Ultimately, a Teleport user is the subject of a certificate issued by the **Teleport Auth Service**. The Auth Service verifies that a client or service attempting to connect has a valid Teleport-issued certificate. It then uses the subject of the certificate—including its username and Teleport roles—to -authorize the user. +authorize the user. Read more about [local users](reference/access-controls/authentication.mdx) and how [SSO authentication works in Teleport](admin-guides/access-controls/sso/sso.mdx). @@ -201,21 +201,21 @@ authentication works in Teleport](admin-guides/access-controls/sso/sso.mdx). ### Authentication connector An authentication connector is a **configuration resource** that allows users to -authenticate to Teleport via a Single Sign-On (SSO) solution. +authenticate to Teleport via a Single Sign-On (SSO) solution. See our guide to [Authentication Options](reference/access-controls/authentication.mdx). ### Trusted clusters -Teleport allows you to configure a **trusted cluster relationship** between a -**root cluster** and one or more **leaf clusters** that trust the root cluster -certificate authority. The trust relationship between the root and leaf clusters -enables users authenticated in the root cluster to access resources +Teleport allows you to configure a **trusted cluster relationship** between a +**root cluster** and one or more **leaf clusters** that trust the root cluster +certificate authority. The trust relationship between the root and leaf clusters +enables users authenticated in the root cluster to access resources in leaf cluster. The root and leaf cluster operate independently with their own users, roles, and resources, but the trust relationship allows users with certain roles in the root cluster to be mapped to roles and permissions defined in the leaf cluster. For more information about how to configure a trust relationship between clusters, -see [Configure Trusted Clusters](admin-guides/management/admin/trustedclusters.mdx). -For an overview of the architecture used in a trusted cluster relationship, see +see [Configure Trusted Clusters](admin-guides/management/admin/trustedclusters.mdx). +For an overview of the architecture used in a trusted cluster relationship, see [Trusted Cluster Architecture](reference/architecture/trustedclusters.mdx). diff --git a/docs/pages/faq.mdx b/docs/pages/faq.mdx index 20135fb639467..2c9bd58aa7d8a 100644 --- a/docs/pages/faq.mdx +++ b/docs/pages/faq.mdx @@ -11,32 +11,24 @@ Fortune 500 companies. It has been through several security audits from nationally recognized technology security companies, so we are comfortable with the stability of Teleport from a security perspective. -## Can Teleport be deployed in agentless mode? - -Yes. All Teleport services support agentless mode, where the service proxies -traffic to an upstream infrastructure resource not available on `localhost`. +## Can I connect to nodes behind a firewall? -With Teleport in agentless mode, you can easily control access to SSH servers, -Kubernetes clusters, desktops, databases, and internal applications without -running any additional software on your servers. Agentless mode supports session -recordings and audit logs for deep understanding into user behavior. +Yes, Teleport supports reverse SSH tunnels out of the box. To configure +behind-firewall clusters, see [Configure Trusted Clusters](admin-guides/management/admin/trustedclusters.mdx). -For capabilities such as kernel-level logging and user provisioning, we -recommend Teleport as a drop in replacement for OpenSSH. Since Teleport replaces -the OpenSSH agent while preserving OpenSSH's functionality, you get more -functionality without a net addition of an agent on your system. +## How is Teleport's Community Edition different from Enterprise? -## Can I use OpenSSH with a Teleport cluster? +Teleport provides two editions: -Yes, this question comes up often and is related to the previous one. Take a -look at [Using OpenSSH Guide](enroll-resources/server-access/openssh/openssh-agentless.mdx). +- Teleport Enterprise +- Teleport Community Edition -## Can I connect to nodes behind a firewall? +Here is a detailed breakdown of the differences between Teleport's editions. -Yes, Teleport supports reverse SSH tunnels out of the box. To configure -behind-firewall clusters, see [Configure Trusted Clusters](admin-guides/management/admin/trustedclusters.mdx). +(!docs/pages/includes/edition-comparison.mdx!) ## Should we use Teleport Enterprise or Teleport Community Edition for connecting resources to our Teleport cluster? + (!docs/pages/includes/ent-vs-community-faq.mdx!) ## Can individual agents create reverse tunnels to the Proxy Service without creating a new cluster? @@ -54,6 +46,26 @@ Yes, Teleport supports tunnel multiplexing on a single port. Set the setting in the `proxy_service` configuration. Teleport will automatically use multiplexing with that configuration. +## Can Teleport be deployed in agentless mode? + +Yes. All Teleport services support agentless mode, where the service proxies +traffic to an upstream infrastructure resource not available on `localhost`. + +With Teleport in agentless mode, you can easily control access to SSH servers, +Kubernetes clusters, desktops, databases, and internal applications without +running any additional software on your servers. Agentless mode supports session +recordings and audit logs for deep understanding into user behavior. + +For capabilities such as kernel-level logging and user provisioning, we +recommend Teleport as a drop in replacement for OpenSSH. Since Teleport replaces +the OpenSSH agent while preserving OpenSSH's functionality, you get more +functionality without a net addition of an agent on your system. + +## Can I use OpenSSH with a Teleport cluster? + +Yes, this question comes up often and is related to the previous one. Take a +look at [Using OpenSSH Guide](enroll-resources/server-access/openssh/openssh-agentless.mdx). + ## Can I copy files from one Teleport node to another? Yes, Teleport supports [Headless WebAuthn authentication](admin-guides/access-controls/guides/headless.mdx), @@ -65,7 +77,7 @@ are not logged in to Teleport or may not have access to a browser. If your host machine is joined to an Active Directory domain, you might find user lookups take a lot longer than you expect. The number of Active Directory accounts that must be scanned to perform a user lookup can cause tsh to hang waiting to get information about the current user. -To fix this issue, you can use environment variables to set default account information for your +To fix this issue, you can use environment variables to set default account information for your Teleport user. If you are experiencing long lookup times on Windows, do the following: - Either set the `TELEPORT_USER` environment variable or set the `--user` flag to the name of your Teleport user. @@ -75,18 +87,6 @@ Teleport user. If you are experiencing long lookup times on Windows, do the foll You can set these environment variables globally in Windows so that you don't have to set them every time you run `tsh`. -## How is Open Source different from Enterprise? - -Teleport provides three editions: - -- Teleport Enterprise -- Teleport Enterprise Cloud -- Teleport Community Edition - -Here is a detailed breakdown of the differences between Teleport's editions. - -(!docs/pages/includes/edition-comparison.mdx!) - ## Which version of Teleport is supported? Teleport releases a new major version approximately every 4 months, and provides @@ -121,6 +121,19 @@ Please refer to our [Networking](./reference/networking.mdx) guide. Teleport offers this feature for the Enterprise (Cloud) and Enterprise (Self-Hosted) versions of Teleport. +## Why do changes to a user's role set only take effect on the log next login? + +A Teleport user's assigned roles are embedded in the client certificate they +receive upon logging on. This certificate remains valid and can be used until +its expiry, even if the user's role set has changed. + +To get a new certificate with the new role set, the user will need to log out +and log back in. + +Revocation of Teleport access should be done with Teleport's +[session and identity locks](./admin-guides/access-controls/guides/locking.mdx), +not by removing roles. + ## Does Teleport support provisioning users via SCIM? Teleport supports [SCIM](https://scim.cloud/) provisioning for Okta via the @@ -144,7 +157,10 @@ Service and Auth Service, as well as agents running other Teleport Services. Teleport requires a minimum of TLS version 1.2. -This means that when applications and clients establish or accept TLS connections with Teleport processes, they must use TLS 1.2 or a higher protocol version. Teleport enforces this requirement in all operations that involve TLS connections. +This means that when applications and clients establish or accept TLS +connections with Teleport processes, they must use TLS 1.2 or a higher protocol +version. Teleport enforces this requirement in all operations that involve TLS +connections. ## Can I suppress warnings about available upgrades? diff --git a/docs/pages/reference/helm-reference/teleport-cluster.mdx b/docs/pages/reference/helm-reference/teleport-cluster.mdx index 8708ba1a9e36e..5c1caa908a96c 100644 --- a/docs/pages/reference/helm-reference/teleport-cluster.mdx +++ b/docs/pages/reference/helm-reference/teleport-cluster.mdx @@ -606,6 +606,22 @@ $ kubectl --namespace teleport create secret generic license --from-file=/path/t enterprise: true ``` +### `licenseSecretName` + +| Type | Default value | +|----------|----------------| +| `string` | `license` | + +`licenseSecretName` controls Kubernetes secret name for the Enterprise license. + +By using this value you will update the Kubernetes volume specification to mount Secret based volume to the container using custom name. + +`values.yaml` example: + + ```yaml + licenseSecretName: enterprise-license + ``` + ## `installCRDs` | Type | Default value | diff --git a/examples/README.md b/examples/README.md index 0fed255d5c9cf..9563f5e06bf6d 100644 --- a/examples/README.md +++ b/examples/README.md @@ -1,9 +1,5 @@ # Examples -## Configuration Examples - -* [local-cluster](https://github.com/gravitational/teleport/tree/master/examples/local-cluster) : Sample configuration of a 3-node Teleport cluster using just a single machine - ## Daemon Configuration * [systemd](https://github.com/gravitational/teleport/tree/master/examples/systemd) : Service file for systemd @@ -13,7 +9,6 @@ * [AWS: CloudFormation](https://github.com/gravitational/teleport/tree/master/examples/aws/cloudformation#aws-cloudformation-based-provisioning-example) : CloudFormation templates as an example of how to setup HA Teleport in AWS using our AMIs. * [AWS: Terraform](https://github.com/gravitational/teleport/tree/master/examples/aws/terraform#terraform-based-provisioning-example-amazon-single-ami) : Terraform specifies example provisioning script for Teleport auth, proxy and nodes in HA mode. -* [AWS: EKS. External Link](https://aws.amazon.com/blogs/opensource/authenticating-eks-github-credentials-teleport/) ## Kubernetes - Helm Charts @@ -33,4 +28,4 @@ ### Trusted Cluster * [Trusted Cluster Resource](https://github.com/gravitational/teleport/blob/master/examples/resources/trusted_cluster.yaml) -* [Trusted Cluster Resource - With RBAC (Enterprise Only)](https://github.com/gravitational/teleport/blob/master/examples/resources/trusted_cluster_enterprise.yaml) \ No newline at end of file +* [Trusted Cluster Resource - With RBAC (Enterprise Only)](https://github.com/gravitational/teleport/blob/master/examples/resources/trusted_cluster_enterprise.yaml) diff --git a/examples/chart/teleport-cluster/.lint/auth-enterprise-license.yaml b/examples/chart/teleport-cluster/.lint/auth-enterprise-license.yaml new file mode 100644 index 0000000000000..a86c5261469fc --- /dev/null +++ b/examples/chart/teleport-cluster/.lint/auth-enterprise-license.yaml @@ -0,0 +1,4 @@ +clusterName: helm-lint +enterprise: true +licenseSecretName: enterprise-license + diff --git a/examples/chart/teleport-cluster/templates/auth/deployment.yaml b/examples/chart/teleport-cluster/templates/auth/deployment.yaml index 7dc0901694fdc..aee44b69befe3 100644 --- a/examples/chart/teleport-cluster/templates/auth/deployment.yaml +++ b/examples/chart/teleport-cluster/templates/auth/deployment.yaml @@ -266,7 +266,7 @@ spec: {{- if $auth.enterprise }} - name: license secret: - secretName: "license" + secretName: {{ $auth.licenseSecretName | quote }} {{- end }} {{- if and ($auth.gcp.credentialSecretName) (eq $auth.chartMode "gcp") }} - name: gcp-credentials diff --git a/examples/chart/teleport-cluster/templates/auth/predeploy_job.yaml b/examples/chart/teleport-cluster/templates/auth/predeploy_job.yaml index 860c790645fa4..e75c0f20a55e8 100644 --- a/examples/chart/teleport-cluster/templates/auth/predeploy_job.yaml +++ b/examples/chart/teleport-cluster/templates/auth/predeploy_job.yaml @@ -84,7 +84,7 @@ spec: {{- if .Values.enterprise }} - name: license secret: - secretName: "license" + secretName: {{ .Values.licenseSecretName | quote }} {{- end }} {{- if and (.Values.gcp.credentialSecretName) (eq .Values.chartMode "gcp") }} - name: gcp-credentials diff --git a/examples/chart/teleport-cluster/tests/auth_deployment_test.yaml b/examples/chart/teleport-cluster/tests/auth_deployment_test.yaml index 6f158540d23a7..49946a9500085 100644 --- a/examples/chart/teleport-cluster/tests/auth_deployment_test.yaml +++ b/examples/chart/teleport-cluster/tests/auth_deployment_test.yaml @@ -215,6 +215,30 @@ tests: secret: secretName: license + - it: should use enterprise image and mount license with custom secret name when enterprise is set in values + template: auth/deployment.yaml + set: + clusterName: helm-lint.example.com + enterprise: true + licenseSecretName: enterprise-license + teleportVersionOverride: 12.2.1 + asserts: + - equal: + path: spec.template.spec.containers[0].image + value: public.ecr.aws/gravitational/teleport-ent-distroless:12.2.1 + - contains: + path: spec.template.spec.containers[0].volumeMounts + content: + mountPath: /var/lib/license + name: "license" + readOnly: true + - contains: + path: spec.template.spec.volumes + content: + name: license + secret: + secretName: enterprise-license + - it: should use OSS image and not mount license when enterprise is not set in values template: auth/deployment.yaml set: diff --git a/examples/chart/teleport-cluster/values.schema.json b/examples/chart/teleport-cluster/values.schema.json index 2c4a6da0c5e73..6e3796ca8c9e5 100644 --- a/examples/chart/teleport-cluster/values.schema.json +++ b/examples/chart/teleport-cluster/values.schema.json @@ -286,6 +286,11 @@ "type": "boolean", "default": false }, + "licenseSecretName": { + "$id": "#/properties/licenseSecretName", + "type": "string", + "default": "license" + }, "installCRDs": { "$id": "#/properties/installCRDs", "type": "boolean" diff --git a/examples/chart/teleport-cluster/values.yaml b/examples/chart/teleport-cluster/values.yaml index 526f1ed85518b..bd34b5c57cae4 100644 --- a/examples/chart/teleport-cluster/values.yaml +++ b/examples/chart/teleport-cluster/values.yaml @@ -245,7 +245,8 @@ acmeURI: "" # You will need to download your Enterprise license from the Teleport dashboard and create a secret to use this: # kubectl -n ${TELEPORT_NAMESPACE?} create secret generic license --from-file=/path/to/downloaded/license.pem enterprise: false - +# Override default Enterprise license name +licenseSecretName: "license" # CRDs are installed by default when the operator is enabled. This manual override allows to disable CRD installation # when deploying multiple releases in the same cluster. # installCRDs: diff --git a/integration/hostuser_test.go b/integration/hostuser_test.go index fca40cc9f8481..66e5dee2114c9 100644 --- a/integration/hostuser_test.go +++ b/integration/hostuser_test.go @@ -499,6 +499,28 @@ func TestRootHostUsers(t *testing.T) { require.NoError(t, err) require.False(t, hasExpirations) }) + + t.Run("Test migrate unmanaged user", func(t *testing.T) { + t.Cleanup(func() { cleanupUsersAndGroups([]string{testuser}, []string{types.TeleportKeepGroup}) }) + + users := srv.NewHostUsers(context.Background(), presence, "host_uuid") + _, err := host.UserAdd(testuser, nil, "", "", "") + require.NoError(t, err) + + closer, err := users.UpsertUser(testuser, services.HostUsersInfo{Mode: types.CreateHostUserMode_HOST_USER_MODE_KEEP, Groups: []string{types.TeleportKeepGroup}}) + require.NoError(t, err) + require.Nil(t, closer) + + u, err := user.Lookup(testuser) + require.NoError(t, err) + + gids, err := u.GroupIds() + require.NoError(t, err) + + keepGroup, err := user.LookupGroup(types.TeleportKeepGroup) + require.NoError(t, err) + require.Contains(t, gids, keepGroup.Gid) + }) } type hostUsersBackendWithExp struct { diff --git a/lib/auth/desktop.go b/lib/auth/desktop.go index f730c3e7c3610..664a055eb7846 100644 --- a/lib/auth/desktop.go +++ b/lib/auth/desktop.go @@ -71,8 +71,13 @@ func (a *Server) GenerateWindowsDesktopCert(ctx context.Context, req *proto.Wind NotAfter: a.clock.Now().UTC().Add(req.TTL.Get()), ExtraExtensions: csr.Extensions, KeyUsage: x509.KeyUsageDigitalSignature, - // CRL is required for Windows smartcard certs. - CRLDistributionPoints: []string{req.CRLEndpoint}, + } + + // CRL Distribution Points (CDP) are required for Windows smartcard certs + // for users wanting to RDP. They are not required for the service account + // cert that Teleport itself uses to authenticate for LDAP. + if req.CRLEndpoint != "" { + certReq.CRLDistributionPoints = []string{req.CRLEndpoint} } limitExceeded, err := a.desktopsLimitExceeded(ctx) diff --git a/lib/auth/windows/ldap.go b/lib/auth/windows/ldap.go index 4970500c34628..195dd14f67606 100644 --- a/lib/auth/windows/ldap.go +++ b/lib/auth/windows/ldap.go @@ -184,9 +184,9 @@ func convertLDAPError(err error) error { return trace.ConnectionProblem(err, "network error") case ldap.LDAPResultOperationsError: if strings.Contains(err.Error(), "successful bind must be completed") { - return trace.AccessDenied( - "the LDAP server did not accept Teleport's client certificate, " + - "has the Teleport CA been imported correctly?") + return trace.NewAggregate(trace.AccessDenied( + "the LDAP server did not accept Teleport's client certificate, "+ + "has the Teleport CA been imported correctly?"), err) } case ldap.LDAPResultEntryAlreadyExists: return trace.AlreadyExists("LDAP object already exists: %v", err) diff --git a/lib/auth/windows/windows.go b/lib/auth/windows/windows.go index 5b198833410b5..dcf20188469bd 100644 --- a/lib/auth/windows/windows.go +++ b/lib/auth/windows/windows.go @@ -128,19 +128,26 @@ func getCertRequest(req *GenerateCredentialsRequest) (*certRequest, error) { return nil, trace.Wrap(err) } csrPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE REQUEST", Bytes: csrBytes}) - // Note: this CRL DN may or may not be the same DN published in updateCRL. - // - // There can be multiple AD domains connected to Teleport. Each - // windows_desktop_service is connected to a single AD domain and publishes - // CRLs in it. Each service can also handle RDP connections for a different - // domain, with the assumption that some other windows_desktop_service - // published a CRL there. - crlDN := crlDN(req.ClusterName, req.LDAPConfig, req.CAType) - return &certRequest{ - csrPEM: csrPEM, - crlEndpoint: fmt.Sprintf("ldap:///%s?certificateRevocationList?base?objectClass=cRLDistributionPoint", crlDN), - keyDER: keyDER, - }, nil + cr := &certRequest{ + csrPEM: csrPEM, + keyDER: keyDER, + } + + if !req.OmitCDP { + // Note: this CRL DN may or may not be the same DN published in updateCRL. + // + // There can be multiple AD domains connected to Teleport. Each + // windows_desktop_service is connected to a single AD domain and publishes + // CRLs in it. Each service can also handle RDP connections for a different + // domain, with the assumption that some other windows_desktop_service + // published a CRL there. + crlDN := crlDN(req.ClusterName, req.LDAPConfig, req.CAType) + + // TODO(zmb3) consider making Teleport itself the CDP (via HTTP) instead of LDAP + cr.crlEndpoint = fmt.Sprintf("ldap:///%s?certificateRevocationList?base?objectClass=cRLDistributionPoint", crlDN) + } + + return cr, nil } // AuthInterface is a subset of auth.ClientI @@ -181,6 +188,11 @@ type GenerateCredentialsRequest struct { CreateUser bool // Groups are groups that user should be member of Groups []string + + // OmitCDP can be used to prevent Teleport from issuing certs with a + // CRL Distribution Point (CDP). CDPs are required in user certificates + // for RDP, but they can be omitted for certs that are used for LDAP binds. + OmitCDP bool } // GenerateWindowsDesktopCredentials generates a private key / certificate pair for the given diff --git a/lib/automaticupgrades/version/basichttp.go b/lib/automaticupgrades/version/basichttp.go index 849ddc86108df..29bea8e325861 100644 --- a/lib/automaticupgrades/version/basichttp.go +++ b/lib/automaticupgrades/version/basichttp.go @@ -47,7 +47,7 @@ func (b *basicHTTPVersionClient) Get(ctx context.Context) (string, error) { versionURL := b.baseURL.JoinPath(constants.VersionPath) body, err := b.client.GetContent(ctx, *versionURL) if err != nil { - return "", trace.Wrap(err) + return "", trace.Wrap(err, "failed to get version from %s", versionURL) } response := string(body) if response == constants.NoVersion { diff --git a/lib/client/api.go b/lib/client/api.go index 4337bcd241632..81a482072617c 100644 --- a/lib/client/api.go +++ b/lib/client/api.go @@ -5313,9 +5313,6 @@ func parseMFAMode(in string) (wancli.AuthenticatorAttachment, error) { // NewKubernetesServiceClient connects to the proxy and returns an authenticated gRPC // client to the Kubernetes service. func (tc *TeleportClient) NewKubernetesServiceClient(ctx context.Context, clusterName string) (kubeproto.KubeServiceClient, error) { - if !tc.TLSRoutingEnabled { - return nil, trace.BadParameter("kube service is not supported if TLS routing is not enabled") - } // get tlsConfig to dial to proxy. tlsConfig, err := tc.LoadTLSConfig() if err != nil { diff --git a/lib/srv/desktop/windows_server.go b/lib/srv/desktop/windows_server.go index d80c0dd2470b6..44e2ebd148d9a 100644 --- a/lib/srv/desktop/windows_server.go +++ b/lib/srv/desktop/windows_server.go @@ -443,6 +443,7 @@ func (s *WindowsService) tlsConfigForLDAP() (*tls.Config, error) { domain: s.cfg.Domain, ttl: windowsDesktopServiceCertTTL, activeDirectorySID: s.cfg.SID, + omitCDP: true, }) if err != nil { return nil, trace.Wrap(err) @@ -1226,7 +1227,8 @@ type generateCredentialsRequest struct { // createUser specifies if Windows user should be created if missing createUser bool // groups are groups that user should be member of - groups []string + groups []string + omitCDP bool } // generateCredentials generates a private key / certificate pair for the given @@ -1254,6 +1256,7 @@ func (s *WindowsService) generateCredentials(ctx context.Context, request genera AuthClient: s.cfg.AuthClient, CreateUser: request.createUser, Groups: request.groups, + OmitCDP: request.omitCDP, }) } diff --git a/lib/srv/regular/sshserver.go b/lib/srv/regular/sshserver.go index 6500637dadf6d..44e9f05789206 100644 --- a/lib/srv/regular/sshserver.go +++ b/lib/srv/regular/sshserver.go @@ -2378,8 +2378,18 @@ func (s *Server) handleTCPIPForwardRequest(ctx context.Context, ccx *sshutils.Co return trace.Wrap(err) } - // Set the src addr again since it may have been updated with a new port. - scx.SrcAddr = listener.Addr().String() + // If the client didn't request a specific port, the chosen port needs to + // be reported back. + srcHost, _, err := sshutils.SplitHostPort(scx.SrcAddr) + if err != nil { + return trace.Wrap(err) + } + _, listenPort, err := sshutils.SplitHostPort(listener.Addr().String()) + if err != nil { + return trace.Wrap(err) + } + scx.SrcAddr = sshutils.JoinHostPort(srcHost, listenPort) + event := scx.GetPortForwardEvent() if err := s.EmitAuditEvent(ctx, &event); err != nil { s.Logger.WithError(err).Warn("Failed to emit audit event.") diff --git a/lib/srv/regular/sshserver_test.go b/lib/srv/regular/sshserver_test.go index 54ac1b06d08bd..800ef30531b04 100644 --- a/lib/srv/regular/sshserver_test.go +++ b/lib/srv/regular/sshserver_test.go @@ -19,7 +19,6 @@ package regular import ( - "bytes" "context" "encoding/json" "fmt" @@ -711,40 +710,63 @@ func TestDirectTCPIP(t *testing.T) { // "tcpip-forward" request and do remote port forwarding. func TestTCPIPForward(t *testing.T) { t.Parallel() - f := newFixtureWithoutDiskBasedLogging(t) - - // Request a listener from the server. - listener, err := f.ssh.clt.Listen("tcp", "127.0.0.1:0") + hostname, err := os.Hostname() require.NoError(t, err) + tests := []struct { + name string + listenAddr string + }{ + { + name: "localhost", + listenAddr: "localhost:0", + }, + { + name: "ip address", + listenAddr: "127.0.0.1:0", + }, + { + name: "hostname", + listenAddr: hostname + ":0", + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + f := newFixtureWithoutDiskBasedLogging(t) - // Start up a test server that uses the port forwarded listener. - ts := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - fmt.Fprintln(w, "hello, world") - })) - t.Cleanup(ts.Close) - ts.Listener = listener - ts.Start() + // Request a listener from the server. + listener, err := f.ssh.clt.Listen("tcp", tc.listenAddr) + require.NoError(t, err) - // Dial the test server over the SSH connection. - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - t.Cleanup(cancel) - req, err := http.NewRequestWithContext(ctx, http.MethodGet, ts.URL, &bytes.Buffer{}) - require.NoError(t, err) - client := &http.Client{} - resp, err := client.Do(req) - require.NoError(t, err) - t.Cleanup(func() { - require.NoError(t, resp.Body.Close()) - }) + // Start up a test server that uses the port forwarded listener. + ts := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + fmt.Fprintln(w, "hello, world") + })) + t.Cleanup(ts.Close) + ts.Listener = listener + ts.Start() + + // Dial the test server over the SSH connection. + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + t.Cleanup(cancel) + req, err := http.NewRequestWithContext(ctx, http.MethodGet, ts.URL, nil) + require.NoError(t, err) + resp, err := ts.Client().Do(req) + require.NoError(t, err) + t.Cleanup(func() { + require.NoError(t, resp.Body.Close()) + }) - // Make sure the response is what was expected. - body, err := io.ReadAll(resp.Body) - require.NoError(t, err) - require.Equal(t, []byte("hello, world\n"), body) + // Make sure the response is what was expected. + body, err := io.ReadAll(resp.Body) + require.NoError(t, err) + require.Equal(t, []byte("hello, world\n"), body) + }) + } t.Run("SessionJoinPrincipal cannot use tcpip-forward", func(t *testing.T) { // Ensure that ssh client using SessionJoinPrincipal as Login, cannot // connect using "tcpip-forward". + f := newFixtureWithoutDiskBasedLogging(t) ctx := context.Background() cliUsingSessionJoin := f.newSSHClient(ctx, t, &user.User{Username: teleport.SSHSessionJoinPrincipal}) _, err := cliUsingSessionJoin.Listen("tcp", "127.0.0.1:0") diff --git a/lib/srv/usermgmt.go b/lib/srv/usermgmt.go index f5b3bd187c690..6da3b87eca912 100644 --- a/lib/srv/usermgmt.go +++ b/lib/srv/usermgmt.go @@ -672,6 +672,7 @@ func (u *HostUserManagement) getHostUser(username string) (*HostUser, error) { return &HostUser{ Name: username, UID: usr.Uid, + GID: usr.Gid, Home: usr.HomeDir, Groups: groups, }, trace.NewAggregate(groupErrs...) diff --git a/lib/sshutils/tcpip.go b/lib/sshutils/tcpip.go index 4b92efb0177ce..55ac4ea981cf3 100644 --- a/lib/sshutils/tcpip.go +++ b/lib/sshutils/tcpip.go @@ -101,6 +101,7 @@ func StartRemoteListener(ctx context.Context, sshConn channelOpener, srcAddr str dstHost, dstPort, err := SplitHostPort(conn.RemoteAddr().String()) if err != nil { + conn.Close() logger.WithError(err).Warn("failed to parse addr") return } @@ -112,6 +113,7 @@ func StartRemoteListener(ctx context.Context, sshConn channelOpener, srcAddr str OrigPort: dstPort, } if err := req.CheckAndSetDefaults(); err != nil { + conn.Close() logger.WithError(err).Warn("failed to create forwarded tcpip request") return } @@ -119,6 +121,7 @@ func StartRemoteListener(ctx context.Context, sshConn channelOpener, srcAddr str ch, rch, err := sshConn.OpenChannel(teleport.ChanForwardedTCPIP, reqBytes) if err != nil { + conn.Close() logger.WithError(err).Warn("failed to open channel") continue } diff --git a/lib/tbot/config/migrate_test.go b/lib/tbot/config/migrate_test.go index 31c3421867a1a..b46cb72ffdb04 100644 --- a/lib/tbot/config/migrate_test.go +++ b/lib/tbot/config/migrate_test.go @@ -304,7 +304,7 @@ destinations: }, // Backwards compat with guides { - name: "backwards compat with https://goteleport.com/docs/machine-id/guides/jenkins/", + name: "backwards compat with https://goteleport.com/docs/enroll-resources/machine-id/deployment/jenkins/", input: ` auth_server: "auth.example.com:3025" onboarding: diff --git a/lib/utils/hostid/hostid_unix.go b/lib/utils/hostid/hostid_unix.go index b5334e641c232..df91eec76b83d 100644 --- a/lib/utils/hostid/hostid_unix.go +++ b/lib/utils/hostid/hostid_unix.go @@ -27,6 +27,7 @@ import ( "github.com/google/uuid" "github.com/gravitational/trace" + "github.com/gravitational/teleport/api/utils/retryutils" "github.com/gravitational/teleport/lib/utils" ) @@ -49,6 +50,16 @@ func ReadOrCreateFile(dataDir string) (string, error) { hostUUIDFileLock := GetPath(dataDir) + ".lock" const iterationLimit = 3 + backoff, err := retryutils.NewRetryV2(retryutils.RetryV2Config{ + First: 100 * time.Millisecond, + Driver: retryutils.NewLinearDriver(100 * time.Millisecond), + Max: time.Second, + Jitter: retryutils.NewFullJitter(), + }) + if err != nil { + return "", trace.Wrap(err) + } + for i := 0; i < iterationLimit; i++ { if read, err := ReadFile(dataDir); err == nil { return read, nil @@ -57,7 +68,7 @@ func ReadOrCreateFile(dataDir string) (string, error) { } // Checking error instead of the usual uuid.New() in case uuid generation - // fails due to not enough randomness. It's been known to happen happen when + // fails due to not enough randomness. It's been known to happen when // Teleport starts very early in the node initialization cycle and /dev/urandom // isn't ready yet. rawID, err := uuid.NewRandom() @@ -91,12 +102,14 @@ func ReadOrCreateFile(dataDir string) (string, error) { id, err := writeFile(rawID.String()) if err != nil { if errors.Is(err, utils.ErrUnsuccessfulLockTry) { - time.Sleep(100 * time.Millisecond) + backoff.Inc() + <-backoff.After() continue } return "", trace.Wrap(err) } + backoff.Reset() return id, nil } diff --git a/lib/web/scripts/node-join/install.sh b/lib/web/scripts/node-join/install.sh index f1d82b2b3be58..3151fb5c89885 100755 --- a/lib/web/scripts/node-join/install.sh +++ b/lib/web/scripts/node-join/install.sh @@ -230,15 +230,33 @@ log_important() { log_cleanup_message() { log_only "This script does not overwrite any existing settings or Teleport installations." log_only "Please clean up by running any of the following steps as necessary:" + if is_using_systemd; then + log_only "- stop teleport's service" + log_only " - systemctl stop teleport" + fi log_only "- stop any running Teleport processes" log_only " - pkill -f teleport" log_only "- remove any data under ${TELEPORT_DATA_DIR}, along with the directory itself" log_only " - rm -rf ${TELEPORT_DATA_DIR}" log_only "- remove any configuration at ${TELEPORT_CONFIG_PATH}" log_only " - rm -f ${TELEPORT_CONFIG_PATH}" - log_only "- remove any Teleport binaries (${TELEPORT_BINARY_LIST}) installed under ${TELEPORT_BINARY_DIR}" - for BINARY in ${TELEPORT_BINARY_LIST}; do EXAMPLE_DELETE_COMMAND+="${TELEPORT_BINARY_DIR}/${BINARY} "; done - log_only " - rm -f ${EXAMPLE_DELETE_COMMAND}" + if check_exists apt; then + log_only "- remove teleport package" + log_only " - apt remove teleport" + elif check_exists yum; then + log_only "- remove teleport package" + log_only " - yum remove teleport" + elif check_exists dnf; then + log_only "- remove teleport package" + log_only " - dnf remove teleport" + elif check_exists zypper; then + log_only "- remove teleport package" + log_only " - zypper remove teleport" + else + log_only "- remove any Teleport binaries (${TELEPORT_BINARY_LIST}) installed under ${TELEPORT_BINARY_DIR}" + for BINARY in ${TELEPORT_BINARY_LIST}; do EXAMPLE_DELETE_COMMAND+="${TELEPORT_BINARY_DIR}/${BINARY} "; done + log_only " - rm -f ${EXAMPLE_DELETE_COMMAND}" + fi if is_macos_host; then log_only "- unload and remove Teleport launchd config ${LAUNCHD_CONFIG_PATH}/${LAUNCHD_PLIST_FILE}" log_only " - launchctl unload ${LAUNCHD_CONFIG_PATH}/${LAUNCHD_PLIST_FILE}" diff --git a/tool/tctl/common/auth_command.go b/tool/tctl/common/auth_command.go index e02632d118f02..cb7d47bcb27a3 100644 --- a/tool/tctl/common/auth_command.go +++ b/tool/tctl/common/auth_command.go @@ -79,6 +79,7 @@ type AuthCommand struct { windowsDomain string windowsPKIDomain string windowsSID string + omitCDP bool signOverwrite bool password string caType string @@ -150,6 +151,7 @@ func (a *AuthCommand) Initialize(app *kingpin.Application, config *servicecfg.Co a.authSign.Flag("windows-domain", `Active Directory domain for which this cert is valid. Only used when --format is set to "windows"`).StringVar(&a.windowsDomain) a.authSign.Flag("windows-pki-domain", `Active Directory domain where CRLs will be located. Only used when --format is set to "windows"`).StringVar(&a.windowsPKIDomain) a.authSign.Flag("windows-sid", `Optional Security Identifier to embed in the certificate. Only used when --format is set to "windows"`).StringVar(&a.windowsSID) + a.authSign.Flag("omit-cdp", `Omit CRL Distribution Points from the cert. Only used when --format is set to "windows"`).BoolVar(&a.omitCDP) a.authRotate = auth.Command("rotate", "Rotate certificate authorities in the cluster.") a.authRotate.Flag("grace-period", "Grace period keeps previous certificate authorities signatures valid, if set to 0 will force users to re-login and nodes to re-register."). @@ -363,6 +365,7 @@ func (a *AuthCommand) generateWindowsCert(ctx context.Context, clusterAPI certif TTL: a.genTTL, ClusterName: cn.GetClusterName(), LDAPConfig: windows.LDAPConfig{Domain: domain}, + OmitCDP: a.omitCDP, AuthClient: clusterAPI, }) if err != nil { diff --git a/web/packages/teleport/src/Discover/SelectResource/databases.tsx b/web/packages/teleport/src/Discover/SelectResource/databases.tsx index d4cf3a18332b4..cf563b09e1028 100644 --- a/web/packages/teleport/src/Discover/SelectResource/databases.tsx +++ b/web/packages/teleport/src/Discover/SelectResource/databases.tsx @@ -26,25 +26,12 @@ import { ResourceKind } from '../Shared/ResourceKind'; import { ResourceSpec, DatabaseLocation, DatabaseEngine } from './types'; -enum DatabaseGuideSection { - Aws = 'enroll-aws-databases', - Azure = 'enroll-azure-databases', - Gcp = 'enroll-google-cloud-databases', - Managed = 'enroll-managed-databases', - SelfHosted = 'enroll-self-hosted-databases', - Guides = 'guides', -} - const baseDatabaseKeywords = 'db database databases'; const awsKeywords = baseDatabaseKeywords + 'aws amazon web services'; const gcpKeywords = baseDatabaseKeywords + 'gcp google cloud provider'; const selfhostedKeywords = baseDatabaseKeywords + 'self hosted self-hosted'; const azureKeywords = baseDatabaseKeywords + 'microsoft azure'; -function getDbAccessDocLink(subsection: DatabaseGuideSection, guide: string) { - return `https://goteleport.com/docs/enroll-resources/database-access/${subsection}/${guide}`; -} - // DATABASES_UNGUIDED_DOC are documentations that is not specific // to one type of database. export const DATABASES_UNGUIDED_DOC: ResourceSpec[] = [ @@ -54,10 +41,8 @@ export const DATABASES_UNGUIDED_DOC: ResourceSpec[] = [ keywords: awsKeywords + 'rds proxy postgresql', kind: ResourceKind.Database, icon: 'aws', - unguidedLink: getDbAccessDocLink( - DatabaseGuideSection.Aws, - 'rds-proxy-postgres' - ), + unguidedLink: + 'https://goteleport.com/docs/enroll-resources/database-access/enroll-aws-databases/rds-proxy-postgres', // TODO(lisa): add a new usage event event: DiscoverEventResource.DatabaseDocRdsProxy, }, @@ -67,10 +52,8 @@ export const DATABASES_UNGUIDED_DOC: ResourceSpec[] = [ keywords: awsKeywords + 'rds proxy sql server sqlserver', kind: ResourceKind.Database, icon: 'aws', - unguidedLink: getDbAccessDocLink( - DatabaseGuideSection.Aws, - 'rds-proxy-sqlserver' - ), + unguidedLink: + 'https://goteleport.com/docs/enroll-resources/database-access/enroll-aws-databases/rds-proxy-sqlserver', // TODO(lisa): add a new usage event event: DiscoverEventResource.DatabaseDocRdsProxy, }, @@ -80,10 +63,8 @@ export const DATABASES_UNGUIDED_DOC: ResourceSpec[] = [ keywords: awsKeywords + 'rds proxy mariadb mysql', kind: ResourceKind.Database, icon: 'aws', - unguidedLink: getDbAccessDocLink( - DatabaseGuideSection.Aws, - 'rds-proxy-mysql' - ), + unguidedLink: + 'https://goteleport.com/docs/enroll-resources/database-access/enroll-aws-databases/rds-proxy-mysql', // TODO(lisa): add a new usage event event: DiscoverEventResource.DatabaseDocRdsProxy, }, @@ -93,7 +74,8 @@ export const DATABASES_UNGUIDED_DOC: ResourceSpec[] = [ keywords: baseDatabaseKeywords + 'high availability ha', kind: ResourceKind.Database, icon: 'database', - unguidedLink: getDbAccessDocLink(DatabaseGuideSection.Guides, 'ha'), + unguidedLink: + 'https://goteleport.com/docs/enroll-resources/database-access/guides/ha', event: DiscoverEventResource.DatabaseDocHighAvailability, }, { @@ -102,10 +84,8 @@ export const DATABASES_UNGUIDED_DOC: ResourceSpec[] = [ keywords: baseDatabaseKeywords + 'dynamic registration', kind: ResourceKind.Database, icon: 'database', - unguidedLink: getDbAccessDocLink( - DatabaseGuideSection.Guides, - 'dynamic-registration' - ), + unguidedLink: + 'https://goteleport.com/docs/enroll-resources/database-access/guides/dynamic-registration', event: DiscoverEventResource.DatabaseDocDynamicRegistration, }, ]; @@ -117,7 +97,8 @@ export const DATABASES_UNGUIDED: ResourceSpec[] = [ keywords: awsKeywords + 'dynamodb', kind: ResourceKind.Database, icon: 'dynamo', - unguidedLink: getDbAccessDocLink(DatabaseGuideSection.Aws, 'aws-dynamodb'), + unguidedLink: + 'https://goteleport.com/docs/enroll-resources/database-access/enroll-aws-databases/aws-dynamodb', event: DiscoverEventResource.DatabaseDynamoDb, }, { @@ -126,7 +107,8 @@ export const DATABASES_UNGUIDED: ResourceSpec[] = [ keywords: awsKeywords + 'elasticache memorydb redis', kind: ResourceKind.Database, icon: 'aws', - unguidedLink: getDbAccessDocLink(DatabaseGuideSection.Aws, 'redis-aws'), + unguidedLink: + 'https://goteleport.com/docs/enroll-resources/database-access/enroll-aws-databases/redis-aws', event: DiscoverEventResource.DatabaseRedisElasticache, }, { @@ -138,10 +120,8 @@ export const DATABASES_UNGUIDED: ResourceSpec[] = [ keywords: awsKeywords + 'keyspaces apache cassandra', kind: ResourceKind.Database, icon: 'aws', - unguidedLink: getDbAccessDocLink( - DatabaseGuideSection.Aws, - 'aws-cassandra-keyspaces' - ), + unguidedLink: + 'https://goteleport.com/docs/enroll-resources/database-access/enroll-aws-databases/aws-cassandra-keyspaces', event: DiscoverEventResource.DatabaseCassandraKeyspaces, }, { @@ -150,10 +130,8 @@ export const DATABASES_UNGUIDED: ResourceSpec[] = [ keywords: awsKeywords + 'redshift postgresql', kind: ResourceKind.Database, icon: 'redshift', - unguidedLink: getDbAccessDocLink( - DatabaseGuideSection.Aws, - 'postgres-redshift' - ), + unguidedLink: + 'https://goteleport.com/docs/enroll-resources/database-access/enroll-aws-databases/postgres-redshift', event: DiscoverEventResource.DatabasePostgresRedshift, }, { @@ -162,10 +140,8 @@ export const DATABASES_UNGUIDED: ResourceSpec[] = [ keywords: awsKeywords + 'redshift serverless postgresql', kind: ResourceKind.Database, icon: 'redshift', - unguidedLink: getDbAccessDocLink( - DatabaseGuideSection.Aws, - 'redshift-serverless' - ), + unguidedLink: + 'https://goteleport.com/docs/enroll-resources/database-access/enroll-aws-databases/redshift-serverless', event: DiscoverEventResource.DatabasePostgresRedshiftServerless, }, { @@ -174,7 +150,8 @@ export const DATABASES_UNGUIDED: ResourceSpec[] = [ keywords: azureKeywords + 'cache redis', kind: ResourceKind.Database, icon: 'azure', - unguidedLink: getDbAccessDocLink(DatabaseGuideSection.Azure, 'azure-redis'), + unguidedLink: + 'https://goteleport.com/docs/enroll-resources/database-access/enroll-azure-databases/azure-redis', event: DiscoverEventResource.DatabaseRedisAzureCache, }, { @@ -186,10 +163,8 @@ export const DATABASES_UNGUIDED: ResourceSpec[] = [ keywords: azureKeywords + 'postgresql', kind: ResourceKind.Database, icon: 'azure', - unguidedLink: getDbAccessDocLink( - DatabaseGuideSection.Azure, - 'azure-postgres-mysql' - ), + unguidedLink: + 'https://goteleport.com/docs/enroll-resources/database-access/enroll-azure-databases/azure-postgres-mysql', event: DiscoverEventResource.DatabasePostgresAzure, }, { @@ -198,10 +173,8 @@ export const DATABASES_UNGUIDED: ResourceSpec[] = [ keywords: azureKeywords + 'mysql', kind: ResourceKind.Database, icon: 'azure', - unguidedLink: getDbAccessDocLink( - DatabaseGuideSection.Azure, - 'azure-postgres-mysql' - ), + unguidedLink: + 'https://goteleport.com/docs/enroll-resources/database-access/enroll-azure-databases/azure-postgres-mysql', event: DiscoverEventResource.DatabaseMysqlAzure, }, { @@ -214,10 +187,8 @@ export const DATABASES_UNGUIDED: ResourceSpec[] = [ azureKeywords + 'active directory ad sql server sqlserver preview', kind: ResourceKind.Database, icon: 'azure', - unguidedLink: getDbAccessDocLink( - DatabaseGuideSection.Azure, - 'azure-sql-server-ad' - ), + unguidedLink: + 'https://goteleport.com/docs/enroll-resources/database-access/enroll-azure-databases/azure-sql-server-ad', event: DiscoverEventResource.DatabaseSqlServerAzure, platform: Platform.Windows, }, @@ -232,7 +203,8 @@ export const DATABASES_UNGUIDED: ResourceSpec[] = [ 'rds microsoft active directory ad sql server sqlserver preview', kind: ResourceKind.Database, icon: 'aws', - unguidedLink: getDbAccessDocLink(DatabaseGuideSection.Aws, 'sql-server-ad'), + unguidedLink: + 'https://goteleport.com/docs/enroll-resources/database-access/enroll-aws-databases/sql-server-ad', event: DiscoverEventResource.DatabaseSqlServerMicrosoft, platform: Platform.Windows, }, @@ -242,10 +214,8 @@ export const DATABASES_UNGUIDED: ResourceSpec[] = [ keywords: gcpKeywords + 'mysql', kind: ResourceKind.Database, icon: 'googlecloud', - unguidedLink: getDbAccessDocLink( - DatabaseGuideSection.Gcp, - 'mysql-cloudsql' - ), + unguidedLink: + 'https://goteleport.com/docs/enroll-resources/database-access/enroll-google-cloud-databases/mysql-cloudsql', event: DiscoverEventResource.DatabaseMysqlGcp, }, { @@ -254,10 +224,8 @@ export const DATABASES_UNGUIDED: ResourceSpec[] = [ keywords: gcpKeywords + 'postgresql', kind: ResourceKind.Database, icon: 'googlecloud', - unguidedLink: getDbAccessDocLink( - DatabaseGuideSection.Gcp, - 'postgres-cloudsql' - ), + unguidedLink: + 'https://goteleport.com/docs/enroll-resources/database-access/enroll-google-cloud-databases/postgres-cloudsql', event: DiscoverEventResource.DatabasePostgresGcp, }, { @@ -269,10 +237,8 @@ export const DATABASES_UNGUIDED: ResourceSpec[] = [ keywords: baseDatabaseKeywords + 'mongodb atlas', kind: ResourceKind.Database, icon: 'mongo', - unguidedLink: getDbAccessDocLink( - DatabaseGuideSection.Managed, - 'mongodb-atlas' - ), + unguidedLink: + 'https://goteleport.com/docs/enroll-resources/database-access/enroll-managed-databases/mongodb-atlas', event: DiscoverEventResource.DatabaseMongodbAtlas, }, { @@ -284,10 +250,8 @@ export const DATABASES_UNGUIDED: ResourceSpec[] = [ keywords: selfhostedKeywords + 'cassandra scylladb', kind: ResourceKind.Database, icon: 'selfhosted', - unguidedLink: getDbAccessDocLink( - DatabaseGuideSection.SelfHosted, - 'cassandra-self-hosted' - ), + unguidedLink: + 'https://goteleport.com/docs/enroll-resources/database-access/enroll-self-hosted-databases/cassandra-self-hosted', event: DiscoverEventResource.DatabaseCassandraSelfHosted, }, { @@ -299,10 +263,8 @@ export const DATABASES_UNGUIDED: ResourceSpec[] = [ keywords: selfhostedKeywords + 'cockroachdb', kind: ResourceKind.Database, icon: 'cockroach', - unguidedLink: getDbAccessDocLink( - DatabaseGuideSection.SelfHosted, - 'cockroachdb-self-hosted' - ), + unguidedLink: + 'https://goteleport.com/docs/enroll-resources/database-access/enroll-self-hosted-databases/cockroachdb-self-hosted', event: DiscoverEventResource.DatabaseCockroachDbSelfHosted, }, { @@ -314,10 +276,8 @@ export const DATABASES_UNGUIDED: ResourceSpec[] = [ keywords: selfhostedKeywords + 'elasticsearch', kind: ResourceKind.Database, icon: 'selfhosted', - unguidedLink: getDbAccessDocLink( - DatabaseGuideSection.SelfHosted, - 'elastic' - ), + unguidedLink: + 'https://goteleport.com/docs/enroll-resources/database-access/enroll-self-hosted-databases/elastic', event: DiscoverEventResource.DatabaseElasticSearchSelfHosted, }, { @@ -329,10 +289,8 @@ export const DATABASES_UNGUIDED: ResourceSpec[] = [ keywords: selfhostedKeywords + 'mongodb', kind: ResourceKind.Database, icon: 'mongo', - unguidedLink: getDbAccessDocLink( - DatabaseGuideSection.SelfHosted, - 'mongodb-self-hosted' - ), + unguidedLink: + 'https://goteleport.com/docs/enroll-resources/database-access/enroll-self-hosted-databases/mongodb-self-hosted', event: DiscoverEventResource.DatabaseMongodbSelfHosted, }, { @@ -344,7 +302,8 @@ export const DATABASES_UNGUIDED: ResourceSpec[] = [ keywords: selfhostedKeywords + 'redis', kind: ResourceKind.Database, icon: 'selfhosted', - unguidedLink: getDbAccessDocLink(DatabaseGuideSection.SelfHosted, 'redis'), + unguidedLink: + 'https://goteleport.com/docs/enroll-resources/database-access/enroll-self-hosted-databases/redis', event: DiscoverEventResource.DatabaseRedisSelfHosted, }, { @@ -356,10 +315,8 @@ export const DATABASES_UNGUIDED: ResourceSpec[] = [ keywords: selfhostedKeywords + 'redis cluster', kind: ResourceKind.Database, icon: 'selfhosted', - unguidedLink: getDbAccessDocLink( - DatabaseGuideSection.SelfHosted, - 'redis-cluster' - ), + unguidedLink: + 'https://goteleport.com/docs/enroll-resources/database-access/enroll-self-hosted-databases/redis-cluster', event: DiscoverEventResource.DatabaseRedisClusterSelfHosted, }, { @@ -371,7 +328,8 @@ export const DATABASES_UNGUIDED: ResourceSpec[] = [ keywords: baseDatabaseKeywords + 'snowflake preview', kind: ResourceKind.Database, icon: 'snowflake', - unguidedLink: getDbAccessDocLink(DatabaseGuideSection.Managed, 'snowflake'), + unguidedLink: + 'https://goteleport.com/docs/enroll-resources/database-access/enroll-managed-databases/snowflake', event: DiscoverEventResource.DatabaseSnowflake, }, ];