diff --git a/api/types/installers/installer.sh.tmpl b/api/types/installers/installer.sh.tmpl index 6da86d378589d..2af6e40204458 100644 --- a/api/types/installers/installer.sh.tmpl +++ b/api/types/installers/installer.sh.tmpl @@ -33,7 +33,7 @@ # token is read as a parameter from the AWS ssm script run and # passed as the first argument to the script sudo /usr/local/bin/teleport node configure \ - --auth-server="{{ .PublicProxyAddr }}" \ + --proxy="{{ .PublicProxyAddr }}" \ --join-method=iam \ --token="$1" \ --output=file \ diff --git a/api/types/provisioning.go b/api/types/provisioning.go index c0bd101026832..3da0dc29cf8d8 100644 --- a/api/types/provisioning.go +++ b/api/types/provisioning.go @@ -21,6 +21,7 @@ import ( "time" "github.com/gravitational/teleport/api/defaults" + apiutils "github.com/gravitational/teleport/api/utils" "github.com/gravitational/trace" ) @@ -39,6 +40,21 @@ const ( JoinMethodIAM JoinMethod = "iam" ) +var JoinMethods = []JoinMethod{ + JoinMethodToken, + JoinMethodEC2, + JoinMethodIAM, +} + +func ValidateJoinMethod(method JoinMethod) error { + hasJoinMethod := apiutils.SliceContainsStr(JoinMethods, method) + if !hasJoinMethod { + return trace.BadParameter("join method must be one of %s", apiutils.JoinStrings(JoinMethods, ", ")) + } + + return nil +} + // ProvisionToken is a provisioning token type ProvisionToken interface { Resource diff --git a/api/utils/slices.go b/api/utils/slices.go index 4ee1da2a3debb..de1cca33a681f 100644 --- a/api/utils/slices.go +++ b/api/utils/slices.go @@ -16,6 +16,10 @@ limitations under the License. package utils +import ( + "strings" +) + // CopyByteSlice returns a copy of the byte slice. func CopyByteSlice(in []byte) []byte { if in == nil { @@ -52,7 +56,7 @@ func StringSlicesEqual(a, b []string) bool { } // SliceContainsStr returns 'true' if the slice contains the given value -func SliceContainsStr(slice []string, value string) bool { +func SliceContainsStr[T ~string](slice []T, value T) bool { for i := range slice { if slice[i] == value { return true @@ -61,6 +65,31 @@ func SliceContainsStr(slice []string, value string) bool { return false } +// JoinStrings returns a string that is all the elements in the slice `T[]` joined by `sep` +// This being generic allows for the usage of custom string times, without having to convert +// the elements to a string to be passed into `strings.Join`. +func JoinStrings[T ~string](elems []T, sep string) T { + switch len(elems) { + case 0: + return "" + case 1: + return elems[0] + } + n := len(sep) * (len(elems) - 1) + for i := 0; i < len(elems); i++ { + n += len(elems[i]) + } + + var b strings.Builder + b.Grow(n) + b.WriteString(string(elems[0])) + for _, s := range elems[1:] { + b.WriteString(sep) + b.WriteString(string(s)) + } + return T(b.String()) +} + // Deduplicate deduplicates list of strings func Deduplicate(in []string) []string { if len(in) == 0 { diff --git a/assets/aws/files/bin/teleport-generate-config b/assets/aws/files/bin/teleport-generate-config index 142a34e459d9e..7e70e050156dd 100755 --- a/assets/aws/files/bin/teleport-generate-config +++ b/assets/aws/files/bin/teleport-generate-config @@ -307,6 +307,7 @@ elif [[ "${TELEPORT_ROLE}" == "proxy" ]]; then # Teleport proxy proxies and optionally records # SSH sessions cat >${USE_CONFIG_PATH} < ${USE_CONFD_DIR}/role.node # Teleport node handles incoming connections cat >${USE_CONFIG_PATH} < ${USE_CONFD_DIR}/role.agent cat >${USE_CONFIG_PATH} < Teleport uses AWS [federation](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_enable-console-custom-url.html) to generate sign-in URLs for users, which relies on the `AssumeRole` API -for getting temporary security credentials. +for getting temporary security credentials. You will need to update your IAM roles' "Trusted entities" to include your AWS account ID. Go to the [Roles](https://console.aws.amazon.com/iamv2/home#/roles) list, pick @@ -163,18 +163,18 @@ for details. Add AWS management console to your application service configuration: ```yaml +version: v3 teleport: # Data directory for the Application Proxy service. If running on the same # node as Auth/Proxy service, make sure to use different data directories. data_dir: /var/lib/teleport-app - # Instructs the service to load the join token from the specified file + # Instructs the service to load the auth token from the specified file # during initial registration with the cluster. auth_token: /var/lib/teleport-app/token # Proxy address to connect to. Note that it has to be the proxy address # because the app service always connects to the cluster over a reverse # tunnel. - auth_servers: - - teleport.example.com:3080 + proxy_server: teleport.example.com:3080 app_service: enabled: "yes" apps: diff --git a/docs/pages/application-access/guides/connecting-apps.mdx b/docs/pages/application-access/guides/connecting-apps.mdx index 1333d6f4c5a1f..f0a4146cf5237 100644 --- a/docs/pages/application-access/guides/connecting-apps.mdx +++ b/docs/pages/application-access/guides/connecting-apps.mdx @@ -133,18 +133,18 @@ Teleport proxy server. Example `teleport.yaml` configuration: ```yaml +version: v3 teleport: # Data directory for the Application Proxy service. If running on the same # node as Auth/Proxy service, make sure to use different data directories. data_dir: /var/lib/teleport-app - # Instructs the service to load the join token from the specified file + # Instructs the service to load the auth token from the specified file # during initial registration with the cluster. auth_token: /tmp/token # Proxy address to connect to. Note that it has to be the proxy address # because the app service always connects to the cluster over a reverse # tunnel. - auth_servers: - - teleport.example.com:3080 + proxy_server: teleport.example.com:3080 app_service: enabled: yes # Teleport provides a small debug app that can be used to make sure application diff --git a/docs/pages/application-access/guides/tcp.mdx b/docs/pages/application-access/guides/tcp.mdx index c94c309ef41c5..553f465e759b6 100644 --- a/docs/pages/application-access/guides/tcp.mdx +++ b/docs/pages/application-access/guides/tcp.mdx @@ -77,10 +77,10 @@ Create the Application Service configuration file `/etc/teleport.yaml` with the following contents: ```yaml +version: v3 teleport: auth_token: "/tmp/token" - auth_servers: - - teleport.example.com:3080 + proxy_server: teleport.example.com:3080 auth_service: enabled: "no" ssh_service: diff --git a/docs/pages/database-access/guides/mongodb-atlas.mdx b/docs/pages/database-access/guides/mongodb-atlas.mdx index 4e5b07761218e..0c8fe8400c5db 100644 --- a/docs/pages/database-access/guides/mongodb-atlas.mdx +++ b/docs/pages/database-access/guides/mongodb-atlas.mdx @@ -75,10 +75,10 @@ On the node where you will run the Teleport Database Service, run `teleport db start` with the following in `/etc/teleport.yaml`: ```yaml +version: v3 teleport: auth_token: "/tmp/token" - auth_servers: - - "teleport.example.com:443" + proxy_server: teleport.example.com:443 db_service: enabled: "yes" databases: @@ -122,10 +122,10 @@ On the node where you will run the Teleport Database Service, run `teleport db start` with the following in `/etc/teleport.yaml`: ```yaml +version: v3 teleport: auth_token: "/tmp/token" - auth_servers: - - "mytenant.teleport.sh" + proxy_server: mytenant.teleport.sh db_service: enabled: "yes" databases: diff --git a/docs/pages/database-access/guides/mysql-cloudsql.mdx b/docs/pages/database-access/guides/mysql-cloudsql.mdx index 854f2e39c8da3..3e3abb8187914 100644 --- a/docs/pages/database-access/guides/mysql-cloudsql.mdx +++ b/docs/pages/database-access/guides/mysql-cloudsql.mdx @@ -134,14 +134,14 @@ a single Cloud SQL MySQL database: ```yaml +version: v3 teleport: data_dir: /var/lib/teleport-db nodename: test # Proxy address to connect to. Note that it has to be the proxy address # because the Database Service always connects to the cluster over a reverse # tunnel. - auth_servers: - - teleport.example.com:3080 + proxy_server: teleport.example.com:3080 db_service: enabled: "yes" # This section contains definitions of all databases proxied by this @@ -178,12 +178,12 @@ proxy_service: ```yaml +version: v3 teleport: data_dir: /var/lib/teleport-db nodename: test # Proxy address to connect to. Use your Teleport Cloud tenant address. - auth_servers: - - mytenant.teleport.sh + proxy_server: mytenant.teleport.sh db_service: enabled: "yes" # This section contains definitions of all databases proxied by this diff --git a/docs/pages/database-access/guides/postgres-cloudsql.mdx b/docs/pages/database-access/guides/postgres-cloudsql.mdx index e4e4ae3d2e88a..0effc09f1097b 100644 --- a/docs/pages/database-access/guides/postgres-cloudsql.mdx +++ b/docs/pages/database-access/guides/postgres-cloudsql.mdx @@ -205,14 +205,14 @@ a single Cloud SQL PostgreSQL database: ```yaml +version: v3 teleport: data_dir: /var/lib/teleport-db nodename: test # Proxy address to connect to. Note that it has to be the proxy address # because the Database Service always connects to the cluster over a reverse # tunnel. - auth_servers: - - teleport.example.com:3080 + proxy_server: teleport.example.com:3080 db_service: enabled: "yes" # This section contains definitions of all databases proxied by this @@ -249,12 +249,12 @@ proxy_service: ```yaml +version: v3 teleport: data_dir: /var/lib/teleport-db nodename: test # Proxy address to connect to. Use your Teleport Cloud tenant address here. - auth_servers: - - mytenant.teleport.sh + proxy_server: mytenant.teleport.sh db_service: enabled: "yes" # This section contains definitions of all databases proxied by this diff --git a/docs/pages/deploy-a-cluster/deployments/aws-terraform.mdx b/docs/pages/deploy-a-cluster/deployments/aws-terraform.mdx index a338a65821da4..3a2c23ac519b0 100644 --- a/docs/pages/deploy-a-cluster/deployments/aws-terraform.mdx +++ b/docs/pages/deploy-a-cluster/deployments/aws-terraform.mdx @@ -746,8 +746,7 @@ $ aws elbv2 describe-load-balancers --names "${TF_VAR_cluster_name}-auth" --quer With this method, the Nodes should be configured like so: ```yaml -auth_servers: - - example-cluster-auth-c5b0fc2764ee015b.elb.us-east-1.amazonaws.com:3025 +auth_server: example-cluster-auth-c5b0fc2764ee015b.elb.us-east-1.amazonaws.com:3025 ``` ### Joining Nodes via Teleport IoT/Node tunneling @@ -759,8 +758,7 @@ With this method, you can join the nodes using the public facing proxy address - example. ```yaml -auth_servers: - - teleport.example.com:443 +proxy_server: teleport.example.com:443 ``` ### Trusted Clusters diff --git a/docs/pages/deploy-a-cluster/deployments/gcp.mdx b/docs/pages/deploy-a-cluster/deployments/gcp.mdx index 2b85d6b016613..373c5c7c9071e 100644 --- a/docs/pages/deploy-a-cluster/deployments/gcp.mdx +++ b/docs/pages/deploy-a-cluster/deployments/gcp.mdx @@ -188,12 +188,12 @@ Save the following configuration file as `/etc/teleport.yaml` on the Proxy Serve ```yaml # enable multiplexing all traffic on TCP port 443 -version: v2 +version: v3 teleport: auth_token: EXAMPLE-PROXY-JOIN-TOKEN # We recommend using a TCP load balancer pointed to the auth servers when # setting up in High Availability mode. - auth_servers: [ "auth.example.com:3025" ] + auth_server: auth.example.com:3025 # enable proxy service, disable auth and ssh ssh_service: enabled: false @@ -214,11 +214,12 @@ proxy_service: Save the following configuration file as `/etc/teleport.yaml` on the Node: ```yaml +version: v3 teleport: auth_token: EXAMPLE-NODE-JOIN-TOKEN # Nodes and other agents can be joined to the cluster via the proxy's public address. # This will establish a reverse tunnel between the proxy and the node which is used for all traffic. - auth_servers: [ "teleport.example.com:443" ] + proxy_server: teleport.example.com:443 # enable ssh service and disable auth and proxy ssh_service: enabled: true diff --git a/docs/pages/desktop-access/getting-started.mdx b/docs/pages/desktop-access/getting-started.mdx index 7017831a509ac..9d724f426e64f 100644 --- a/docs/pages/desktop-access/getting-started.mdx +++ b/docs/pages/desktop-access/getting-started.mdx @@ -335,7 +335,7 @@ gpupdate.exe /force Teleport's RDP client supports only secure algorithms - for making TLS connections, so we have to configure our Domain Controller + for making TLS connections, so we have to configure our Domain Controller to support those cipher suites as well. This step is only *necessary* for Windows Server 2012 R2 Domain Controller as it does not support secure algorithms by default. If it does not apply to you, you can skip this step and go to the [next step](#step-57-export-your-ldap-ca-certificate). @@ -466,7 +466,7 @@ windows_desktop_service:
For Teleport Cloud, Windows Desktop Service should establish a reverse tunnel to -the hosted proxy. This requires setting `auth_servers` to your cloud tenant and +the hosted proxy. This requires setting `proxy_server` to your cloud tenant and providing a join token. First, generate a join token with the following command: @@ -479,10 +479,10 @@ Copy the join token to a file on the instance where you will run Windows Desktop Service, and then use the following configuration: ```yaml +version: v3 teleport: auth_token: /path/to/token - auth_servers: - - mytenant.teleport.sh # replace with your cloud tenant + proxy_server: mytenant.teleport.sh # replace with your cloud tenant windows_desktop_service: enabled: yes ldap: diff --git a/docs/pages/desktop-access/reference/configuration.mdx b/docs/pages/desktop-access/reference/configuration.mdx index c6f0942e41e6d..3f6d043008d47 100644 --- a/docs/pages/desktop-access/reference/configuration.mdx +++ b/docs/pages/desktop-access/reference/configuration.mdx @@ -25,7 +25,7 @@ The Windows Desktop Service can be deployed in two modes. In *direct* mode, Windows Desktop Services registers directly with the Teleport Auth Server, and listens for desktop connections from the Teleport Proxy. To enable direct mode, set `windows_desktop_service.listen_addr` in -`teleport.yaml`, and ensure that `teleport.auth_servers` points directly at the +`teleport.yaml`, and ensure that `teleport.auth_server` points directly at the Auth Server. Direct mode requires network connectivity from the Teleport Proxy to Windows Desktop Service, and from Windows Desktop Service to the Auth Server. @@ -36,5 +36,5 @@ connection to a Teleport Proxy. The Windows Desktop Service establishes a reverse tunnel to the proxy, and both registration with the Auth Server and desktop sessions are performed over this tunnel. To enable this mode, ensure that `windows_desktop_service.listen_addr` is *unset*, and point -`teleport.auth_servers` at a Teleport Proxy. +`teleport.proxy_server` at a Teleport Proxy. diff --git a/docs/pages/management/admin/labels.mdx b/docs/pages/management/admin/labels.mdx index 3ceed7217f90a..eab9132cb5e7b 100644 --- a/docs/pages/management/admin/labels.mdx +++ b/docs/pages/management/admin/labels.mdx @@ -104,13 +104,14 @@ On the host where you will run your Node, paste the following content into ```yaml -version: v2 +version: v3 teleport: - auth_servers: - # The address of your Auth Service. You can also use a Proxy Service - # address, e.g., tele.example.com:443, if your Auth Service is not - # exposed to the internet. - - tele.example.com:3025 + # The address of your Auth Service. + auth_server: tele.example.com:3025 + # Or, you can also use a Proxy Service + # address, e.g., tele.example.com:443, if your Auth Service is not + # exposed to the internet. + proxy_server: tele.example.com:443 auth_service: enabled: false @@ -129,11 +130,10 @@ ssh_service: ```yaml -version: v2 +version: v3 teleport: - auth_servers: - # Your Teleport Cloud tenant address - - mytenant.teleport.sh:443 + # Your Teleport Cloud tenant address + proxy_server: mytenant.teleport.sh:443 auth_service: enabled: false @@ -161,8 +161,8 @@ machine. Your Teleport user must be authorized to access the Node. ```code $ tsh ls --query 'labels["environment"]=="dev"' -Node Name Address Labels ------------- ---------- --------------- +Node Name Address Labels +------------ ---------- --------------- bdcb47b87ad6 ⟵ Tunnel environment=dev ``` @@ -231,7 +231,7 @@ host: kubernetes_groups: null kubernetes_users: null - logins: null -+ logins: ++ logins: + - root windows_logins: null version: v2 @@ -240,7 +240,7 @@ host: Apply your changes: ```code -$ tctl create -f user.yaml +$ tctl create -f user.yaml user "myuser" has been updated ``` @@ -261,10 +261,9 @@ Edit `/etc/teleport.yaml` to define a `commands` array as shown below: ```yaml -version: v2 +version: v3 teleport: - auth_servers: - - tele.example.com:3025 + auth_server: tele.example.com:3025 auth_service: enabled: false @@ -290,10 +289,9 @@ ssh_service: ```yaml -version: v2 +version: v3 teleport: - auth_servers: - - mytenant.teleport.sh:443 + proxy_server: mytenant.teleport.sh:443 auth_service: enabled: false @@ -360,9 +358,9 @@ machine. Your Teleport user must be authorized to access the Node. ```code $ tsh ls -Node Name Address Labels ------------------ ---------- --------------- -ip-192-0-2-0 ⟵ Tunnel arch=x86_64,hostname=ip-172-30-156-233 +Node Name Address Labels +----------------- ---------- --------------- +ip-192-0-2-0 ⟵ Tunnel arch=x86_64,hostname=ip-172-30-156-233 ```
diff --git a/docs/pages/management/guides/joining-nodes-aws-ec2.mdx b/docs/pages/management/guides/joining-nodes-aws-ec2.mdx index 6cd1895dce2e7..b16d6a0793af2 100644 --- a/docs/pages/management/guides/joining-nodes-aws-ec2.mdx +++ b/docs/pages/management/guides/joining-nodes-aws-ec2.mdx @@ -23,7 +23,7 @@ IAM credentials with `ec2:DescribeInstances` permissions are required on your Teleport Auth Service. No IAM credentials are required on the Nodes or Proxy Service instances. -
-
teleport.yaml << EOF # By default, this file should be stored in /etc/teleport.yaml + version: v3 teleport: nodename: $TELEPORT_PUBLIC_DNS_NAME cluster_name: $TELEPORT_CLUSTER_NAME @@ -11,8 +12,7 @@ export TELEPORT_CLUSTER_NAME="[teleport-cluster-name]" severity: ERROR storage: type: dir - auth_servers: - - 127.0.0.1:3025 + auth_server: 127.0.0.1:3025 log: output: stderr severity: INFO diff --git a/examples/chart/teleport-cluster/tests/__snapshot__/deployment_test.yaml.snap b/examples/chart/teleport-cluster/tests/__snapshot__/deployment_test.yaml.snap index 8478569ffef1a..01ff1a73157fe 100644 --- a/examples/chart/teleport-cluster/tests/__snapshot__/deployment_test.yaml.snap +++ b/examples/chart/teleport-cluster/tests/__snapshot__/deployment_test.yaml.snap @@ -34,9 +34,6 @@ sets Deployment annotations when specified: name: data serviceAccountName: RELEASE-NAME volumes: - - name: gcp-credentials - secret: - secretName: teleport-gcp-credentials - configMap: name: RELEASE-NAME name: config @@ -79,9 +76,6 @@ sets Pod annotations when specified: name: data serviceAccountName: RELEASE-NAME volumes: - - name: gcp-credentials - secret: - secretName: teleport-gcp-credentials - configMap: name: RELEASE-NAME name: config @@ -124,9 +118,6 @@ should add PersistentVolumeClaim as volume when in custom mode and persistence.e name: data serviceAccountName: RELEASE-NAME volumes: - - name: gcp-credentials - secret: - secretName: teleport-gcp-credentials - configMap: name: RELEASE-NAME name: config @@ -169,9 +160,6 @@ should add PersistentVolumeClaim as volume when in standalone mode and persisten name: data serviceAccountName: RELEASE-NAME volumes: - - name: gcp-credentials - secret: - secretName: teleport-gcp-credentials - configMap: name: RELEASE-NAME name: config @@ -249,9 +237,6 @@ should add emptyDir for data in AWS mode: name: data serviceAccountName: RELEASE-NAME volumes: - - name: gcp-credentials - secret: - secretName: teleport-gcp-credentials - configMap: name: RELEASE-NAME name: config @@ -353,9 +338,6 @@ should add insecureSkipProxyTLSVerify to args when set in values: name: data serviceAccountName: RELEASE-NAME volumes: - - name: gcp-credentials - secret: - secretName: teleport-gcp-credentials - configMap: name: RELEASE-NAME name: config @@ -398,9 +380,6 @@ should add named PersistentVolumeClaim as volume when in custom mode and persist name: data serviceAccountName: RELEASE-NAME volumes: - - name: gcp-credentials - secret: - secretName: teleport-gcp-credentials - configMap: name: RELEASE-NAME name: config @@ -444,9 +423,6 @@ should add named PersistentVolumeClaim as volume when in custom mode and persist name: data serviceAccountName: RELEASE-NAME volumes: - - name: gcp-credentials - secret: - secretName: teleport-gcp-credentials - configMap: name: RELEASE-NAME name: config @@ -495,9 +471,6 @@ should do enterprise things when when enterprise is set in values: - name: license secret: secretName: license - - name: gcp-credentials - secret: - secretName: teleport-gcp-credentials - configMap: name: RELEASE-NAME name: config @@ -540,9 +513,6 @@ should expose diag port: name: data serviceAccountName: RELEASE-NAME volumes: - - name: gcp-credentials - secret: - secretName: teleport-gcp-credentials - configMap: name: RELEASE-NAME name: config @@ -585,9 +555,6 @@ should have Recreate strategy in standalone mode: name: data serviceAccountName: RELEASE-NAME volumes: - - name: gcp-credentials - secret: - secretName: teleport-gcp-credentials - configMap: name: RELEASE-NAME name: config @@ -642,9 +609,6 @@ should have multiple replicas when replicaCount is set: name: data serviceAccountName: RELEASE-NAME volumes: - - name: gcp-credentials - secret: - secretName: teleport-gcp-credentials - configMap: name: RELEASE-NAME name: config @@ -699,9 +663,6 @@ should mount ConfigMap for config in AWS mode: name: data serviceAccountName: RELEASE-NAME volumes: - - name: gcp-credentials - secret: - secretName: teleport-gcp-credentials - configMap: name: RELEASE-NAME name: config @@ -802,9 +763,6 @@ should mount ConfigMap for config in custom mode: name: data serviceAccountName: RELEASE-NAME volumes: - - name: gcp-credentials - secret: - secretName: teleport-gcp-credentials - configMap: name: RELEASE-NAME name: config @@ -847,9 +805,6 @@ should mount ConfigMap for config in standalone mode: name: data serviceAccountName: RELEASE-NAME volumes: - - name: gcp-credentials - secret: - secretName: teleport-gcp-credentials - configMap: name: RELEASE-NAME name: config @@ -1186,9 +1141,6 @@ should mount cert-manager TLS secret when highAvailability.certManager.enabled i name: data serviceAccountName: RELEASE-NAME volumes: - - name: gcp-credentials - secret: - secretName: teleport-gcp-credentials - name: teleport-tls secret: secretName: teleport-tls @@ -1236,9 +1188,6 @@ should mount extraVolumes and extraVolumeMounts: name: my-mount serviceAccountName: RELEASE-NAME volumes: - - name: gcp-credentials - secret: - secretName: teleport-gcp-credentials - configMap: name: RELEASE-NAME name: config @@ -1293,9 +1242,6 @@ should mount tls.existingCASecretName and set environment when set in values: name: data serviceAccountName: RELEASE-NAME volumes: - - name: gcp-credentials - secret: - secretName: teleport-gcp-credentials - name: teleport-tls secret: secretName: helm-lint-existing-tls-secret @@ -1355,9 +1301,6 @@ should mount tls.existingCASecretName and set extra environment when set in valu name: data serviceAccountName: RELEASE-NAME volumes: - - name: gcp-credentials - secret: - secretName: teleport-gcp-credentials - name: teleport-tls secret: secretName: helm-lint-existing-tls-secret @@ -1409,9 +1352,6 @@ should mount tls.existingSecretName when set in values: name: data serviceAccountName: RELEASE-NAME volumes: - - name: gcp-credentials - secret: - secretName: teleport-gcp-credentials - name: teleport-tls secret: secretName: helm-lint-existing-tls-secret @@ -1457,9 +1397,6 @@ should not add PersistentVolumeClaim as volume when in custom mode and persisten name: data serviceAccountName: RELEASE-NAME volumes: - - name: gcp-credentials - secret: - secretName: teleport-gcp-credentials - configMap: name: RELEASE-NAME name: config @@ -1501,9 +1438,6 @@ should not add PersistentVolumeClaim as volume when in standalone mode and persi name: data serviceAccountName: RELEASE-NAME volumes: - - name: gcp-credentials - secret: - secretName: teleport-gcp-credentials - configMap: name: RELEASE-NAME name: config @@ -1546,9 +1480,6 @@ should not add PersistentVolumeClaim as volume when in standalone mode and persi name: data serviceAccountName: RELEASE-NAME volumes: - - name: gcp-credentials - secret: - secretName: teleport-gcp-credentials - configMap: name: RELEASE-NAME name: config @@ -1591,9 +1522,6 @@ should not add PersistentVolumeClaim as volume when in standalone mode and persi name: data serviceAccountName: RELEASE-NAME volumes: - - name: gcp-credentials - secret: - secretName: teleport-gcp-credentials - configMap: name: RELEASE-NAME name: config @@ -1635,9 +1563,6 @@ should not do enterprise things when when enterprise is not set in values: name: data serviceAccountName: RELEASE-NAME volumes: - - name: gcp-credentials - secret: - secretName: teleport-gcp-credentials - configMap: name: RELEASE-NAME name: config @@ -1680,9 +1605,6 @@ should not have more than one replica in standalone mode: name: data serviceAccountName: RELEASE-NAME volumes: - - name: gcp-credentials - secret: - secretName: teleport-gcp-credentials - configMap: name: RELEASE-NAME name: config @@ -1737,9 +1659,6 @@ should not have strategy in AWS mode: name: data serviceAccountName: RELEASE-NAME volumes: - - name: gcp-credentials - secret: - secretName: teleport-gcp-credentials - configMap: name: RELEASE-NAME name: config @@ -1840,9 +1759,6 @@ should not have strategy in custom mode: name: data serviceAccountName: RELEASE-NAME volumes: - - name: gcp-credentials - secret: - secretName: teleport-gcp-credentials - configMap: name: RELEASE-NAME name: config @@ -1885,9 +1801,6 @@ should not mount TLS secrets when when highAvailability.certManager.enabled is f name: data serviceAccountName: RELEASE-NAME volumes: - - name: gcp-credentials - secret: - secretName: teleport-gcp-credentials - configMap: name: RELEASE-NAME name: config @@ -1930,9 +1843,6 @@ should not set securityContext when is empty object (default value): name: data serviceAccountName: RELEASE-NAME volumes: - - name: gcp-credentials - secret: - secretName: teleport-gcp-credentials - configMap: name: RELEASE-NAME name: config @@ -2003,9 +1913,6 @@ should provision initContainer correctly when set in values: name: data serviceAccountName: RELEASE-NAME volumes: - - name: gcp-credentials - secret: - secretName: teleport-gcp-credentials - configMap: name: RELEASE-NAME name: config @@ -2057,9 +1964,6 @@ should set affinity when set in values: name: data serviceAccountName: RELEASE-NAME volumes: - - name: gcp-credentials - secret: - secretName: teleport-gcp-credentials - configMap: name: RELEASE-NAME name: config @@ -2105,9 +2009,6 @@ should set environment when extraEnv set in values: name: data serviceAccountName: RELEASE-NAME volumes: - - name: gcp-credentials - secret: - secretName: teleport-gcp-credentials - configMap: name: RELEASE-NAME name: config @@ -2150,9 +2051,6 @@ should set imagePullPolicy when set in values: name: data serviceAccountName: RELEASE-NAME volumes: - - name: gcp-credentials - secret: - secretName: teleport-gcp-credentials - configMap: name: RELEASE-NAME name: config @@ -2201,9 +2099,6 @@ should set postStart command if set in values: name: data serviceAccountName: RELEASE-NAME volumes: - - name: gcp-credentials - secret: - secretName: teleport-gcp-credentials - configMap: name: RELEASE-NAME name: config @@ -2247,9 +2142,6 @@ should set priorityClassName when set in values: priorityClassName: system-cluster-critical serviceAccountName: RELEASE-NAME volumes: - - name: gcp-credentials - secret: - secretName: teleport-gcp-credentials - configMap: name: RELEASE-NAME name: config @@ -2292,9 +2184,6 @@ should set probeTimeoutSeconds when set in values: name: data serviceAccountName: RELEASE-NAME volumes: - - name: gcp-credentials - secret: - secretName: teleport-gcp-credentials - configMap: name: RELEASE-NAME name: config @@ -2347,9 +2236,6 @@ should set required affinity when highAvailability.requireAntiAffinity is set: name: data serviceAccountName: RELEASE-NAME volumes: - - name: gcp-credentials - secret: - secretName: teleport-gcp-credentials - configMap: name: RELEASE-NAME name: config @@ -2398,9 +2284,6 @@ should set resources when set in values: name: data serviceAccountName: RELEASE-NAME volumes: - - name: gcp-credentials - secret: - secretName: teleport-gcp-credentials - configMap: name: RELEASE-NAME name: config @@ -2450,9 +2333,6 @@ should set securityContext when set in values: name: data serviceAccountName: RELEASE-NAME volumes: - - name: gcp-credentials - secret: - secretName: teleport-gcp-credentials - configMap: name: RELEASE-NAME name: config @@ -2516,9 +2396,6 @@ should set tolerations when set in values: operator: Equal value: teleport volumes: - - name: gcp-credentials - secret: - secretName: teleport-gcp-credentials - configMap: name: RELEASE-NAME name: config diff --git a/examples/chart/teleport-kube-agent/templates/config.yaml b/examples/chart/teleport-kube-agent/templates/config.yaml index 6b3671d551866..2d55ae7ff8490 100644 --- a/examples/chart/teleport-kube-agent/templates/config.yaml +++ b/examples/chart/teleport-kube-agent/templates/config.yaml @@ -19,9 +19,10 @@ metadata: {{- end }} data: teleport.yaml: | + version: v3 teleport: auth_token: "/etc/teleport-secrets/auth-token" - auth_servers: ["{{ required "proxyAddr is required in chart values" .Values.proxyAddr }}"] + proxy_server: {{ required "proxyAddr is required in chart values" .Values.proxyAddr }} {{- if .Values.caPin }} ca_pin: {{- toYaml .Values.caPin | nindent 8 }} {{- end }} diff --git a/examples/chart/teleport-kube-agent/tests/__snapshot__/config_test.yaml.snap b/examples/chart/teleport-kube-agent/tests/__snapshot__/config_test.yaml.snap index 8685b04c1a330..7c78560e42476 100644 --- a/examples/chart/teleport-kube-agent/tests/__snapshot__/config_test.yaml.snap +++ b/examples/chart/teleport-kube-agent/tests/__snapshot__/config_test.yaml.snap @@ -3,9 +3,10 @@ does not generate a config for clusterrole.yaml: apiVersion: v1 data: teleport.yaml: | + version: v3 teleport: auth_token: "/etc/teleport-secrets/auth-token" - auth_servers: ["proxy.example.com:3080"] + proxy_server: proxy.example.com:3080 log: severity: INFO output: stderr @@ -38,9 +39,10 @@ does not generate a config for pdb.yaml: apiVersion: v1 data: teleport.yaml: | + version: v3 teleport: auth_token: "/etc/teleport-secrets/auth-token" - auth_servers: ["proxy.example.com:3080"] + proxy_server: proxy.example.com:3080 log: severity: INFO output: stderr @@ -73,9 +75,10 @@ matches snapshot and tests for annotations.yaml: apiVersion: v1 data: teleport.yaml: | + version: v3 teleport: auth_token: "/etc/teleport-secrets/auth-token" - auth_servers: ["proxy.example.com:3080"] + proxy_server: proxy.example.com:3080 log: severity: INFO output: stderr @@ -111,9 +114,10 @@ matches snapshot and tests for extra-labels.yaml: apiVersion: v1 data: teleport.yaml: | + version: v3 teleport: auth_token: "/etc/teleport-secrets/auth-token" - auth_servers: ["proxy.example.com:3080"] + proxy_server: proxy.example.com:3080 log: severity: INFO output: stderr @@ -149,9 +153,10 @@ matches snapshot for affinity.yaml: apiVersion: v1 data: teleport.yaml: | + version: v3 teleport: auth_token: "/etc/teleport-secrets/auth-token" - auth_servers: ["proxy.example.com:3080"] + proxy_server: proxy.example.com:3080 log: severity: INFO output: stderr @@ -184,9 +189,10 @@ matches snapshot for all-v6.yaml: apiVersion: v1 data: teleport.yaml: | + version: v3 teleport: auth_token: "/etc/teleport-secrets/auth-token" - auth_servers: ["proxy.example.com:3080"] + proxy_server: proxy.example.com:3080 log: severity: INFO output: stderr @@ -235,9 +241,10 @@ matches snapshot for aws-databases.yaml: apiVersion: v1 data: teleport.yaml: | + version: v3 teleport: auth_token: "/etc/teleport-secrets/auth-token" - auth_servers: ["proxy.example.com:3080"] + proxy_server: proxy.example.com:3080 log: severity: INFO output: stderr @@ -282,9 +289,10 @@ matches snapshot for backwards-compatibility.yaml: apiVersion: v1 data: teleport.yaml: | + version: v3 teleport: auth_token: "/etc/teleport-secrets/auth-token" - auth_servers: ["proxy.example.com:3080"] + proxy_server: proxy.example.com:3080 log: severity: INFO output: stderr @@ -317,9 +325,10 @@ matches snapshot for ca-pin.yaml: apiVersion: v1 data: teleport.yaml: | + version: v3 teleport: auth_token: "/etc/teleport-secrets/auth-token" - auth_servers: ["proxy.example.com:3080"] + proxy_server: proxy.example.com:3080 ca_pin: - sha256:7e12c17c20d9cb504bbcb3f0236be3f446861f1396dcbb44425fe28ec1c108f1 log: @@ -354,9 +363,10 @@ matches snapshot for db.yaml: apiVersion: v1 data: teleport.yaml: | + version: v3 teleport: auth_token: "/etc/teleport-secrets/auth-token" - auth_servers: ["proxy.example.com:3080"] + proxy_server: proxy.example.com:3080 log: severity: INFO output: stderr @@ -394,9 +404,10 @@ matches snapshot for dynamic-app.yaml: apiVersion: v1 data: teleport.yaml: | + version: v3 teleport: auth_token: "/etc/teleport-secrets/auth-token" - auth_servers: ["proxy.example.com:3080"] + proxy_server: proxy.example.com:3080 log: severity: INFO output: stderr @@ -431,9 +442,10 @@ matches snapshot for dynamic-db.yaml: apiVersion: v1 data: teleport.yaml: | + version: v3 teleport: auth_token: "/etc/teleport-secrets/auth-token" - auth_servers: ["proxy.example.com:3080"] + proxy_server: proxy.example.com:3080 log: severity: INFO output: stderr @@ -468,9 +480,10 @@ matches snapshot for imagepullsecrets.yaml: apiVersion: v1 data: teleport.yaml: | + version: v3 teleport: auth_token: "/etc/teleport-secrets/auth-token" - auth_servers: ["proxy.example.com:3080"] + proxy_server: proxy.example.com:3080 log: severity: INFO output: stderr @@ -503,9 +516,10 @@ matches snapshot for initcontainers.yaml: apiVersion: v1 data: teleport.yaml: | + version: v3 teleport: auth_token: "/etc/teleport-secrets/auth-token" - auth_servers: ["proxy.example.com:3080"] + proxy_server: proxy.example.com:3080 log: severity: INFO output: stderr @@ -538,9 +552,10 @@ matches snapshot for log-basic.yaml: apiVersion: v1 data: teleport.yaml: | + version: v3 teleport: auth_token: "/etc/teleport-secrets/auth-token" - auth_servers: ["proxy.example.com:3080"] + proxy_server: proxy.example.com:3080 log: severity: INFO output: stderr @@ -573,9 +588,10 @@ matches snapshot for log-extra.yaml: apiVersion: v1 data: teleport.yaml: | + version: v3 teleport: auth_token: "/etc/teleport-secrets/auth-token" - auth_servers: ["proxy.example.com:3080"] + proxy_server: proxy.example.com:3080 log: severity: DEBUG output: /var/lib/teleport/test.log @@ -608,9 +624,10 @@ matches snapshot for log-legacy.yaml: apiVersion: v1 data: teleport.yaml: | + version: v3 teleport: auth_token: "/etc/teleport-secrets/auth-token" - auth_servers: ["proxy.example.com:3080"] + proxy_server: proxy.example.com:3080 log: severity: DEBUG output: stderr @@ -643,9 +660,10 @@ matches snapshot for node-selector.yaml: apiVersion: v1 data: teleport.yaml: | + version: v3 teleport: auth_token: "/etc/teleport-secrets/auth-token" - auth_servers: ["proxy.example.com:3080"] + proxy_server: proxy.example.com:3080 log: severity: INFO output: stderr @@ -678,9 +696,10 @@ matches snapshot for pdb.yaml: apiVersion: v1 data: teleport.yaml: | + version: v3 teleport: auth_token: "/etc/teleport-secrets/auth-token" - auth_servers: ["proxy.example.com:3080"] + proxy_server: proxy.example.com:3080 log: severity: DEBUG output: /var/lib/teleport/test.log @@ -713,9 +732,10 @@ matches snapshot for resources.yaml: apiVersion: v1 data: teleport.yaml: | + version: v3 teleport: auth_token: "/etc/teleport-secrets/auth-token" - auth_servers: ["proxy.example.com:3080"] + proxy_server: proxy.example.com:3080 log: severity: INFO output: stderr @@ -748,9 +768,10 @@ matches snapshot for stateful.yaml: apiVersion: v1 data: teleport.yaml: | + version: v3 teleport: auth_token: "/etc/teleport-secrets/auth-token" - auth_servers: ["proxy.example.com:3080"] + proxy_server: proxy.example.com:3080 log: severity: INFO output: stderr @@ -783,9 +804,10 @@ matches snapshot for tolerations.yaml: apiVersion: v1 data: teleport.yaml: | + version: v3 teleport: auth_token: "/etc/teleport-secrets/auth-token" - auth_servers: ["proxy.example.com:3080"] + proxy_server: proxy.example.com:3080 log: severity: INFO output: stderr @@ -818,9 +840,10 @@ matches snapshot for volumes.yaml: apiVersion: v1 data: teleport.yaml: | + version: v3 teleport: auth_token: "/etc/teleport-secrets/auth-token" - auth_servers: ["proxy.example.com:3080"] + proxy_server: proxy.example.com:3080 log: severity: INFO output: stderr diff --git a/examples/chart/teleport-kube-agent/tests/__snapshot__/deployment_test.yaml.snap b/examples/chart/teleport-kube-agent/tests/__snapshot__/deployment_test.yaml.snap index 845525bea9d71..d27d35670bf9e 100644 --- a/examples/chart/teleport-kube-agent/tests/__snapshot__/deployment_test.yaml.snap +++ b/examples/chart/teleport-kube-agent/tests/__snapshot__/deployment_test.yaml.snap @@ -18,7 +18,7 @@ sets Deployment annotations when specified if action is Upgrade: template: metadata: annotations: - checksum/config: 511656bfc4345260ef1ddc4319c2a30ff1e004c72c518c82020a76e088a10cd8 + checksum/config: 40ee068e95f9baae75f3b7f6ef1a62a7ffdf3d9005e74514e597dbd4c4af595e kubernetes.io/pod: test-annotation kubernetes.io/pod-different: 4 labels: @@ -86,7 +86,7 @@ sets Deployment labels when specified if action is Upgrade: template: metadata: annotations: - checksum/config: b37ca9b3da292ffe343a4629c7da7dc006ec03156fc19268123a24df51dfeb78 + checksum/config: e23c34c3027af13bb06e161dfe1fe316312a1d5621ef217502a5c76596e49668 labels: app: RELEASE-NAME app.kubernetes.io/name: teleport-kube-agent diff --git a/examples/chart/teleport-kube-agent/tests/__snapshot__/statefulset_test.yaml.snap b/examples/chart/teleport-kube-agent/tests/__snapshot__/statefulset_test.yaml.snap index cf9f9afab9f39..77cd14b6f1b69 100644 --- a/examples/chart/teleport-kube-agent/tests/__snapshot__/statefulset_test.yaml.snap +++ b/examples/chart/teleport-kube-agent/tests/__snapshot__/statefulset_test.yaml.snap @@ -150,7 +150,7 @@ sets StatefulSet labels when specified: template: metadata: annotations: - checksum/config: b37ca9b3da292ffe343a4629c7da7dc006ec03156fc19268123a24df51dfeb78 + checksum/config: e23c34c3027af13bb06e161dfe1fe316312a1d5621ef217502a5c76596e49668 labels: app: RELEASE-NAME app.kubernetes.io/name: teleport-kube-agent @@ -381,7 +381,7 @@ should add volumeClaimTemplate for data volume when using StatefulSet and is Fre template: metadata: annotations: - checksum/config: b68f736b13876b204549cacfa6683f63942acdfe1e98c43d74f9868eb8f1edff + checksum/config: 85faa83e7e3e6789b109a5d52e61141243de9d7c5e408af802fb5ad544f79698 labels: app: RELEASE-NAME spec: diff --git a/examples/local-cluster/node/teleport.yaml b/examples/local-cluster/node/teleport.yaml index 799e2b22a40fc..f83004dd12c8f 100644 --- a/examples/local-cluster/node/teleport.yaml +++ b/examples/local-cluster/node/teleport.yaml @@ -1,8 +1,8 @@ +version: v3 teleport: nodename: graviton-node auth_token: hello - auth_servers: - - 127.0.0.1:5000 + auth_server: 127.0.0.1:5000 data_dir: .data proxy_service: enabled: "no" diff --git a/examples/local-cluster/proxy/teleport.yaml b/examples/local-cluster/proxy/teleport.yaml index 43dc5b734b9f8..018ce8c8d1f42 100644 --- a/examples/local-cluster/proxy/teleport.yaml +++ b/examples/local-cluster/proxy/teleport.yaml @@ -1,8 +1,8 @@ +version: v3 teleport: nodename: graviton-proxy auth_token: hello - auth_servers: - - 127.0.0.1:5000 + auth_server: 127.0.0.1:5000 data_dir: .data proxy_service: enabled: "yes" diff --git a/integration/appaccess/pack.go b/integration/appaccess/pack.go index 6d0922b3d6ef8..4dbcbb866aa65 100644 --- a/integration/appaccess/pack.go +++ b/integration/appaccess/pack.go @@ -556,12 +556,10 @@ func (p *Pack) startRootAppServers(t *testing.T, count int, extraApps []service. raConf.Log = log raConf.DataDir = t.TempDir() raConf.SetToken("static-token-value") - raConf.AuthServers = []utils.NetAddr{ - { - AddrNetwork: "tcp", - Addr: p.rootCluster.Web, - }, - } + raConf.SetAuthServerAddress(utils.NetAddr{ + AddrNetwork: "tcp", + Addr: p.rootCluster.Web, + }) raConf.Auth.Enabled = false raConf.Proxy.Enabled = false raConf.SSH.Enabled = false @@ -701,12 +699,10 @@ func (p *Pack) startLeafAppServers(t *testing.T, count int, extraApps []service. laConf.Log = log laConf.DataDir = t.TempDir() laConf.SetToken("static-token-value") - laConf.AuthServers = []utils.NetAddr{ - { - AddrNetwork: "tcp", - Addr: p.leafCluster.Web, - }, - } + laConf.SetAuthServerAddress(utils.NetAddr{ + AddrNetwork: "tcp", + Addr: p.leafCluster.Web, + }) laConf.Auth.Enabled = false laConf.Proxy.Enabled = false laConf.SSH.Enabled = false diff --git a/integration/db/fixture.go b/integration/db/fixture.go index 4c93c0ba0aac1..cb7b0b1b9397d 100644 --- a/integration/db/fixture.go +++ b/integration/db/fixture.go @@ -109,12 +109,10 @@ func (pack *databaseClusterPack) StartDatabaseServices(t *testing.T, clock clock conf := service.MakeDefaultConfig() conf.DataDir = filepath.Join(t.TempDir(), pack.name) conf.SetToken("static-token-value") - conf.AuthServers = []utils.NetAddr{ - { - AddrNetwork: "tcp", - Addr: pack.Cluster.Web, - }, - } + conf.SetAuthServerAddress(utils.NetAddr{ + AddrNetwork: "tcp", + Addr: pack.Cluster.Web, + }) conf.Databases.Enabled = true conf.Databases.Databases = []service.Database{ pack.PostgresService, @@ -400,12 +398,10 @@ func (p *DatabasePack) startRootDatabaseAgent(t *testing.T, params databaseAgent conf.DataDir = t.TempDir() conf.SetToken("static-token-value") conf.DiagnosticAddr = *utils.MustParseAddr(helpers.NewListener(t, service.ListenerDiagnostic, &conf.FileDescriptors)) - conf.AuthServers = []utils.NetAddr{ - { - AddrNetwork: "tcp", - Addr: p.Root.Cluster.Web, - }, - } + conf.SetAuthServerAddress(utils.NetAddr{ + AddrNetwork: "tcp", + Addr: p.Root.Cluster.Web, + }) conf.Clock = p.clock conf.Databases.Enabled = true conf.Databases.Databases = params.databases diff --git a/integration/ec2_test.go b/integration/ec2_test.go index 85463c77e5e22..d9d279b9d09f0 100644 --- a/integration/ec2_test.go +++ b/integration/ec2_test.go @@ -63,7 +63,7 @@ func newNodeConfig(t *testing.T, authAddr utils.NetAddr, tokenName string, joinM config.Auth.Enabled = false config.Proxy.Enabled = false config.DataDir = t.TempDir() - config.AuthServers = append(config.AuthServers, authAddr) + config.SetAuthServerAddress(authAddr) config.Log = newSilentLogger() config.CircuitBreakerConfig = breaker.NoopBreakerConfig() return config @@ -84,7 +84,7 @@ func newProxyConfig(t *testing.T, authAddr utils.NetAddr, tokenName string, join config.Proxy.EnableProxyProtocol = true config.DataDir = t.TempDir() - config.AuthServers = append(config.AuthServers, authAddr) + config.SetAuthServerAddress(authAddr) config.Log = newSilentLogger() config.CircuitBreakerConfig = breaker.NoopBreakerConfig() return config @@ -107,7 +107,7 @@ func newAuthConfig(t *testing.T, clock clockwork.Clock) *service.Config { ClusterName: "testcluster", }) require.NoError(t, err) - config.AuthServers = append(config.AuthServers, config.Auth.ListenAddr) + config.SetAuthServerAddress(config.Auth.ListenAddr) config.Auth.StorageConfig = storageConfig config.Auth.NetworkingConfig.SetProxyListenerMode(types.ProxyListenerMode_Multiplex) config.Auth.StaticTokens, err = types.NewStaticTokens(types.StaticTokensSpecV2{ @@ -342,7 +342,7 @@ func TestEC2Labels(t *testing.T) { tconf.Proxy.DisableWebInterface = true tconf.Auth.StorageConfig = storageConfig tconf.Auth.ListenAddr.Addr = helpers.NewListener(t, service.ListenerAuth, &tconf.FileDescriptors) - tconf.AuthServers = append(tconf.AuthServers, tconf.Auth.ListenAddr) + tconf.SetAuthServerAddress(tconf.Auth.ListenAddr) tconf.SSH.Enabled = true tconf.SSH.Addr.Addr = helpers.NewListener(t, service.ListenerNodeSSH, &tconf.FileDescriptors) @@ -447,7 +447,7 @@ func TestEC2Hostname(t *testing.T) { tconf.Proxy.WebAddr.Addr = helpers.NewListener(t, service.ListenerProxyWeb, &tconf.FileDescriptors) tconf.Auth.StorageConfig = storageConfig tconf.Auth.ListenAddr.Addr = helpers.NewListener(t, service.ListenerAuth, &tconf.FileDescriptors) - tconf.AuthServers = append(tconf.AuthServers, tconf.Auth.ListenAddr) + tconf.SetAuthServerAddress(tconf.Auth.ListenAddr) tconf.SSH.Enabled = true tconf.SSH.Addr.Addr = helpers.NewListener(t, service.ListenerNodeSSH, &tconf.FileDescriptors) diff --git a/integration/helpers/instance.go b/integration/helpers/instance.go index ffcaccfd8e02b..c1ea4000ea71e 100644 --- a/integration/helpers/instance.go +++ b/integration/helpers/instance.go @@ -508,7 +508,7 @@ func (i *TeleInstance) GenerateConfig(t *testing.T, trustedSecrets []*InstanceSe tconf.Proxy.MongoAddr.Addr = i.Mongo } } - tconf.AuthServers = append(tconf.AuthServers, tconf.Auth.ListenAddr) + tconf.SetAuthServerAddress(tconf.Auth.ListenAddr) tconf.Auth.StorageConfig = backend.Config{ Type: lite.GetName(), Params: backend.Params{"path": dataDir + string(os.PathListSeparator) + defaults.BackendDir, "poll_stream_period": 50 * time.Millisecond}, @@ -618,8 +618,18 @@ func (i *TeleInstance) StartNodeWithTargetPort(tconf *service.Config, authPort s tconf.DataDir = dataDir - authServer := utils.MustParseAddr(net.JoinHostPort(i.Hostname, authPort)) - tconf.AuthServers = append(tconf.AuthServers, *authServer) + if tconf.Version == defaults.TeleportConfigVersionV3 { + if tconf.ProxyServer.IsEmpty() { + authServer := utils.MustParseAddr(net.JoinHostPort(i.Hostname, authPort)) + tconf.SetAuthServerAddress(*authServer) + } + } else { + authServer := utils.MustParseAddr(net.JoinHostPort(i.Hostname, authPort)) + if err := tconf.SetAuthServerAddresses(append(tconf.AuthServerAddresses(), *authServer)); err != nil { + return nil, err + } + } + tconf.SetToken("token") tconf.UploadEventsC = i.UploadEventsC tconf.CachePolicy = service.CachePolicy{ @@ -671,12 +681,10 @@ func (i *TeleInstance) StartApp(conf *service.Config) (*service.TeleportProcess, i.tempDirs = append(i.tempDirs, dataDir) conf.DataDir = dataDir - conf.AuthServers = []utils.NetAddr{ - { - AddrNetwork: "tcp", - Addr: i.Web, - }, - } + conf.SetAuthServerAddress(utils.NetAddr{ + AddrNetwork: "tcp", + Addr: i.Web, + }) conf.SetToken("token") conf.UploadEventsC = i.UploadEventsC conf.Auth.Enabled = false @@ -723,12 +731,10 @@ func (i *TeleInstance) StartApps(configs []*service.Config) ([]*service.Teleport } cfg.DataDir = dataDir - cfg.AuthServers = []utils.NetAddr{ - { - AddrNetwork: "tcp", - Addr: i.Web, - }, - } + cfg.SetAuthServerAddress(utils.NetAddr{ + AddrNetwork: "tcp", + Addr: i.Web, + }) cfg.SetToken("token") cfg.UploadEventsC = i.UploadEventsC cfg.Auth.Enabled = false @@ -787,12 +793,10 @@ func (i *TeleInstance) StartDatabase(conf *service.Config) (*service.TeleportPro i.tempDirs = append(i.tempDirs, dataDir) conf.DataDir = dataDir - conf.AuthServers = []utils.NetAddr{ - { - AddrNetwork: "tcp", - Addr: i.Web, - }, - } + conf.SetAuthServerAddress(utils.NetAddr{ + AddrNetwork: "tcp", + Addr: i.Web, + }) conf.SetToken("token") conf.UploadEventsC = i.UploadEventsC conf.Auth.Enabled = false @@ -850,12 +854,10 @@ func (i *TeleInstance) StartKube(t *testing.T, conf *service.Config, clusterName i.tempDirs = append(i.tempDirs, dataDir) conf.DataDir = dataDir - conf.AuthServers = []utils.NetAddr{ - { - AddrNetwork: "tcp", - Addr: i.Web, - }, - } + conf.SetAuthServerAddress(utils.NetAddr{ + AddrNetwork: "tcp", + Addr: i.Web, + }) conf.SetToken("token") conf.UploadEventsC = i.UploadEventsC conf.Auth.Enabled = false @@ -903,7 +905,7 @@ func (i *TeleInstance) StartNodeAndProxy(t *testing.T, name string) (sshPort, we tconf.Log = i.Log authServer := utils.MustParseAddr(i.Auth) - tconf.AuthServers = append(tconf.AuthServers, *authServer) + tconf.SetAuthServerAddress(*authServer) tconf.SetToken("token") tconf.HostUUID = name tconf.Hostname = name @@ -994,7 +996,7 @@ func (i *TeleInstance) StartProxy(cfg ProxyConfig) (reversetunnel.Server, *servi tconf.Console = nil tconf.Log = i.Log authServer := utils.MustParseAddr(i.Auth) - tconf.AuthServers = append(tconf.AuthServers, *authServer) + tconf.SetAuthServerAddress(*authServer) tconf.CachePolicy = service.CachePolicy{Enabled: true} tconf.DataDir = dataDir tconf.UploadEventsC = i.UploadEventsC diff --git a/integration/hsm/hsm_test.go b/integration/hsm/hsm_test.go index d1475c0818bf8..a518fac608dbb 100644 --- a/integration/hsm/hsm_test.go +++ b/integration/hsm/hsm_test.go @@ -253,7 +253,7 @@ func newHSMAuthConfig(ctx context.Context, t *testing.T, storageConfig *backend. ClusterName: "testcluster", }) require.NoError(t, err) - config.AuthServers = append(config.AuthServers, config.Auth.ListenAddr) + config.SetAuthServerAddress(config.Auth.ListenAddr) config.Auth.StaticTokens, err = types.NewStaticTokens(types.StaticTokensSpecV2{ StaticTokens: []types.ProvisionTokenV1{ { @@ -291,7 +291,7 @@ func newProxyConfig(ctx context.Context, t *testing.T, authAddr utils.NetAddr, l config.PollingPeriod = 1 * time.Second config.ShutdownTimeout = time.Minute config.DataDir = t.TempDir() - config.AuthServers = append(config.AuthServers, authAddr) + config.SetAuthServerAddress(authAddr) config.CircuitBreakerConfig = breaker.NoopBreakerConfig() config.Log = log return config diff --git a/integration/integration_test.go b/integration/integration_test.go index 4c6d469479511..8b7139ececab6 100644 --- a/integration/integration_test.go +++ b/integration/integration_test.go @@ -720,12 +720,10 @@ func (s *integrationTestSuite) newTeleportIoT(t *testing.T, logins []string) *he tconf := s.defaultServiceConfig() tconf.Hostname = Host tconf.SetToken("token") - tconf.AuthServers = []utils.NetAddr{ - { - AddrNetwork: "tcp", - Addr: main.Web, - }, - } + tconf.SetAuthServerAddress(utils.NetAddr{ + AddrNetwork: "tcp", + Addr: main.Web, + }) tconf.Auth.Enabled = false @@ -2695,12 +2693,10 @@ func testTrustedTunnelNode(t *testing.T, suite *integrationTestSuite) { tconf := suite.defaultServiceConfig() tconf.Hostname = tunnelNodeHostname tconf.SetToken("token") - tconf.AuthServers = []utils.NetAddr{ - { - AddrNetwork: "tcp", - Addr: aux.Web, - }, - } + tconf.SetAuthServerAddress(utils.NetAddr{ + AddrNetwork: "tcp", + Addr: aux.Web, + }) tconf.Auth.Enabled = false tconf.Proxy.Enabled = false tconf.SSH.Enabled = true @@ -3107,12 +3103,10 @@ func testReverseTunnelCollapse(t *testing.T, suite *integrationTestSuite) { tconf := suite.defaultServiceConfig() tconf.Hostname = "cluster-main-node" tconf.SetToken("token") - tconf.AuthServers = []utils.NetAddr{ - { - AddrNetwork: "tcp", - Addr: proxyConfig.WebAddr, - }, - } + tconf.SetAuthServerAddress(utils.NetAddr{ + AddrNetwork: "tcp", + Addr: proxyConfig.WebAddr, + }) tconf.Auth.Enabled = false tconf.Proxy.Enabled = false tconf.SSH.Enabled = true @@ -3248,12 +3242,10 @@ func testDiscoveryNode(t *testing.T, suite *integrationTestSuite) { tconf := suite.defaultServiceConfig() tconf.Hostname = "cluster-main-node" tconf.SetToken("token") - tconf.AuthServers = []utils.NetAddr{ - { - AddrNetwork: "tcp", - Addr: main.Web, - }, - } + tconf.SetAuthServerAddress(utils.NetAddr{ + AddrNetwork: "tcp", + Addr: main.Web, + }) tconf.Auth.Enabled = false @@ -6303,9 +6295,7 @@ func testListResourcesAcrossClusters(t *testing.T, suite *integrationTestSuite) conf.DataDir = t.TempDir() conf.SetToken("token") conf.UploadEventsC = i.UploadEventsC - conf.AuthServers = []utils.NetAddr{ - *utils.MustParseAddr(net.JoinHostPort(i.Hostname, helpers.PortStr(t, i.Web))), - } + conf.SetAuthServerAddress(*utils.MustParseAddr(net.JoinHostPort(i.Hostname, helpers.PortStr(t, i.Web)))) conf.HostUUID = name conf.Hostname = name conf.SSH.Enabled = true diff --git a/integration/proxy/proxy_helpers.go b/integration/proxy/proxy_helpers.go index 19a42e8d980fe..d6738a3b70905 100644 --- a/integration/proxy/proxy_helpers.go +++ b/integration/proxy/proxy_helpers.go @@ -178,12 +178,10 @@ func (p *Suite) addNodeToLeafCluster(t *testing.T, tunnelNodeHostname string) { tconf.Log = utils.NewLoggerForTests() tconf.Hostname = tunnelNodeHostname tconf.SetToken("token") - tconf.AuthServers = []utils.NetAddr{ - { - AddrNetwork: "tcp", - Addr: p.leaf.Web, - }, - } + tconf.SetAuthServerAddress(utils.NetAddr{ + AddrNetwork: "tcp", + Addr: p.leaf.Web, + }) tconf.Auth.Enabled = false tconf.Proxy.Enabled = false tconf.SSH.Enabled = true @@ -513,16 +511,12 @@ func mustStartALPNLocalProxyWithConfig(t *testing.T, config alpnproxy.LocalProxy return lp } -func makeNodeConfig(nodeName, authAddr string) *service.Config { +func makeNodeConfig(nodeName, proxyAddr string) *service.Config { nodeConfig := service.MakeDefaultConfig() + nodeConfig.Version = defaults.TeleportConfigVersionV3 nodeConfig.Hostname = nodeName nodeConfig.SetToken("token") - nodeConfig.AuthServers = []utils.NetAddr{ - { - AddrNetwork: "tcp", - Addr: authAddr, - }, - } + nodeConfig.ProxyServer = *utils.MustParseAddr(proxyAddr) nodeConfig.Auth.Enabled = false nodeConfig.Proxy.Enabled = false nodeConfig.SSH.Enabled = true diff --git a/integration/proxy/proxy_tunnel_strategy_test.go b/integration/proxy/proxy_tunnel_strategy_test.go index 745b8642c5a19..2a236c2d6fdf3 100644 --- a/integration/proxy/proxy_tunnel_strategy_test.go +++ b/integration/proxy/proxy_tunnel_strategy_test.go @@ -329,7 +329,7 @@ func (p *proxyTunnelStrategy) makeProxy(t *testing.T) { authAddr := utils.MustParseAddr(p.auth.Auth) conf := service.MakeDefaultConfig() - conf.AuthServers = append(conf.AuthServers, *authAddr) + conf.SetAuthServerAddress(*authAddr) conf.SetToken("token") conf.DataDir = t.TempDir() @@ -372,7 +372,7 @@ func (p *proxyTunnelStrategy) makeNode(t *testing.T) { }) conf := service.MakeDefaultConfig() - conf.AuthServers = append(conf.AuthServers, utils.FromAddr(p.lb.Addr())) + conf.SetAuthServerAddress(utils.FromAddr(p.lb.Addr())) conf.SetToken("token") conf.DataDir = t.TempDir() @@ -414,7 +414,7 @@ func (p *proxyTunnelStrategy) makeDatabase(t *testing.T) { }) conf := service.MakeDefaultConfig() - conf.AuthServers = append(conf.AuthServers, utils.FromAddr(p.lb.Addr())) + conf.SetAuthServerAddress(utils.FromAddr(p.lb.Addr())) conf.SetToken("token") conf.DataDir = t.TempDir() diff --git a/lib/auth/bot_test.go b/lib/auth/bot_test.go index edf662ed1a30f..f263061273316 100644 --- a/lib/auth/bot_test.go +++ b/lib/auth/bot_test.go @@ -226,7 +226,7 @@ func TestRegisterBotOnboardFeatureDisabled(t *testing.T) { ID: IdentityID{ Role: types.RoleBot, }, - Servers: []utils.NetAddr{*utils.MustParseAddr(srv.Addr().String())}, + AuthServers: []utils.NetAddr{*utils.MustParseAddr(srv.Addr().String())}, PublicTLSKey: tlsPublicKey, PublicSSHKey: publicKey, }) @@ -291,7 +291,7 @@ func TestRegisterBotCertificateGenerationCheck(t *testing.T) { ID: IdentityID{ Role: types.RoleBot, }, - Servers: []utils.NetAddr{*utils.MustParseAddr(srv.Addr().String())}, + AuthServers: []utils.NetAddr{*utils.MustParseAddr(srv.Addr().String())}, PublicTLSKey: tlsPublicKey, PublicSSHKey: publicKey, }) @@ -348,7 +348,7 @@ func TestRegisterBotCertificateGenerationStolen(t *testing.T) { ID: IdentityID{ Role: types.RoleBot, }, - Servers: []utils.NetAddr{*utils.MustParseAddr(srv.Addr().String())}, + AuthServers: []utils.NetAddr{*utils.MustParseAddr(srv.Addr().String())}, PublicTLSKey: tlsPublicKey, PublicSSHKey: publicKey, }) diff --git a/lib/auth/join_test.go b/lib/auth/join_test.go index e2db930261245..a9be6260fe7ad 100644 --- a/lib/auth/join_test.go +++ b/lib/auth/join_test.go @@ -344,7 +344,7 @@ func TestRegister_Bot(t *testing.T) { ID: IdentityID{ Role: types.RoleBot, }, - Servers: []utils.NetAddr{*utils.MustParseAddr(srv.Addr().String())}, + AuthServers: []utils.NetAddr{*utils.MustParseAddr(srv.Addr().String())}, PublicTLSKey: tlsPublicKey, PublicSSHKey: publicKey, }) diff --git a/lib/auth/register.go b/lib/auth/register.go index 837bfdec12389..173fa7f975c66 100644 --- a/lib/auth/register.go +++ b/lib/auth/register.go @@ -91,8 +91,10 @@ type RegisterParams struct { Token string // ID is identity ID ID IdentityID - // Servers is a list of auth servers to dial - Servers []utils.NetAddr + // AuthServers is a list of auth servers to dial + AuthServers []utils.NetAddr + // ProxyServer is a proxy server to dial + ProxyServer utils.NetAddr // AdditionalPrincipals is a list of additional principals to dial AdditionalPrincipals []string // DNSNames is a list of DNS names to add to x509 certificate @@ -124,10 +126,31 @@ type RegisterParams struct { FIPS bool } -func (r *RegisterParams) setDefaults() { +func (r *RegisterParams) checkAndSetDefaults() error { if r.Clock == nil { r.Clock = clockwork.NewRealClock() } + + if err := r.verifyAuthOrProxyAddress(); err != nil { + return trace.BadParameter("no auth or proxy servers set") + } + + return nil +} + +func (r *RegisterParams) verifyAuthOrProxyAddress() error { + haveAuthServers := len(r.AuthServers) > 0 + haveProxyServer := !r.ProxyServer.IsEmpty() + + if !haveAuthServers && !haveProxyServer { + return trace.BadParameter("no auth or proxy servers set") + } + + if haveAuthServers && haveProxyServer { + return trace.BadParameter("only one of auth or proxy server should be set") + } + + return nil } // CredGetter is an interface for a client that can be used to get host @@ -140,7 +163,9 @@ type HostCredentials func(context.Context, string, bool, types.RegisterUsingToke // tokens to prove a valid auth server was used to issue the joining request // as well as a method for the node to validate the auth server. func Register(params RegisterParams) (*proto.Certs, error) { - params.setDefaults() + if err := params.checkAndSetDefaults(); err != nil { + return nil, trace.Wrap(err) + } // Read in the token. The token can either be passed in or come from a file // on disk. token, err := utils.TryReadValueAsFile(params.Token) @@ -163,22 +188,34 @@ func Register(params RegisterParams) (*proto.Certs, error) { } } - log.WithField("auth-servers", params.Servers).Debugf("Registering node to the cluster.") - type registerMethod struct { call func(token string, params RegisterParams) (*proto.Certs, error) desc string } + registerThroughAuth := registerMethod{registerThroughAuth, "with auth server"} registerThroughProxy := registerMethod{registerThroughProxy, "via proxy server"} registerMethods := []registerMethod{registerThroughAuth, registerThroughProxy} - if params.GetHostCredentials == nil { - log.Debugf("Missing client, it is not possible to register through proxy.") - registerMethods = []registerMethod{registerThroughAuth} - } else if authServerIsProxy(params.Servers) { - log.Debugf("The first specified auth server appears to be a proxy.") - registerMethods = []registerMethod{registerThroughProxy, registerThroughAuth} + + if !params.ProxyServer.IsEmpty() { + log.WithField("proxy-server", params.ProxyServer).Debugf("Registering node to the cluster.") + + registerMethods = []registerMethod{registerThroughProxy} + + if proxyServerIsAuth(params.ProxyServer) { + log.Debugf("The specified proxy server appears to be an auth server.") + } + } else { + log.WithField("auth-servers", params.AuthServers).Debugf("Registering node to the cluster.") + + if params.GetHostCredentials == nil { + log.Debugf("Missing client, it is not possible to register through proxy.") + registerMethods = []registerMethod{registerThroughAuth} + } else if authServerIsProxy(params.AuthServers) { + log.Debugf("The first specified auth server appears to be a proxy.") + registerMethods = []registerMethod{registerThroughProxy, registerThroughAuth} + } } var collectedErrs []error @@ -206,12 +243,15 @@ func authServerIsProxy(servers []utils.NetAddr) bool { return port == defaults.HTTPListenPort || port == teleport.StandardHTTPSPort } +// proxyServerIsAuth returns true if the address given to register with +// appears to be an auth server. +func proxyServerIsAuth(server utils.NetAddr) bool { + port := server.Port(0) + return port == defaults.AuthListenPort +} + // registerThroughProxy is used to register through the proxy server. func registerThroughProxy(token string, params RegisterParams) (*proto.Certs, error) { - if len(params.Servers) == 0 { - return nil, trace.BadParameter("no auth servers set") - } - var certs *proto.Certs if params.JoinMethod == types.JoinMethodIAM { // IAM join method requires gRPC client @@ -228,7 +268,7 @@ func registerThroughProxy(token string, params RegisterParams) (*proto.Certs, er // params to call proxy HTTP endpoint var err error certs, err = params.GetHostCredentials(context.Background(), - params.Servers[0].String(), + getHostAddresses(params)[0], lib.IsInsecureDevMode(), types.RegisterUsingTokenRequest{ Token: token, @@ -248,6 +288,14 @@ func registerThroughProxy(token string, params RegisterParams) (*proto.Certs, er return certs, nil } +func getHostAddresses(params RegisterParams) []string { + if !params.ProxyServer.IsEmpty() { + return []string{params.ProxyServer.String()} + } + + return utils.NetAddrsToStrings(params.AuthServers) +} + // registerThroughAuth is used to register through the auth server. func registerThroughAuth(token string, params RegisterParams) (*proto.Certs, error) { var client *Client @@ -295,10 +343,6 @@ func registerThroughAuth(token string, params RegisterParams) (*proto.Certs, err // proxy. The Proxy's TLS cert will be verified using the host's root CA pool // (PKI) unless the --insecure flag was passed. func proxyJoinServiceClient(params RegisterParams) (*client.JoinServiceClient, error) { - if len(params.Servers) == 0 { - return nil, trace.BadParameter("no auth servers set") - } - tlsConfig := utils.TLSConfig(params.CipherSuites) tlsConfig.Time = params.Clock.Now // set NextProtos for TLS routing, the actual protocol will be h2 @@ -310,7 +354,7 @@ func proxyJoinServiceClient(params RegisterParams) (*client.JoinServiceClient, e } conn, err := grpc.Dial( - params.Servers[0].String(), + getHostAddresses(params)[0], grpc.WithUnaryInterceptor(metadata.UnaryClientInterceptor), grpc.WithStreamInterceptor(metadata.StreamClientInterceptor), grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig)), @@ -353,7 +397,7 @@ func insecureRegisterClient(params RegisterParams) (*Client, error) { } client, err := NewClient(client.Config{ - Addrs: utils.NetAddrsToStrings(params.Servers), + Addrs: getHostAddresses(params), Credentials: []client.Credentials{ client.LoadTLS(tlsConfig), }, @@ -392,7 +436,7 @@ func pinRegisterClient(params RegisterParams) (*Client, error) { tlsConfig.InsecureSkipVerify = true tlsConfig.Time = params.Clock.Now authClient, err := NewClient(client.Config{ - Addrs: utils.NetAddrsToStrings(params.Servers), + Addrs: getHostAddresses(params), Credentials: []client.Credentials{ client.LoadTLS(tlsConfig), }, @@ -443,7 +487,7 @@ func pinRegisterClient(params RegisterParams) (*Client, error) { tlsConfig.RootCAs = certPool authClient, err = NewClient(client.Config{ - Addrs: utils.NetAddrsToStrings(params.Servers), + Addrs: getHostAddresses(params), Credentials: []client.Credentials{ client.LoadTLS(tlsConfig), }, diff --git a/lib/auth/tls_test.go b/lib/auth/tls_test.go index 01528200d7c09..7cf7d065e68a5 100644 --- a/lib/auth/tls_test.go +++ b/lib/auth/tls_test.go @@ -2777,8 +2777,8 @@ func TestRegisterCAPin(t *testing.T) { // Attempt to register with valid CA pin, should work. _, err = Register(RegisterParams{ - Servers: []utils.NetAddr{utils.FromAddr(tt.server.Addr())}, - Token: token, + AuthServers: []utils.NetAddr{utils.FromAddr(tt.server.Addr())}, + Token: token, ID: IdentityID{ HostUUID: "once", NodeName: "node-name", @@ -2795,8 +2795,8 @@ func TestRegisterCAPin(t *testing.T) { // Attempt to register with multiple CA pins where the auth server only // matches one, should work. _, err = Register(RegisterParams{ - Servers: []utils.NetAddr{utils.FromAddr(tt.server.Addr())}, - Token: token, + AuthServers: []utils.NetAddr{utils.FromAddr(tt.server.Addr())}, + Token: token, ID: IdentityID{ HostUUID: "once", NodeName: "node-name", @@ -2812,8 +2812,8 @@ func TestRegisterCAPin(t *testing.T) { // Attempt to register with invalid CA pin, should fail. _, err = Register(RegisterParams{ - Servers: []utils.NetAddr{utils.FromAddr(tt.server.Addr())}, - Token: token, + AuthServers: []utils.NetAddr{utils.FromAddr(tt.server.Addr())}, + Token: token, ID: IdentityID{ HostUUID: "once", NodeName: "node-name", @@ -2829,8 +2829,8 @@ func TestRegisterCAPin(t *testing.T) { // Attempt to register with multiple invalid CA pins, should fail. _, err = Register(RegisterParams{ - Servers: []utils.NetAddr{utils.FromAddr(tt.server.Addr())}, - Token: token, + AuthServers: []utils.NetAddr{utils.FromAddr(tt.server.Addr())}, + Token: token, ID: IdentityID{ HostUUID: "once", NodeName: "node-name", @@ -2865,8 +2865,8 @@ func TestRegisterCAPin(t *testing.T) { // Attempt to register with multiple CA pins, should work _, err = Register(RegisterParams{ - Servers: []utils.NetAddr{utils.FromAddr(tt.server.Addr())}, - Token: token, + AuthServers: []utils.NetAddr{utils.FromAddr(tt.server.Addr())}, + Token: token, ID: IdentityID{ HostUUID: "once", NodeName: "node-name", @@ -2908,8 +2908,8 @@ func TestRegisterCAPath(t *testing.T) { // Attempt to register with nothing at the CA path, should work. _, err = Register(RegisterParams{ - Servers: []utils.NetAddr{utils.FromAddr(tt.server.Addr())}, - Token: token, + AuthServers: []utils.NetAddr{utils.FromAddr(tt.server.Addr())}, + Token: token, ID: IdentityID{ HostUUID: "once", NodeName: "node-name", @@ -2937,8 +2937,8 @@ func TestRegisterCAPath(t *testing.T) { // Attempt to register with valid CA path, should work. _, err = Register(RegisterParams{ - Servers: []utils.NetAddr{utils.FromAddr(tt.server.Addr())}, - Token: token, + AuthServers: []utils.NetAddr{utils.FromAddr(tt.server.Addr())}, + Token: token, ID: IdentityID{ HostUUID: "once", NodeName: "node-name", diff --git a/lib/client/api_login_test.go b/lib/client/api_login_test.go index 0e3041af0fc2b..fcb148dbc4d8b 100644 --- a/lib/client/api_login_test.go +++ b/lib/client/api_login_test.go @@ -370,7 +370,7 @@ func newStandaloneTeleport(t *testing.T, clock clockwork.Clock) *standaloneBundl cfg.Clock = clock cfg.Console = console cfg.Log = logger - cfg.AuthServers = []utils.NetAddr{randomAddr} // must be present + cfg.SetAuthServerAddress(randomAddr) // must be present cfg.Auth.Preference, err = types.NewAuthPreferenceFromConfigFile(types.AuthPreferenceSpecV2{ Type: constants.Local, SecondFactor: constants.SecondFactorOptional, @@ -453,7 +453,7 @@ func newStandaloneTeleport(t *testing.T, clock clockwork.Clock) *standaloneBundl cfg.Clock = clock cfg.Console = console cfg.Log = logger - cfg.AuthServers = []utils.NetAddr{*authAddr} + cfg.SetAuthServerAddress(*authAddr) cfg.Auth.Enabled = false cfg.Proxy.Enabled = true cfg.Proxy.WebAddr = randomAddr diff --git a/lib/config/configuration.go b/lib/config/configuration.go index 77f74070d3bff..5ff343e965dde 100644 --- a/lib/config/configuration.go +++ b/lib/config/configuration.go @@ -216,6 +216,9 @@ func ApplyFileConfig(fc *FileConfig, cfg *service.Config) error { if fc == nil { return nil } + + applyConfigVersion(fc, cfg) + // merge file-based config with defaults in 'cfg' if fc.Auth.Disabled() { cfg.Auth.Enabled = false @@ -253,20 +256,8 @@ func ApplyFileConfig(fc *FileConfig, cfg *service.Config) error { } cfg.PIDFile = fc.PIDFile - // config file has auth servers in there? - if len(fc.AuthServers) > 0 { - cfg.AuthServers = make([]utils.NetAddr, 0, len(fc.AuthServers)) - for _, as := range fc.AuthServers { - addr, err := utils.ParseHostPortAddr(as, defaults.AuthListenPort) - if err != nil { - return trace.Wrap(err) - } - - if err != nil { - return trace.Errorf("cannot parse auth server address: '%v'", as) - } - cfg.AuthServers = append(cfg.AuthServers, *addr) - } + if err := applyAuthOrProxyAddress(fc, cfg); err != nil { + return trace.Wrap(err) } if err := applyTokenConfig(fc, cfg); err != nil { @@ -391,8 +382,6 @@ func ApplyFileConfig(fc *FileConfig, cfg *service.Config) error { } } - applyConfigVersion(fc, cfg) - // Apply configuration for "auth_service", "proxy_service", "ssh_service", // and "app_service" if they are enabled. if fc.Auth.Enabled() { @@ -451,6 +440,72 @@ func ApplyFileConfig(fc *FileConfig, cfg *service.Config) error { return nil } +func applyAuthOrProxyAddress(fc *FileConfig, cfg *service.Config) error { + switch cfg.Version { + // For config versions v1 and v2, the auth_servers field can point to an auth + // server or a proxy server + case defaults.TeleportConfigVersionV1, defaults.TeleportConfigVersionV2: + // config file has auth servers in there? + if len(fc.AuthServers) > 0 { + var parsedAddresses []utils.NetAddr + + for _, as := range fc.AuthServers { + addr, err := utils.ParseHostPortAddr(as, defaults.AuthListenPort) + if err != nil { + return trace.Wrap(err) + } + + parsedAddresses = append(parsedAddresses, *addr) + } + + if err := cfg.SetAuthServerAddresses(parsedAddresses); err != nil { + return trace.Wrap(err) + } + } + + if fc.AuthServer != "" { + return trace.BadParameter("auth_server is supported from config version v3 onwards") + } + + if fc.ProxyServer != "" { + return trace.BadParameter("proxy_server is supported from config version v3 onwards") + } + + // From v3 onwards, either auth_server or proxy_server should be set + case defaults.TeleportConfigVersionV3: + if len(fc.AuthServers) > 0 { + return trace.BadParameter("config v3 has replaced auth_servers with either auth_server or proxy_server") + } + + haveAuthServer := fc.AuthServer != "" + haveProxyServer := fc.ProxyServer != "" + + if haveProxyServer && haveAuthServer { + return trace.BadParameter("only one of auth_server or proxy_server should be set") + } + + if haveAuthServer { + addr, err := utils.ParseHostPortAddr(fc.AuthServer, defaults.AuthListenPort) + if err != nil { + return trace.Wrap(err) + } + + cfg.SetAuthServerAddress(*addr) + } + + if haveProxyServer { + addr, err := utils.ParseHostPortAddr(fc.ProxyServer, defaults.HTTPListenPort) + if err != nil { + return trace.Wrap(err) + } + + cfg.ProxyServer = *addr + } + } + + return nil +} + func applyLogConfig(loggerConfig Log, cfg *service.Config) error { logger := log.StandardLogger() @@ -544,7 +599,9 @@ func applyAuthConfig(fc *FileConfig, cfg *service.Config) error { return trace.Wrap(err) } cfg.Auth.ListenAddr = *addr - cfg.AuthServers = append(cfg.AuthServers, *addr) + if len(cfg.AuthServerAddresses()) == 0 { + cfg.SetAuthServerAddress(*addr) + } } for _, t := range fc.Auth.ReverseTunnels { tun, err := t.ConvertAndValidate() @@ -857,8 +914,7 @@ func applyProxyConfig(fc *FileConfig, cfg *service.Config) error { case legacyKube && newKube: return trace.BadParameter("proxy_service should either set kube_listen_addr/kube_public_addr or kubernetes.enabled, not both; keep kubernetes.enabled if you don't enable kubernetes_service, or keep kube_listen_addr otherwise") case !legacyKube && !newKube: - if fc.Version == defaults.TeleportConfigVersionV2 { - // Always enable kube service if using config V2 (TLS routing is supported) + if fc.Version != "" && fc.Version != defaults.TeleportConfigVersionV1 { cfg.Proxy.Kube.Enabled = true } } @@ -955,8 +1011,8 @@ func getPostgresDefaultPort(cfg *service.Config) int { } func applyDefaultProxyListenerAddresses(cfg *service.Config) { - if cfg.Version == defaults.TeleportConfigVersionV2 { - // For v2 configuration if an address is not provided don't fallback to the default values. + // From v2 onwards if an address is not provided don't fall back to the default values. + if cfg.Version != "" && cfg.Version != defaults.TeleportConfigVersionV1 { return } @@ -1978,13 +2034,18 @@ func Configure(clf *CommandLineFlags, cfg *service.Config) error { log.Warnf("not starting the local auth service. --auth-server flag tells to connect to another auth server") cfg.Auth.Enabled = false } - cfg.AuthServers = make([]utils.NetAddr, 0, len(clf.AuthServerAddr)) + + authServerAddresses := make([]utils.NetAddr, 0, len(clf.AuthServerAddr)) for _, as := range clf.AuthServerAddr { addr, err := utils.ParseHostPortAddr(as, defaults.AuthListenPort) if err != nil { return trace.BadParameter("cannot parse auth server address: '%v'", as) } - cfg.AuthServers = append(cfg.AuthServers, *addr) + authServerAddresses = append(authServerAddresses, *addr) + } + + if err := cfg.SetAuthServerAddresses(authServerAddresses); err != nil { + return trace.Wrap(err) } } @@ -2032,8 +2093,8 @@ func Configure(clf *CommandLineFlags, cfg *service.Config) error { } // auth_servers not configured, but the 'auth' is enabled (auth is on localhost)? - if len(cfg.AuthServers) == 0 && cfg.Auth.Enabled { - cfg.AuthServers = append(cfg.AuthServers, cfg.Auth.ListenAddr) + if len(cfg.AuthServerAddresses()) == 0 && cfg.Auth.Enabled { + cfg.SetAuthServerAddress(cfg.Auth.ListenAddr) } // add data_dir to the backend config: @@ -2188,23 +2249,24 @@ func splitRoles(roles string) []string { // applyTokenConfig applies the auth_token and join_params to the config func applyTokenConfig(fc *FileConfig, cfg *service.Config) error { if fc.AuthToken != "" { + if fc.JoinParams != (JoinParams{}) { + return trace.BadParameter("only one of auth_token or join_params should be set") + } + cfg.JoinMethod = types.JoinMethodToken cfg.SetToken(fc.AuthToken) + + return nil } if fc.JoinParams != (JoinParams{}) { - if cfg.HasToken() { - return trace.BadParameter("only one of auth_token or join_params should be set") - } - cfg.SetToken(fc.JoinParams.TokenName) - switch fc.JoinParams.Method { - case types.JoinMethodEC2, types.JoinMethodIAM, types.JoinMethodToken: - cfg.JoinMethod = fc.JoinParams.Method - default: - return trace.BadParameter(`unknown value for join_params.method: %q, expected one of %v`, fc.JoinParams.Method, []types.JoinMethod{types.JoinMethodEC2, types.JoinMethodIAM, types.JoinMethodToken}) + if err := types.ValidateJoinMethod(fc.JoinParams.Method); err != nil { + return trace.Wrap(err) } + + cfg.JoinMethod = fc.JoinParams.Method } return nil diff --git a/lib/config/database.go b/lib/config/database.go index e0bee3ee7e9f2..cebb9ace7b379 100644 --- a/lib/config/database.go +++ b/lib/config/database.go @@ -38,14 +38,12 @@ var databaseAgentConfigurationTemplate = template.Must(template.New("").Funcs(da # Teleport database agent configuration file. # Configuration reference: https://goteleport.com/docs/database-access/reference/configuration/ # +version: v3 teleport: nodename: {{ .NodeName }} data_dir: {{ .DataDir }} + proxy_server: {{ .ProxyServer }} auth_token: {{ .AuthToken }} - auth_servers: - {{- range .AuthServersAddr }} - - {{ . }} - {{- end }} {{- if .CAPins }} ca_pin: {{- range .CAPins }} @@ -312,7 +310,7 @@ type DatabaseSampleFlags struct { // the user. StaticDatabaseStaticLabels map[string]string // StaticDatabaseDynamicLabels list of database dynamic labels provided by - // the user. + // the user.` StaticDatabaseDynamicLabels services.CommandLabels // StaticDatabaseRawLabels "raw" list of database labels provided by the // user. @@ -321,9 +319,8 @@ type DatabaseSampleFlags struct { NodeName string // DataDir `data_dir` configuration. DataDir string - // ProxyServerAddr is a list of addresses of the auth servers placed on - // the configuration. - AuthServersAddr []string + // ProxyServer is the address of the proxy servers + ProxyServer string // AuthToken auth server token. AuthToken string // CAPins are the SKPI hashes of the CAs used to verify the Auth Server. diff --git a/lib/config/database_test.go b/lib/config/database_test.go index c9b2c5c56c6c9..9c1077239b699 100644 --- a/lib/config/database_test.go +++ b/lib/config/database_test.go @@ -25,11 +25,11 @@ import ( func TestMakeDatabaseConfig(t *testing.T) { t.Run("Global", func(t *testing.T) { flags := DatabaseSampleFlags{ - NodeName: "testlocal", - DataDir: "/var/lib/data", - AuthServersAddr: []string{"localhost:3080"}, - AuthToken: "/tmp/token.txt", - CAPins: []string{"pin-1", "pin-2"}, + NodeName: "testlocal", + DataDir: "/var/lib/data", + ProxyServer: "localhost:3080", + AuthToken: "/tmp/token.txt", + CAPins: []string{"pin-1", "pin-2"}, } configString, err := MakeDatabaseAgentConfigString(flags) @@ -40,7 +40,7 @@ func TestMakeDatabaseConfig(t *testing.T) { require.Equal(t, flags.NodeName, fileConfig.NodeName) require.Equal(t, flags.DataDir, fileConfig.DataDir) - require.ElementsMatch(t, flags.AuthServersAddr, fileConfig.AuthServers) + require.Equal(t, flags.ProxyServer, fileConfig.ProxyServer) require.Equal(t, flags.AuthToken, fileConfig.AuthToken) require.ElementsMatch(t, flags.CAPins, fileConfig.CAPin) }) diff --git a/lib/config/fileconf.go b/lib/config/fileconf.go index 79b72a92559a4..032c0da89dac2 100644 --- a/lib/config/fileconf.go +++ b/lib/config/fileconf.go @@ -160,6 +160,8 @@ type SampleFlags struct { Roles string // AuthServer is the address of the auth server AuthServer string + // ProxyAddress is the address of the proxy + ProxyAddress string // AppName is the name of the application to start AppName string // AppURI is the internal address of the application to proxy @@ -222,6 +224,10 @@ func MakeSampleFileConfig(flags SampleFlags) (fc *FileConfig, err error) { g.AuthServers = []string{flags.AuthServer} } + if flags.ProxyAddress != "" { + g.ProxyServer = flags.ProxyAddress + } + g.CAPin = strings.Split(flags.CAPin, ",") roles := roleMapFromFlags(flags) @@ -311,7 +317,8 @@ func makeSampleAuthConfig(conf *service.Config, flags SampleFlags, enabled bool) a.LicenseFile = flags.LicensePath } - if flags.Version == defaults.TeleportConfigVersionV2 { + // from config v2 onwards, we support `proxy_listener_mode`, so we set it to `multiplex` + if flags.Version != defaults.TeleportConfigVersionV1 { a.ProxyListenerMode = types.ProxyListenerMode_Multiplex } } else { @@ -574,12 +581,19 @@ type Global struct { DataDir string `yaml:"data_dir,omitempty"` PIDFile string `yaml:"pid_file,omitempty"` + JoinParams JoinParams `yaml:"join_params,omitempty"` + + // v1, v2 + AuthServers []string `yaml:"auth_servers,omitempty"` // AuthToken is the old way of configuring the token to be used by the // node to join the Teleport cluster. `JoinParams.TokenName` should be // used instead with `JoinParams.JoinMethod = types.JoinMethodToken`. - AuthToken string `yaml:"auth_token,omitempty"` - JoinParams JoinParams `yaml:"join_params,omitempty"` - AuthServers []string `yaml:"auth_servers,omitempty"` + AuthToken string `yaml:"auth_token,omitempty"` + + // v3 + AuthServer string `yaml:"auth_server,omitempty"` + ProxyServer string `yaml:"proxy_server,omitempty"` + Limits ConnectionLimits `yaml:"connection_limits,omitempty"` Logger Log `yaml:"log,omitempty"` Storage backend.Config `yaml:"storage,omitempty"` diff --git a/lib/config/testdata_test.go b/lib/config/testdata_test.go index e100d2cbdf3e6..171683347e40c 100644 --- a/lib/config/testdata_test.go +++ b/lib/config/testdata_test.go @@ -20,13 +20,12 @@ const StaticConfigString = ` # # Some comments # +version: v3 teleport: nodename: edsger.example.com advertise_ip: 10.10.10.1:3022 pid_file: /var/run/teleport.pid - auth_servers: - - auth0.server.example.org:3024 - - auth1.server.example.org:3024 + auth_server: auth0.server.example.org:3024 auth_token: xxxyyy log: output: stderr @@ -84,14 +83,13 @@ ssh_service: ` const SmallConfigString = ` +version: v3 teleport: nodename: cat.example.com advertise_ip: 10.10.10.1 pid_file: /var/run/teleport.pid auth_token: %v - auth_servers: - - auth0.server.example.org:3024 - - auth1.server.example.org:3024 + auth_server: auth0.server.example.org:3024 log: output: stderr severity: INFO diff --git a/lib/defaults/defaults.go b/lib/defaults/defaults.go index fe1c869a2f120..91b6a95694579 100644 --- a/lib/defaults/defaults.go +++ b/lib/defaults/defaults.go @@ -29,6 +29,7 @@ import ( "github.com/gravitational/teleport" "github.com/gravitational/teleport/api/defaults" + apiutils "github.com/gravitational/teleport/api/utils" "github.com/gravitational/teleport/lib/limiter" "github.com/gravitational/teleport/lib/utils" @@ -816,8 +817,27 @@ const ( TeleportConfigVersionV1 string = "v1" // TeleportConfigVersionV2 is the teleport proxy configuration v2 version. TeleportConfigVersionV2 string = "v2" + // TeleportConfigVersionV3 is the teleport proxy configuration v3 version. + TeleportConfigVersionV3 string = "v3" ) +// TeleportConfigVersions is an exported slice of the allowed versions in the config file, +// for convenience (looping through, etc) +var TeleportConfigVersions = []string{ + TeleportConfigVersionV1, + TeleportConfigVersionV2, + TeleportConfigVersionV3, +} + +func ValidateConfigVersion(version string) error { + hasVersion := apiutils.SliceContainsStr(TeleportConfigVersions, version) + if !hasVersion { + return trace.BadParameter("version must be one of %s", strings.Join(TeleportConfigVersions, ", ")) + } + + return nil +} + // Default values for tsh and tctl commands. const ( // Use more human readable format than RFC3339 diff --git a/lib/service/cfg.go b/lib/service/cfg.go index 31a9745d2dbd5..5603a41457f92 100644 --- a/lib/service/cfg.go +++ b/lib/service/cfg.go @@ -90,10 +90,8 @@ type Config struct { // JoinMethod is the method the instance will use to join the auth server JoinMethod types.JoinMethod - // AuthServers is a list of auth servers, proxies and peer auth servers to - // connect to. Yes, this is not just auth servers, the field name is - // misleading. - AuthServers []utils.NetAddr + // ProxyServer is the address of the proxy + ProxyServer utils.NetAddr // Identities is an optional list of pre-generated key pairs // for teleport roles, this is helpful when server is preconfigured @@ -269,6 +267,49 @@ type Config struct { // This is private to avoid external packages reading the value - the value should be obtained // using Token() token string + + // v1, v2 - + // AuthServers is a list of auth servers, proxies and peer auth servers to + // connect to. Yes, this is not just auth servers, the field name is + // misleading. + // v3 - + // AuthServers contains a single address that is set by `auth_server` in the config + // A proxy address would be specified separately, so this no longer contains both + // auth servers and proxies. + // + // In order to keep backwards compatibility between v3 and v2/v1, this is now private + // and the value is retrieved via AuthServerAddresses() and set via SetAuthServerAddresses() + // as we still need to keep multiple addresses and return them for older config versions. + authServers []utils.NetAddr +} + +// AuthServerAddresses returns the value of authServers for config versions v1 and v2 and +// will return just the first (as only one should be set) address for config versions v3 +// onwards. +func (cfg *Config) AuthServerAddresses() []utils.NetAddr { + return cfg.authServers +} + +// SetAuthServerAddresses sets the value of authServers +// If the config version is v1 or v2, it will set the value to all the given addresses (as +// multiple can be specified). +// If the config version is v3 or onwards, it'll error if more than one address is given. +func (cfg *Config) SetAuthServerAddresses(addrs []utils.NetAddr) error { + // from config v3 onwards, we will error if more than one address is given + if cfg.Version != defaults.TeleportConfigVersionV1 && cfg.Version != defaults.TeleportConfigVersionV2 { + if len(addrs) > 1 { + return trace.BadParameter("only one auth server address should be set from config v3 onwards") + } + } + + cfg.authServers = addrs + + return nil +} + +// SetAuthServerAddress sets the value of authServers to a single value +func (cfg *Config) SetAuthServerAddress(addr utils.NetAddr) { + cfg.authServers = []utils.NetAddr{addr} } // Token returns token needed to join the auth server @@ -329,7 +370,7 @@ func (cfg *Config) RoleConfig() RoleConfig { DataDir: cfg.DataDir, HostUUID: cfg.HostUUID, HostName: cfg.Hostname, - AuthServers: cfg.AuthServers, + AuthServers: cfg.AuthServerAddresses(), Auth: cfg.Auth, Console: cfg.Console, } @@ -1308,6 +1349,8 @@ func ApplyDefaults(cfg *Config) { var sc ssh.Config sc.SetDefaults() + cfg.Version = defaults.TeleportConfigVersionV1 + if cfg.Log == nil { cfg.Log = utils.NewLogger() } diff --git a/lib/service/connect.go b/lib/service/connect.go index 2575666d60f90..deee73c4ed958 100644 --- a/lib/service/connect.go +++ b/lib/service/connect.go @@ -253,7 +253,7 @@ func (process *TeleportProcess) connect(role types.SystemRole, opts ...certOptio }, nil } process.log.Infof("Connecting to the cluster %v with TLS client certificate.", identity.ClusterName) - clt, err := process.newClient(process.Config.AuthServers, identity) + clt, err := process.newClient(identity) if err != nil { // In the event that a user is attempting to connect a machine to // a different cluster it will give a cryptic warning about an @@ -282,7 +282,7 @@ func (process *TeleportProcess) connect(role types.SystemRole, opts ...certOptio ServerIdentity: identity, }, nil } - clt, err := process.newClient(process.Config.AuthServers, identity) + clt, err := process.newClient(identity) if err != nil { return nil, trace.Wrap(err) } @@ -304,7 +304,7 @@ func (process *TeleportProcess) connect(role types.SystemRole, opts ...certOptio ServerIdentity: identity, }, nil } - clt, err := process.newClient(process.Config.AuthServers, newIdentity) + clt, err := process.newClient(newIdentity) if err != nil { return nil, trace.Wrap(err) } @@ -326,7 +326,7 @@ func (process *TeleportProcess) connect(role types.SystemRole, opts ...certOptio ServerIdentity: newIdentity, }, nil } - clt, err := process.newClient(process.Config.AuthServers, newIdentity) + clt, err := process.newClient(newIdentity) if err != nil { return nil, trace.Wrap(err) } @@ -346,7 +346,7 @@ func (process *TeleportProcess) connect(role types.SystemRole, opts ...certOptio ServerIdentity: identity, }, nil } - clt, err := process.newClient(process.Config.AuthServers, identity) + clt, err := process.newClient(identity) if err != nil { return nil, trace.Wrap(err) } @@ -511,7 +511,7 @@ func (process *TeleportProcess) firstTimeConnectWithAssertions(role types.System } process.deleteKeyPair(role, reason) - clt, err := process.newClient(process.Config.AuthServers, identity) + clt, err := process.newClient(identity) if err != nil { return nil, trace.Wrap(err) } @@ -591,17 +591,23 @@ func (process *TeleportProcess) firstTimeConnect(role types.SystemRole) (*Connec return nil, trace.Wrap(err) } + dataDir := defaults.DataDir + if process.Config.DataDir != "" { + dataDir = process.Config.DataDir + } + certs, err := auth.Register(auth.RegisterParams{ Token: token, ID: id, - Servers: process.Config.AuthServers, + AuthServers: process.Config.AuthServerAddresses(), + ProxyServer: process.Config.ProxyServer, AdditionalPrincipals: additionalPrincipals, DNSNames: dnsNames, PublicTLSKey: keyPair.PublicTLSKey, PublicSSHKey: keyPair.PublicSSHKey, CipherSuites: process.Config.CipherSuites, CAPins: process.Config.CAPins, - CAPath: filepath.Join(defaults.DataDir, defaults.CACertFile), + CAPath: filepath.Join(dataDir, defaults.CACertFile), GetHostCredentials: client.HostCredentials, Clock: process.Clock, JoinMethod: process.Config.JoinMethod, @@ -631,7 +637,7 @@ func (process *TeleportProcess) firstTimeConnect(role types.SystemRole) (*Connec ServerIdentity: identity, } } else { - clt, err := process.newClient(process.Config.AuthServers, identity) + clt, err := process.newClient(identity) if err != nil { return nil, trace.Wrap(err) } @@ -1042,55 +1048,99 @@ func (process *TeleportProcess) rotate(conn *Connector, localState auth.StateV2, } } -// newClient attempts to connect directly to the Auth Server. If it fails, it -// falls back to trying to connect to the Auth Server through the proxy. -// The proxy address might be configured in process environment as apidefaults.TunnelPublicAddrEnvar -// in which case, no attempt at discovering the reverse tunnel address is made. -func (process *TeleportProcess) newClient(authServers []utils.NetAddr, identity *auth.Identity) (*auth.Client, error) { +// newClient attempts to connect to either the proxy server or auth server +// For config v3 and onwards, it will only connect to either the proxy (via tunnel) or the auth server (direct), +// depending on what was specified in the config. +// For config v1 and v2, it will attempt to direct dial the auth server, and fallback to trying to tunnel +// to the Auth Server through the proxy. +func (process *TeleportProcess) newClient(identity *auth.Identity) (*auth.Client, error) { tlsConfig, err := identity.TLSConfig(process.Config.CipherSuites) if err != nil { return nil, trace.Wrap(err) } - logger := process.log.WithField("auth-addrs", utils.NetAddrsToStrings(authServers)) - logger.Debug("Attempting to connect to Auth Server directly.") - directClient, directErr := process.newClientDirect(authServers, tlsConfig, identity.ID.Role) - if directErr == nil { - logger.Debug("Connected to Auth Server with direct connection.") - return directClient, nil + sshClientConfig, err := identity.SSHClientConfig(process.Config.FIPS) + if err != nil { + return nil, trace.Wrap(err) } - logger.Debug("Failed to connect to Auth Server directly.") - // Don't attempt to connect through a tunnel as a proxy or auth server. - if identity.ID.Role == types.RoleAuth || identity.ID.Role == types.RoleProxy { - return nil, trace.Wrap(directErr) + authServers := process.Config.AuthServerAddresses() + connectToAuthServer := func(logger *logrus.Entry) (*auth.Client, error) { + logger.Debug("Attempting to connect to Auth Server directly.") + client, err := process.newClientDirect(authServers, tlsConfig, identity.ID.Role) + if err != nil { + logger.Debug("Failed to connect to Auth Server directly.") + return nil, err + } + + logger.Debug("Connected to Auth Server with direct connection.") + return client, nil } - logger.Debug("Attempting to discover reverse tunnel address.") + switch process.Config.Version { + // for config v1 and v2, attempt to directly connect to the auth server and fall back to tunneling + case defaults.TeleportConfigVersionV1, defaults.TeleportConfigVersionV2: + // if we don't have a proxy address, try to connect to the auth server directly + logger := process.log.WithField("auth-addrs", utils.NetAddrsToStrings(authServers)) - logger.Debug("Attempting to connect to Auth Server through tunnel.") - sshClientConfig, err := identity.SSHClientConfig(process.Config.FIPS) - if err != nil { - return nil, trace.Wrap(err) - } - tunnelClient, err := process.newClientThroughTunnel(authServers, tlsConfig, sshClientConfig) - if err != nil { - process.log.Errorf("Node failed to establish connection to Teleport Proxy. We have tried the following endpoints:") - process.log.Errorf("- connecting to auth server directly: %v", directErr) - if trace.IsConnectionProblem(err) && strings.Contains(err.Error(), "connection refused") { - err = trace.Wrap(err, "This is the alternative port we tried and it's not configured.") + directClient, directErr := connectToAuthServer(logger) + if directErr == nil { + return directClient, nil } - process.log.Errorf("- connecting to auth server through tunnel: %v", err) - collectedErrs := trace.NewAggregate(directErr, err) - if utils.IsUntrustedCertErr(collectedErrs) { - collectedErrs = trace.WrapWithMessage(collectedErrs, utils.SelfSignedCertsMsg) + + // Don't attempt to connect through a tunnel as a proxy or auth server. + if identity.ID.Role == types.RoleAuth || identity.ID.Role == types.RoleProxy { + return nil, trace.Wrap(directErr) } - return nil, trace.WrapWithMessage(collectedErrs, - "Failed to connect to Auth Server directly or over tunnel, no methods remaining.") + + // if that fails, attempt to connect to the auth server through a tunnel + + logger.Debug("Attempting to discover reverse tunnel address.") + logger.Debug("Attempting to connect to Auth Server through tunnel.") + + tunnelClient, err := process.newClientThroughTunnel(authServers, tlsConfig, sshClientConfig) + if err != nil { + process.log.Errorf("Node failed to establish connection to Teleport Proxy. We have tried the following endpoints:") + process.log.Errorf("- connecting to auth server directly: %v", directErr) + if trace.IsConnectionProblem(err) && strings.Contains(err.Error(), "connection refused") { + err = trace.Wrap(err, "This is the alternative port we tried and it's not configured.") + } + process.log.Errorf("- connecting to auth server through tunnel: %v", err) + collectedErrs := trace.NewAggregate(directErr, err) + if utils.IsUntrustedCertErr(collectedErrs) { + collectedErrs = trace.WrapWithMessage(collectedErrs, utils.SelfSignedCertsMsg) + } + return nil, trace.WrapWithMessage(collectedErrs, + "Failed to connect to Auth Server directly or over tunnel, no methods remaining.") + } + + logger.Debug("Connected to Auth Server through tunnel.") + return tunnelClient, nil + + // for config v3, either tunnel to the given proxy server or directly connect to the given auth server + case defaults.TeleportConfigVersionV3: + proxyServer := process.Config.ProxyServer + if !proxyServer.IsEmpty() { + logger := process.log.WithField("proxy-server", proxyServer.String()) + logger.Debug("Attempting to connect to Auth Server through tunnel.") + + tunnelClient, err := process.newClientThroughTunnel([]utils.NetAddr{proxyServer}, tlsConfig, sshClientConfig) + if err != nil { + return nil, trace.Errorf("Failed to connect to Proxy Server through tunnel: %v", err) + } + + logger.Debug("Connected to Auth Server through tunnel.") + + return tunnelClient, nil + } + + // if we don't have a proxy address, try to connect to the auth server directly + logger := process.log.WithField("auth-server", utils.NetAddrsToStrings(authServers)) + + return connectToAuthServer(logger) } - logger.Debug("Connected to Auth Server through tunnel.") - return tunnelClient, nil + return nil, trace.NotImplemented("could not find connection strategy for config version %s", process.Config.Version) } func (process *TeleportProcess) newClientThroughTunnel(authServers []utils.NetAddr, tlsConfig *tls.Config, sshConfig *ssh.ClientConfig) (*auth.Client, error) { diff --git a/lib/service/desktop.go b/lib/service/desktop.go index 47b00dab817c4..4a2b991b1834c 100644 --- a/lib/service/desktop.go +++ b/lib/service/desktop.go @@ -86,9 +86,9 @@ func (process *TeleportProcess) initWindowsDesktopServiceRegistered(log *logrus. // Filter out cases where both listen_addr and tunnel are set or both are // not set. case useTunnel && !cfg.WindowsDesktop.ListenAddr.IsEmpty(): - return trace.BadParameter("either set windows_desktop_service.listen_addr if this process can be reached from a teleport proxy or point teleport.auth_servers to a proxy to dial out, but don't set both") + return trace.BadParameter("either set windows_desktop_service.listen_addr if this process can be reached from a teleport proxy or point teleport.proxy_server to a proxy to dial out, but don't set both") case !useTunnel && cfg.WindowsDesktop.ListenAddr.IsEmpty(): - return trace.BadParameter("set windows_desktop_service.listen_addr if this process can be reached from a teleport proxy or point teleport.auth_servers to a proxy to dial out") + return trace.BadParameter("set windows_desktop_service.listen_addr if this process can be reached from a teleport proxy or point teleport.proxy_server to a proxy to dial out") // Start a local listener and let proxies dial in. case !useTunnel && !cfg.WindowsDesktop.ListenAddr.IsEmpty(): diff --git a/lib/service/kubernetes.go b/lib/service/kubernetes.go index 90777db1065c6..1847e0b3aee4e 100644 --- a/lib/service/kubernetes.go +++ b/lib/service/kubernetes.go @@ -86,7 +86,7 @@ func (process *TeleportProcess) initKubernetesService(log *logrus.Entry, conn *C // Filter out cases where both listen_addr and tunnel are set or both are // not set. case conn.UseTunnel() && !cfg.Kube.ListenAddr.IsEmpty(): - return trace.BadParameter("either set kubernetes_service.listen_addr if this process can be reached from a teleport proxy or point teleport.auth_servers to a proxy to dial out, but don't set both") + return trace.BadParameter("either set kubernetes_service.listen_addr if this process can be reached from a teleport proxy or point teleport.proxy_server to a proxy to dial out, but don't set both") case !conn.UseTunnel() && cfg.Kube.ListenAddr.IsEmpty(): // TODO(awly): if this process runs auth, proxy and kubernetes // services, the proxy should be able to route requests to this @@ -96,7 +96,7 @@ func (process *TeleportProcess) initKubernetesService(log *logrus.Entry, conn *C // // For now, as a lazy shortcut, kuberentes_service.listen_addr is // always required when running in the same process with a proxy. - return trace.BadParameter("set kubernetes_service.listen_addr if this process can be reached from a teleport proxy or point teleport.auth_servers to a proxy to dial out") + return trace.BadParameter("set kubernetes_service.listen_addr if this process can be reached from a teleport proxy or point teleport.proxy_server to a proxy to dial out") // Start a local listener and let proxies dial in. case !conn.UseTunnel() && !cfg.Kube.ListenAddr.IsEmpty(): diff --git a/lib/service/proxy_settings.go b/lib/service/proxy_settings.go index 1e85d4e5a9b28..7a50aeb6f8872 100644 --- a/lib/service/proxy_settings.go +++ b/lib/service/proxy_settings.go @@ -48,7 +48,7 @@ func (p *proxySettings) GetProxySettings(ctx context.Context) (*webclient.ProxyS } switch p.cfg.Version { - case defaults.TeleportConfigVersionV2: + case defaults.TeleportConfigVersionV2, defaults.TeleportConfigVersionV3: return p.buildProxySettingsV2(resp.GetProxyListenerMode()), nil default: return p.buildProxySettings(resp.GetProxyListenerMode()), nil diff --git a/lib/service/service.go b/lib/service/service.go index 2eaa3cb1425fd..07fc5776e2d0b 100644 --- a/lib/service/service.go +++ b/lib/service/service.go @@ -969,15 +969,15 @@ func NewTeleport(cfg *Config, opts ...NewTeleportOption) (*TeleportProcess, erro // if user started auth and another service (without providing the auth address for // that service, the address of the in-process auth will be used - if process.Config.Auth.Enabled && len(process.Config.AuthServers) == 0 { - process.Config.AuthServers = []utils.NetAddr{process.Config.Auth.ListenAddr} + if process.Config.Auth.Enabled && len(process.Config.AuthServerAddresses()) == 0 { + process.Config.SetAuthServerAddress(process.Config.Auth.ListenAddr) } - if len(process.Config.AuthServers) != 0 && process.Config.AuthServers[0].Port(0) == 0 { + if len(process.Config.AuthServerAddresses()) != 0 && process.Config.AuthServerAddresses()[0].Port(0) == 0 { // port appears undefined, attempt early listener creation so that we can get the real port listener, err := process.importOrCreateListener(ListenerAuth, process.Config.Auth.ListenAddr.Addr) if err == nil { - process.Config.AuthServers = []utils.NetAddr{utils.FromAddr(listener.Addr())} + process.Config.SetAuthServerAddress(utils.FromAddr(listener.Addr())) } } @@ -3456,7 +3456,7 @@ func (process *TeleportProcess) initProxyEndpoint(conn *Connector) error { NodeWatcher: nodeWatcher, CertAuthorityWatcher: caWatcher, CircuitBreakerConfig: process.Config.CircuitBreakerConfig, - LocalAuthAddresses: utils.NetAddrsToStrings(process.Config.AuthServers), + LocalAuthAddresses: utils.NetAddrsToStrings(process.Config.AuthServerAddresses()), }) if err != nil { return trace.Wrap(err) @@ -3507,7 +3507,7 @@ func (process *TeleportProcess) initProxyEndpoint(conn *Connector) error { webConfig := web.Config{ Proxy: tsrv, - AuthServers: cfg.AuthServers[0], + AuthServers: cfg.AuthServerAddresses()[0], DomainName: cfg.Hostname, ProxyClient: conn.Client, ProxySSHAddr: proxySSHAddr, @@ -3676,7 +3676,7 @@ func (process *TeleportProcess) initProxyEndpoint(conn *Connector) error { ReverseTunnelServer: tsrv, FIPS: process.Config.FIPS, Log: rcWatchLog, - LocalAuthAddresses: utils.NetAddrsToStrings(process.Config.AuthServers), + LocalAuthAddresses: utils.NetAddrsToStrings(process.Config.AuthServerAddresses()), }) if err != nil { return trace.Wrap(err) @@ -3873,7 +3873,7 @@ func (process *TeleportProcess) initProxyEndpoint(conn *Connector) error { var alpnServer *alpnproxy.Proxy if !cfg.Proxy.DisableTLS && !cfg.Proxy.DisableALPNSNIListener && listeners.web != nil { - authDialerService := alpnproxyauth.NewAuthProxyDialerService(tsrv, clusterName, utils.NetAddrsToStrings(process.Config.AuthServers)) + authDialerService := alpnproxyauth.NewAuthProxyDialerService(tsrv, clusterName, utils.NetAddrsToStrings(process.Config.AuthServerAddresses())) alpnRouter.Add(alpnproxy.HandlerDecs{ MatchFunc: alpnproxy.MatchByALPNPrefix(string(alpncommon.ProtocolAuth)), HandlerWithConnInfo: authDialerService.HandleConnection, @@ -4649,47 +4649,6 @@ func (process *TeleportProcess) Close() error { return trace.NewAggregate(errors...) } -func validateConfig(cfg *Config) error { - if !cfg.Auth.Enabled && !cfg.SSH.Enabled && !cfg.Proxy.Enabled && !cfg.Kube.Enabled && !cfg.Apps.Enabled && !cfg.Databases.Enabled && !cfg.WindowsDesktop.Enabled && !cfg.Discovery.Enabled { - return trace.BadParameter( - "config: enable at least one of auth_service, ssh_service, proxy_service, app_service, database_service, kubernetes_service, windows_desktop_service or discovery_service") - } - - if cfg.DataDir == "" { - return trace.BadParameter("config: please supply data directory") - } - - if cfg.Console == nil { - cfg.Console = io.Discard - } - - if cfg.Log == nil { - cfg.Log = logrus.StandardLogger() - } - - if len(cfg.AuthServers) == 0 { - return trace.BadParameter("auth_servers is empty") - } - for i := range cfg.Auth.Authorities { - if err := services.ValidateCertAuthority(cfg.Auth.Authorities[i]); err != nil { - return trace.Wrap(err) - } - } - for _, tun := range cfg.ReverseTunnels { - if err := services.ValidateReverseTunnel(tun); err != nil { - return trace.Wrap(err) - } - } - - if cfg.PollingPeriod == 0 { - cfg.PollingPeriod = defaults.LowResPollingPeriod - } - - cfg.SSH.Namespace = types.ProcessNamespace(cfg.SSH.Namespace) - - return nil -} - // initSelfSignedHTTPSCert generates and self-signs a TLS key+cert pair for https connection // to the proxy server. func initSelfSignedHTTPSCert(cfg *Config) (err error) { diff --git a/lib/service/service_test.go b/lib/service/service_test.go index a67c17d03f650..269de8af5ecb7 100644 --- a/lib/service/service_test.go +++ b/lib/service/service_test.go @@ -95,7 +95,7 @@ func TestMonitor(t *testing.T) { var err error cfg.DataDir = t.TempDir() cfg.DiagnosticAddr = utils.NetAddr{AddrNetwork: "tcp", Addr: "127.0.0.1:0"} - cfg.AuthServers = []utils.NetAddr{{AddrNetwork: "tcp", Addr: "127.0.0.1:0"}} + cfg.SetAuthServerAddress(utils.NetAddr{AddrNetwork: "tcp", Addr: "127.0.0.1:0"}) cfg.Auth.Enabled = true cfg.Auth.StorageConfig.Params["path"] = t.TempDir() cfg.Auth.ListenAddr = utils.NetAddr{AddrNetwork: "tcp", Addr: "127.0.0.1:0"} @@ -459,7 +459,7 @@ func TestDesktopAccessFIPS(t *testing.T) { // Create and configure a default Teleport configuration. cfg := MakeDefaultConfig() - cfg.AuthServers = []utils.NetAddr{{AddrNetwork: "tcp", Addr: "127.0.0.1:0"}} + cfg.SetAuthServerAddress(utils.NetAddr{AddrNetwork: "tcp", Addr: "127.0.0.1:0"}) cfg.Clock = clockwork.NewFakeClock() cfg.DataDir = t.TempDir() cfg.Auth.Enabled = false @@ -580,7 +580,7 @@ func TestTeleportProcess_reconnectToAuth(t *testing.T) { clock := clockwork.NewFakeClock() // Create and configure a default Teleport configuration. cfg := MakeDefaultConfig() - cfg.AuthServers = []utils.NetAddr{{AddrNetwork: "tcp", Addr: "127.0.0.1:0"}} + cfg.SetAuthServerAddress(utils.NetAddr{AddrNetwork: "tcp", Addr: "127.0.0.1:0"}) cfg.Clock = clock cfg.DataDir = t.TempDir() cfg.Auth.Enabled = false @@ -641,7 +641,7 @@ func TestTeleportProcessAuthVersionCheck(t *testing.T) { // Create Node process. nodeCfg := MakeDefaultConfig() - nodeCfg.AuthServers = []utils.NetAddr{listenAddr} + nodeCfg.SetAuthServerAddress(listenAddr) nodeCfg.DataDir = t.TempDir() nodeCfg.SetToken(token) nodeCfg.Auth.Enabled = false @@ -669,7 +669,7 @@ func TestTeleportProcessAuthVersionCheck(t *testing.T) { require.NoError(t, err) authCfg := MakeDefaultConfig() - authCfg.AuthServers = []utils.NetAddr{listenAddr} + authCfg.SetAuthServerAddress(listenAddr) authCfg.DataDir = t.TempDir() authCfg.Auth.Enabled = true authCfg.Auth.StaticTokens = staticTokens diff --git a/lib/service/validateconfig.go b/lib/service/validateconfig.go new file mode 100644 index 0000000000000..72693eb271f88 --- /dev/null +++ b/lib/service/validateconfig.go @@ -0,0 +1,159 @@ +/* +Copyright 2022 Gravitational, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package service + +import ( + "io" + + "github.com/gravitational/teleport" + "github.com/gravitational/teleport/api/types" + "github.com/gravitational/teleport/lib/defaults" + "github.com/gravitational/teleport/lib/services" + "github.com/gravitational/trace" + + "github.com/sirupsen/logrus" +) + +func validateConfig(cfg *Config) error { + applyDefaults(cfg) + + if err := defaults.ValidateConfigVersion(cfg.Version); err != nil { + return err + } + + if err := verifyEnabledService(cfg); err != nil { + return err + } + + if err := validateAuthOrProxyServices(cfg); err != nil { + return err + } + + if cfg.DataDir == "" { + return trace.BadParameter("config: please supply data directory") + } + + for i := range cfg.Auth.Authorities { + if err := services.ValidateCertAuthority(cfg.Auth.Authorities[i]); err != nil { + return trace.Wrap(err) + } + } + + for _, tun := range cfg.ReverseTunnels { + if err := services.ValidateReverseTunnel(tun); err != nil { + return trace.Wrap(err) + } + } + + cfg.SSH.Namespace = types.ProcessNamespace(cfg.SSH.Namespace) + + return nil +} + +func applyDefaults(cfg *Config) { + if cfg.Version == "" { + cfg.Version = defaults.TeleportConfigVersionV1 + } + + if cfg.Console == nil { + cfg.Console = io.Discard + } + + if cfg.Log == nil { + cfg.Log = logrus.StandardLogger() + } + + if cfg.PollingPeriod == 0 { + cfg.PollingPeriod = defaults.LowResPollingPeriod + } +} + +func validateAuthOrProxyServices(cfg *Config) error { + haveAuthServers := len(cfg.authServers) > 0 + haveProxyServer := !cfg.ProxyServer.IsEmpty() + + if cfg.Version == defaults.TeleportConfigVersionV3 { + if haveAuthServers && haveProxyServer { + return trace.BadParameter("config: cannot use both auth_server and proxy_server") + } + + if !haveAuthServers && !haveProxyServer { + return trace.BadParameter("config: auth_server or proxy_server is required") + } + + if !cfg.Auth.Enabled { + if haveAuthServers && cfg.Apps.Enabled { + return trace.BadParameter("config: when app_service is enabled, proxy_server must be specified instead of auth_server") + } + + if haveAuthServers && cfg.Databases.Enabled { + return trace.BadParameter("config: when db_service is enabled, proxy_server must be specified instead of auth_server") + } + } + + if haveProxyServer { + port := cfg.ProxyServer.Port(0) + if port == defaults.AuthListenPort { + cfg.Log.Warnf("config: proxy_server is pointing to port %d, is this the auth server address?", defaults.AuthListenPort) + } + } + + if haveAuthServers { + authServerPort := cfg.authServers[0].Port(0) + checkPorts := []int{defaults.HTTPListenPort, teleport.StandardHTTPSPort} + for _, port := range checkPorts { + if authServerPort == port { + cfg.Log.Warnf("config: auth_server is pointing to port %d, is this the proxy server address?", port) + } + } + } + + return nil + } + + if haveProxyServer { + return trace.BadParameter("config: proxy_server is supported from config version v3 onwards") + } + + if !haveAuthServers { + return trace.BadParameter("config: auth_servers is required") + } + + return nil +} + +func verifyEnabledService(cfg *Config) error { + enabled := []bool{ + cfg.Auth.Enabled, + cfg.SSH.Enabled, + cfg.Proxy.Enabled, + cfg.Kube.Enabled, + cfg.Apps.Enabled, + cfg.Databases.Enabled, + cfg.WindowsDesktop.Enabled, + cfg.Discovery.Enabled, + } + + for _, item := range enabled { + if item { + return nil + } + } + + return trace.BadParameter( + "config: enable at least one of auth_service, ssh_service, proxy_service, app_service, database_service, kubernetes_service, windows_desktop_service or discover_service") +} diff --git a/lib/service/validateconfig_test.go b/lib/service/validateconfig_test.go new file mode 100644 index 0000000000000..24180a0985241 --- /dev/null +++ b/lib/service/validateconfig_test.go @@ -0,0 +1,120 @@ +/* + * + * Copyright 2015-2022 Gravitational, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * / + * + */ + +package service + +import ( + "fmt" + "strings" + "testing" + + "github.com/gravitational/teleport/lib/defaults" + "github.com/gravitational/teleport/lib/utils" + + "github.com/stretchr/testify/require" +) + +func TestValidateConfig(t *testing.T) { + tests := []struct { + desc string + config *Config + err string + }{ + { + desc: "invalid version", + config: &Config{ + Version: "v1.1", + }, + err: fmt.Sprintf("version must be one of %s", strings.Join(defaults.TeleportConfigVersions, ", ")), + }, + { + desc: "no service enabled", + config: &Config{ + Version: defaults.TeleportConfigVersionV2, + }, + err: "config: enable at least one of auth_service, ssh_service, proxy_service, app_service, database_service, kubernetes_service, windows_desktop_service or discover_service", + }, + { + desc: "no auth_servers or proxy_server specified", + config: &Config{ + Version: defaults.TeleportConfigVersionV3, + Auth: AuthConfig{ + Enabled: true, + }, + }, + err: "config: auth_server or proxy_server is required", + }, + { + desc: "no auth_servers specified", + config: &Config{ + Version: defaults.TeleportConfigVersionV2, + Auth: AuthConfig{ + Enabled: true, + }, + }, + err: "config: auth_servers is required", + }, + { + desc: "specifying proxy_server with the wrong config version", + config: &Config{ + Version: defaults.TeleportConfigVersionV2, + Auth: AuthConfig{ + Enabled: true, + }, + ProxyServer: *utils.MustParseAddr("0.0.0.0"), + }, + err: "config: proxy_server is supported from config version v3 onwards", + }, + { + desc: "specifying auth_server when app_service is enabled", + config: &Config{ + Version: defaults.TeleportConfigVersionV3, + Apps: AppsConfig{ + Enabled: true, + }, + DataDir: "/", + authServers: []utils.NetAddr{*utils.MustParseAddr("0.0.0.0")}, + }, + err: "config: when app_service is enabled, proxy_server must be specified instead of auth_server", + }, + { + desc: "specifying auth_server when db_service is enabled", + config: &Config{ + Version: defaults.TeleportConfigVersionV3, + Databases: DatabasesConfig{ + Enabled: true, + }, + DataDir: "/", + authServers: []utils.NetAddr{*utils.MustParseAddr("0.0.0.0")}, + }, + err: "config: when db_service is enabled, proxy_server must be specified instead of auth_server", + }, + } + + for _, test := range tests { + t.Run(test.desc, func(t *testing.T) { + err := validateConfig(test.config) + if test.err == "" { + require.NoError(t, err) + } else { + require.EqualError(t, err, test.err) + } + }) + } +} diff --git a/lib/tbot/renew.go b/lib/tbot/renew.go index 8945af83db2e7..e09cd56325d0c 100644 --- a/lib/tbot/renew.go +++ b/lib/tbot/renew.go @@ -464,7 +464,7 @@ func (b *Bot) getIdentityFromToken() (*identity.Identity, error) { ID: auth.IdentityID{ Role: types.RoleBot, }, - Servers: []utils.NetAddr{*addr}, + AuthServers: []utils.NetAddr{*addr}, PublicTLSKey: tlsPublicKey, PublicSSHKey: sshPublicKey, CAPins: b.cfg.Onboarding.CAPins, diff --git a/lib/tbot/testhelpers/srv.go b/lib/tbot/testhelpers/srv.go index 0b61d9c3a2a9e..e88f47d2e0dcd 100644 --- a/lib/tbot/testhelpers/srv.go +++ b/lib/tbot/testhelpers/srv.go @@ -159,7 +159,7 @@ func MakeBotAuthClient(t *testing.T, fc *config.FileConfig, ident *identity.Iden authConfig.TLS, err = ident.TLSConfig(cfg.CipherSuites) require.NoError(t, err) - authConfig.AuthServers = cfg.AuthServers + authConfig.AuthServers = cfg.AuthServerAddresses() authConfig.Log = cfg.Log client, err := authclient.Connect(context.Background(), authConfig) @@ -188,7 +188,7 @@ func MakeDefaultAuthClient(t *testing.T, log utils.Logger, fc *config.FileConfig authConfig.TLS, err = identity.TLSConfig(cfg.CipherSuites) require.NoError(t, err) - authConfig.AuthServers = cfg.AuthServers + authConfig.AuthServers = cfg.AuthServerAddresses() authConfig.Log = log client, err := authclient.Connect(context.Background(), authConfig) @@ -239,7 +239,7 @@ func MakeMemoryBotConfig(t *testing.T, fc *config.FileConfig, botParams *proto.C require.NoError(t, err) cfg := &botconfig.BotConfig{ - AuthServer: authCfg.AuthServers[0].String(), + AuthServer: authCfg.AuthServerAddresses()[0].String(), Onboarding: &botconfig.OnboardingConfig{ JoinMethod: botParams.JoinMethod, }, diff --git a/lib/web/scripts/desktop/configure-ad.ps1 b/lib/web/scripts/desktop/configure-ad.ps1 index b5ff52993b87c..d3cef9bb43720 100644 --- a/lib/web/scripts/desktop/configure-ad.ps1 +++ b/lib/web/scripts/desktop/configure-ad.ps1 @@ -140,9 +140,10 @@ $COMPUTER_IP = (Resolve-DnsName -Type A $Env:COMPUTERNAME).Address $LDAP_ADDR="$COMPUTER_IP" + ":636" $DESKTOP_ACCESS_CONFIG_YAML=@' +version v3 teleport: auth_token: {0} - auth_servers: [ {1} ] + proxy_server: {1} auth_service: enabled: no diff --git a/lib/web/scripts/node-join/README.md b/lib/web/scripts/node-join/README.md index 8aaa32cdec626..aab70b7af0c4a 100644 --- a/lib/web/scripts/node-join/README.md +++ b/lib/web/scripts/node-join/README.md @@ -54,10 +54,10 @@ Required arguments: | Flag | Description | Example value | Required | | - | - | - | - | | `-v` | Teleport version | `4.3.5` | yes | -| `-h` | Hostname for the Teleport auth/proxy server | `teleport.example.com` | yes | +| `-h` | Hostname for the Teleport Proxy Service | `teleport.example.com` | yes | | `-j` | A valid node join token | `ool7ahpo4thohmeuS1gieY7laiwae7oo` | yes | | `-c` | The CA pin hash of the cluster being joined | `sha256:6abdd3a143a230fd31c9706d668bba3ee25a6e0eec54fcd69680c1ec0530fe9c` | yes | -| `-p` | Port connect to on the Teleport auth/proxy server | `3080` | no | +| `-p` | Port connect to on the Teleport Proxy Service | `3080` | no | If any of these arguments is not provided via CLI flags, they will be requested interactively at runtime. diff --git a/lib/web/scripts/node-join/install.sh b/lib/web/scripts/node-join/install.sh index 66cbfdc19dc99..4fa7191a4b3cc 100755 --- a/lib/web/scripts/node-join/install.sh +++ b/lib/web/scripts/node-join/install.sh @@ -414,12 +414,12 @@ install_teleport_app_config() { log "Writing Teleport app service config to ${TELEPORT_CONFIG_PATH}" CA_PINS_CONFIG=$(get_yaml_list "ca_pin" "${CA_PIN_HASHES}" " ") cat << EOF > ${TELEPORT_CONFIG_PATH} +version: v3 teleport: nodename: ${NODENAME} auth_token: ${JOIN_TOKEN} ${CA_PINS_CONFIG} - auth_servers: - - ${TARGET_HOSTNAME}:${TARGET_PORT} + proxy_server: ${TARGET_HOSTNAME}:${TARGET_PORT} log: output: stderr severity: INFO @@ -444,7 +444,7 @@ install_teleport_node_config() { --token ${JOIN_TOKEN} \ ${JOIN_METHOD_FLAG} \ --ca-pin ${CA_PINS} \ - --auth-server ${TARGET_HOSTNAME}:${TARGET_PORT} \ + --proxy ${TARGET_HOSTNAME}:${TARGET_PORT} \ "${LABELS_FLAG[@]}" \ --output ${TELEPORT_CONFIG_PATH} } diff --git a/operator/sidecar/sidecar.go b/operator/sidecar/sidecar.go index ba42c2c3a39bb..33e0f3e011998 100644 --- a/operator/sidecar/sidecar.go +++ b/operator/sidecar/sidecar.go @@ -73,11 +73,15 @@ func createAuthClientConfig(opts Options) (*authclient.Config, error) { return nil, trace.Wrap(err) } - cfg.AuthServers, err = utils.ParseAddrs([]string{opts.Addr}) + authServers, err := utils.ParseAddrs([]string{opts.Addr}) if err != nil { return nil, trace.Wrap(err) } + if err := cfg.SetAuthServerAddresses(authServers); err != nil { + return nil, trace.Wrap(err) + } + // read the host UUID only in case the identity was not provided, // because it will be used for reading local auth server identity cfg.HostUUID, err = utils.ReadHostUUID(cfg.DataDir) @@ -99,7 +103,7 @@ func createAuthClientConfig(opts Options) (*authclient.Config, error) { if err != nil { return nil, trace.Wrap(err) } - authConfig.AuthServers = cfg.AuthServers + authConfig.AuthServers = cfg.AuthServerAddresses() authConfig.Log = cfg.Log return authConfig, nil diff --git a/tool/tctl/common/tctl.go b/tool/tctl/common/tctl.go index 38fb8d86180d8..e00eb4f49fb0f 100644 --- a/tool/tctl/common/tctl.go +++ b/tool/tctl/common/tctl.go @@ -191,7 +191,7 @@ func TryRun(commands []CLICommand, args []string) error { } utils.Consolef(os.Stderr, log.WithField(trace.Component, teleport.ComponentClient), teleport.ComponentClient, "Cannot connect to the auth server: %v.\nIs the auth server running on %q?", - err, cfg.AuthServers[0].Addr) + err, cfg.AuthServerAddresses()[0].Addr) return trace.NewAggregate(&toolcommon.ExitCodeError{Code: 1}, err) } @@ -223,6 +223,10 @@ func ApplyConfig(ccf *GlobalCLIFlags, cfg *service.Config) (*authclient.Config, } cfg.Log = log.StandardLogger() + if cfg.Version == "" { + cfg.Version = defaults.TeleportConfigVersionV1 + } + // If the config file path provided is not a blank string, load the file and apply its values var fileConf *config.FileConfig var err error @@ -248,12 +252,14 @@ func ApplyConfig(ccf *GlobalCLIFlags, cfg *service.Config) (*authclient.Config, // --auth-server flag(-s) if len(ccf.AuthServerAddr) != 0 { - addrs, err := utils.ParseAddrs(ccf.AuthServerAddr) + authServers, err := utils.ParseAddrs(ccf.AuthServerAddr) if err != nil { return nil, trace.Wrap(err) } // Overwrite any existing configuration with flag values. - cfg.AuthServers = addrs + if err := cfg.SetAuthServerAddresses(authServers); err != nil { + return nil, trace.Wrap(err) + } } // Config file should take precedence, if available. @@ -272,12 +278,17 @@ func ApplyConfig(ccf *GlobalCLIFlags, cfg *service.Config) (*authclient.Config, // If auth server is not provided on the command line or in file // configuration, use the default. - if len(cfg.AuthServers) == 0 { - cfg.AuthServers, err = utils.ParseAddrs([]string{defaults.AuthConnectAddr().Addr}) + if len(cfg.AuthServerAddresses()) == 0 { + authServers, err := utils.ParseAddrs([]string{defaults.AuthConnectAddr().Addr}) if err != nil { return nil, trace.Wrap(err) } + + if err := cfg.SetAuthServerAddresses(authServers); err != nil { + return nil, trace.Wrap(err) + } } + authConfig := new(authclient.Config) // --identity flag if ccf.IdentityFilePath != "" { @@ -330,7 +341,7 @@ func ApplyConfig(ccf *GlobalCLIFlags, cfg *service.Config) (*authclient.Config, } } authConfig.TLS.InsecureSkipVerify = ccf.Insecure - authConfig.AuthServers = cfg.AuthServers + authConfig.AuthServers = cfg.AuthServerAddresses() authConfig.Log = cfg.Log return authConfig, nil @@ -421,9 +432,9 @@ func LoadConfigFromProfile(ccf *GlobalCLIFlags, cfg *service.Config) (*authclien return nil, trace.Wrap(err) } log.Debugf("Setting auth server to web proxy %v.", webProxyAddr) - cfg.AuthServers = []utils.NetAddr{*webProxyAddr} + cfg.SetAuthServerAddress(*webProxyAddr) } - authConfig.AuthServers = cfg.AuthServers + authConfig.AuthServers = cfg.AuthServerAddresses() authConfig.Log = cfg.Log return authConfig, nil diff --git a/tool/teleport/common/teleport.go b/tool/teleport/common/teleport.go index 1d97313e2a76a..9605312483a85 100644 --- a/tool/teleport/common/teleport.go +++ b/tool/teleport/common/teleport.go @@ -232,7 +232,7 @@ func Run(options Options) (app *kingpin.Application, executedCommand string, con dbConfigureCreate := dbConfigure.Command("create", "Creates a sample Database Service configuration.") dbConfigureCreate.Flag("proxy", fmt.Sprintf("Teleport proxy address to connect to [%s].", defaults.ProxyWebListenAddr().Addr)). Default(defaults.ProxyWebListenAddr().Addr). - StringsVar(&dbConfigCreateFlags.AuthServersAddr) + StringVar(&dbConfigCreateFlags.ProxyServer) dbConfigureCreate.Flag("token", "Invitation token to register with an auth server [none].").Default("/tmp/token").StringVar(&dbConfigCreateFlags.AuthToken) dbConfigureCreate.Flag("rds-discovery", "List of AWS regions in which the agent will discover RDS/Aurora instances.").StringsVar(&dbConfigCreateFlags.RDSDiscoveryRegions) dbConfigureCreate.Flag("redshift-discovery", "List of AWS regions in which the agent will discover Redshift instances.").StringsVar(&dbConfigCreateFlags.RedshiftDiscoveryRegions) @@ -320,7 +320,7 @@ func Run(options Options) (app *kingpin.Application, executedCommand string, con dump.Flag("acme-email", "Email to receive updates from Letsencrypt.org.").StringVar(&dumpFlags.ACMEEmail) dump.Flag("test", "Path to a configuration file to test.").ExistingFileVar(&dumpFlags.testConfigFile) - dump.Flag("version", "Teleport configuration version.").Default(defaults.TeleportConfigVersionV2).StringVar(&dumpFlags.Version) + dump.Flag("version", "Teleport configuration version.").Default(defaults.TeleportConfigVersionV3).StringVar(&dumpFlags.Version) dump.Flag("public-addr", "The hostport that the proxy advertises for the HTTP endpoint.").StringVar(&dumpFlags.PublicAddr) dump.Flag("cert-file", "Path to a TLS certificate file for the proxy.").ExistingFileVar(&dumpFlags.CertFile) dump.Flag("key-file", "Path to a TLS key file for the proxy.").ExistingFileVar(&dumpFlags.KeyFile) @@ -328,6 +328,7 @@ func Run(options Options) (app *kingpin.Application, executedCommand string, con dump.Flag("token", "Invitation token to register with an auth server.").StringVar(&dumpFlags.AuthToken) dump.Flag("roles", "Comma-separated list of roles to create config with.").StringVar(&dumpFlags.Roles) dump.Flag("auth-server", "Address of the auth server.").StringVar(&dumpFlags.AuthServer) + dump.Flag("proxy", "Address of the proxy.").StringVar(&dumpFlags.ProxyAddress) dump.Flag("app-name", "Name of the application to start when using app role.").StringVar(&dumpFlags.AppName) dump.Flag("app-uri", "Internal address of the application to proxy.").StringVar(&dumpFlags.AppURI) dump.Flag("node-labels", "Comma-separated list of labels to add to newly created nodes, for example env=staging,cloud=aws.").StringVar(&dumpFlags.NodeLabels) @@ -339,11 +340,12 @@ func Run(options Options) (app *kingpin.Application, executedCommand string, con dumpNodeConfigure.Flag("output", "Write to stdout with -o=stdout, default config file with -o=file or custom path with -o=file:///path").Short('o').Default( teleport.SchemeStdout).StringVar(&dumpFlags.output) - dumpNodeConfigure.Flag("version", "Teleport configuration version.").Default(defaults.TeleportConfigVersionV2).StringVar(&dumpFlags.Version) + dumpNodeConfigure.Flag("version", "Teleport configuration version.").Default(defaults.TeleportConfigVersionV3).StringVar(&dumpFlags.Version) dumpNodeConfigure.Flag("public-addr", "The hostport that the node advertises for the SSH endpoint.").StringVar(&dumpFlags.PublicAddr) dumpNodeConfigure.Flag("data-dir", "Path to a directory where Teleport keep its data.").Default(defaults.DataDir).StringVar(&dumpFlags.DataDir) dumpNodeConfigure.Flag("token", "Invitation token to register with an auth server.").StringVar(&dumpFlags.AuthToken) dumpNodeConfigure.Flag("auth-server", "Address of the auth server.").StringVar(&dumpFlags.AuthServer) + dumpNodeConfigure.Flag("proxy", "Address of the proxy server.").StringVar(&dumpFlags.ProxyAddress) dumpNodeConfigure.Flag("labels", "Comma-separated list of labels to add to newly created nodes ex) env=staging,cloud=aws.").StringVar(&dumpFlags.NodeLabels) dumpNodeConfigure.Flag("ca-pin", "Comma-separated list of SKPI hashes for the CA used to verify the auth server.").StringVar(&dumpFlags.CAPin) dumpNodeConfigure.Flag("join-method", "Method to use to join the cluster (token, iam, ec2)").Default("token").EnumVar(&dumpFlags.JoinMethod, "token", "iam", "ec2") @@ -489,16 +491,12 @@ func normalizeOutput(output string) string { } func checkConfigurationFileVersion(version string) error { - supportedVersions := []string{defaults.TeleportConfigVersionV1, defaults.TeleportConfigVersionV2} - switch version { - case defaults.TeleportConfigVersionV1, defaults.TeleportConfigVersionV2, "": - default: - return trace.BadParameter( - "unsupported Teleport configuration version %q, supported are: %s", - version, strings.Join(supportedVersions, ",")) + // allow an empty version as we default to v1 + if version == "" { + return nil } - return nil + return defaults.ValidateConfigVersion(version) } // onConfigDump is the handler for "configure" CLI command diff --git a/tool/teleport/common/teleport_test.go b/tool/teleport/common/teleport_test.go index ac32cbf8305d9..e24ae186037d3 100644 --- a/tool/teleport/common/teleport_test.go +++ b/tool/teleport/common/teleport_test.go @@ -206,11 +206,11 @@ func TestDumpConfigFile(t *testing.T) { } const configData = ` +version: v3 teleport: advertise_ip: 10.5.5.5 nodename: hvostongo.example.org - auth_servers: - - auth.server.example.org:3024 + auth_server: auth.server.example.org:3024 auth_token: xxxyyy log: output: stderr diff --git a/tool/tsh/aws_test.go b/tool/tsh/aws_test.go index f945a4fea3c3c..3cabe520629b7 100644 --- a/tool/tsh/aws_test.go +++ b/tool/tsh/aws_test.go @@ -146,7 +146,7 @@ func makeTestApplicationServer(t *testing.T, auth *service.TeleportProcess, prox proxyAddr, err := proxy.ProxyWebAddr() require.NoError(t, err) - cfg.AuthServers = []utils.NetAddr{*proxyAddr} + cfg.SetAuthServerAddress(*proxyAddr) token, err := proxy.Config.Token() require.NoError(t, err) diff --git a/tool/tsh/db_test.go b/tool/tsh/db_test.go index 985706e15e80c..48fbf6ab001c5 100644 --- a/tool/tsh/db_test.go +++ b/tool/tsh/db_test.go @@ -370,7 +370,7 @@ func makeTestDatabaseServer(t *testing.T, auth *service.TeleportProcess, proxy * proxyAddr, err := proxy.ProxyWebAddr() require.NoError(t, err) - cfg.AuthServers = []utils.NetAddr{*proxyAddr} + cfg.SetAuthServerAddress(*proxyAddr) token, err := proxy.Config.Token() require.NoError(t, err) diff --git a/tool/tsh/tctl_test.go b/tool/tsh/tctl_test.go index 7ee1dcaddef7f..80fbe93ca39fd 100644 --- a/tool/tsh/tctl_test.go +++ b/tool/tsh/tctl_test.go @@ -233,9 +233,9 @@ func TestSetAuthServerFlagWhileLoggedIn(t *testing.T) { _, err = common.ApplyConfig(ccf, cfg) require.NoError(t, err) - require.NotEmpty(t, cfg.AuthServers, "auth servers should be set to a non-empty default if not specified") + require.NotEmpty(t, cfg.AuthServerAddresses(), "auth servers should be set to a non-empty default if not specified") - require.ElementsMatch(t, tt.want, cfg.AuthServers) + require.ElementsMatch(t, tt.want, cfg.AuthServerAddresses()) }) } } diff --git a/tool/tsh/tsh_test.go b/tool/tsh/tsh_test.go index c378a19ca5e22..dd6378e27449c 100644 --- a/tool/tsh/tsh_test.go +++ b/tool/tsh/tsh_test.go @@ -2280,7 +2280,7 @@ func makeTestSSHNode(t *testing.T, authAddr *utils.NetAddr, opts ...testServerOp cfg.Hostname = "node" cfg.DataDir = t.TempDir() - cfg.AuthServers = []utils.NetAddr{*authAddr} + cfg.SetAuthServerAddress(*authAddr) cfg.SetToken(staticToken) cfg.Auth.Enabled = false cfg.Proxy.Enabled = false @@ -2326,7 +2326,7 @@ func makeTestServers(t *testing.T, opts ...testServerOptFunc) (auth *service.Tel cfg.Hostname = "localhost" cfg.DataDir = t.TempDir() - cfg.AuthServers = []utils.NetAddr{{AddrNetwork: "tcp", Addr: net.JoinHostPort("127.0.0.1", ports.Pop())}} + cfg.SetAuthServerAddress(utils.NetAddr{AddrNetwork: "tcp", Addr: net.JoinHostPort("127.0.0.1", ports.Pop())}) cfg.Auth.Resources = options.bootstrap cfg.Auth.StorageConfig.Params = backend.Params{defaults.BackendPath: filepath.Join(cfg.DataDir, defaults.BackendDir)} cfg.Auth.StaticTokens, err = types.NewStaticTokens(types.StaticTokensSpecV2{ @@ -2371,7 +2371,7 @@ func makeTestServers(t *testing.T, opts ...testServerOptFunc) (auth *service.Tel cfg.Hostname = "localhost" cfg.DataDir = t.TempDir() - cfg.AuthServers = []utils.NetAddr{*authAddr} + cfg.SetAuthServerAddress(*authAddr) cfg.SetToken(staticToken) cfg.SSH.Enabled = false cfg.Auth.Enabled = false diff --git a/vagrant/opt/b-node/teleport.yaml b/vagrant/opt/b-node/teleport.yaml index c11e41d93aca9..26a2b7b606ed3 100644 --- a/vagrant/opt/b-node/teleport.yaml +++ b/vagrant/opt/b-node/teleport.yaml @@ -1,8 +1,9 @@ # Node for cluster-B +version: v3 teleport: nodename: bear auth_token: hello - auth_servers: ["b-auth:5025"] + auth_server: b-auth:5025 log: output: stderr severity: INFO