2024 Secure Infrastructure Access Report: Key Insights and Trends
Oct 30
Virtual
Register Today
Teleport logoTry For Free
Fork me on GitHub

Teleport

Web Application Access

This guide shows you how to enroll a web application with your Teleport cluster in order to set up role-based access controls, audit logging, and other Teleport capabilities.

How it works

To enroll a web application with your Teleport cluster, you deploy the Teleport Application Service, which uses a join token to establish trust with the Teleport Auth Service. Users visit Teleport-protected web applications through the Teleport Web UI. The Teleport Proxy Service routes browser traffic to the Teleport Application Service, which forwards HTTP requests to and from target applications.

Prerequisites

  • A running Teleport cluster version 16.4.2 or above. If you want to get started with Teleport, sign up for a free trial or set up a demo environment.

  • The tctl admin tool and tsh client tool.

    Visit Installation for instructions on downloading tctl and tsh.

  • A web application that you want to protect with Teleport. The web application should be running in a private network. In this guide, we assume that the web application is available on app.example.com:3000.
  • A Linux server where you will run the Teleport Application Service. Your network must enable the server to connect to your web application.
  • To check that you can connect to your Teleport cluster, sign in with tsh login, then verify that you can run tctl commands using your current credentials. For example:
    tsh login --proxy=teleport.example.com --user=[email protected]
    tctl status

    Cluster teleport.example.com

    Version 16.4.2

    CA pin sha256:abdc1245efgh5678abdc1245efgh5678abdc1245efgh5678abdc1245efgh5678

    If you can connect to the cluster and run the tctl status command, you can use your current credentials to run subsequent tctl commands from your workstation. If you host your own Teleport cluster, you can also run tctl commands on the computer that hosts the Teleport Auth Service for full permissions.

Step 1/3. Deploy the Teleport Application Service

In this step, you will configure the Teleport Application Service to proxy a target application, then deploy a Teleport Agent to run the service.

Generate a token

A join token is required to authorize a Teleport Application Service to join the cluster.

  1. Generate a short-lived join token. Make sure to change app-name to the name of your application and app-uri to the application's domain name and port:

    tctl tokens add \ --type=app \ --app-name=my-app \ --app-uri=app.example.com:3000 \ --ttl=1h

    This command creates a join token with a TTL of 1 hour.

  2. Copy the token and save it in /tmp/token on the Linux server that will run the Teleport Application Service.

Install the Teleport Application Service

Follow the instructions below on the host where you will install the Teleport Application Service:

Install Teleport on your Linux server:

  1. Assign edition to one of the following, depending on your Teleport edition:

    EditionValue
    Teleport Enterprise Cloudcloud
    Teleport Enterprise (Self-Hosted)enterprise
    Teleport Community Editionoss
  2. Get the version of Teleport to install. If you have automatic agent updates enabled in your cluster, query the latest Teleport version that is compatible with the updater:

    TELEPORT_DOMAIN=example.teleport.com
    TELEPORT_VERSION="$(curl https://$TELEPORT_DOMAIN/v1/webapi/automaticupgrades/channel/default/version | sed 's/v//')"

    Otherwise, get the version of your Teleport cluster:

    TELEPORT_DOMAIN=example.teleport.com
    TELEPORT_VERSION="$(curl https://$TELEPORT_DOMAIN/v1/webapi/ping | jq -r '.server_version')"
  3. Install Teleport on your Linux server:

    curl https://cdn.teleport.dev/install-v16.4.2.sh | bash -s ${TELEPORT_VERSION} edition

    The installation script detects the package manager on your Linux server and uses it to install Teleport binaries. To customize your installation, learn about the Teleport package repositories in the installation guide.

Configure the Teleport Application Service

  1. On the host where you will run the Teleport Application Service, create a file at /etc/teleport.yaml with the following content:

    version: v3
    teleport:
      join_params:
        token_name: "/tmp/token"
        method: token
      proxy_server: "teleport.example.com:443"
    auth_service:
      enabled: off
    proxy_service:
      enabled: off
    ssh_service:
      enabled: off
    app_service:
      enabled: true
      apps:
      - name: my-app
        uri: "app.example.com:3000"
        labels:
          env: "demo"
    
  2. Edit /etc/teleport.yaml to replace teleport.example.com:443 with the host and port of your Teleport Proxy Service or Teleport Enterprise (Cloud) account, e.g., example.teleport.sh:443.

  3. Change app.example.com:3000 to match the host and port of your own web application.

    The app_service field configures the Teleport Application Service. Each item within app_service.apps is an application configuration. The labels field assigns a label to each application. You can use Teleport labels to allow and deny users access to resources, as we will demonstrate later in this guide.

Run the Teleport Application Service

Configure the Teleport Application Service to start automatically when the host boots up by creating a systemd service for it. The instructions depend on how you installed the Teleport Application Service.

On the host where you will run the Teleport Application Service, enable and start Teleport:

sudo systemctl enable teleport
sudo systemctl start teleport

On the host where you will run the Teleport Application Service, create a systemd service configuration for Teleport, enable the Teleport service, and start Teleport:

sudo teleport install systemd -o /etc/systemd/system/teleport.service
sudo systemctl enable teleport
sudo systemctl start teleport

You can check the status of the Teleport Application Service with systemctl status teleport and view its logs with journalctl -fu teleport.

Step 2/3. [Optional] Configure TLS and DNS for your web applications

Once the Teleport Application Service is proxying traffic to your web application, the Teleport Proxy Service makes the application available at the following URL:

https://<APPLICATION_NAME>.<TELEPORT_DOMAIN>

For example, if your Teleport domain name is teleport.example.com, the application named my-app would be available at https://my-app.teleport.example.com. The Proxy Service presents a TLS certificate for this domain name that browsers can verify against a certificate authority.

If you are using Teleport Enterprise (Cloud), DNS records and TLS certificates for this domain name are provisioned automatically. If you are self-hosting Teleport, you must configure these yourself:

  1. Create either:

    • A DNS A record that associates a wildcard subdomain of your Teleport Proxy Service domain, e.g., *.teleport.example.com, with the IP address of the Teleport Proxy Service.
    • A DNS CNAME record that associates a wildcard subdomain of your Proxy Service domain, e.g., *.teleport.example.com, with the domain name of the Teleport Proxy Service.
  2. Ensure that your system provisionings TLS certificates for Teleport-registered applications. The method to use depends on how you originally set up TLS for your self-hosted Teleport deployment, and is outside the scope of this guide.

    In general, the same system that provisions TLS certificates signed for the web address of the Proxy Service (e.g., teleport.example.com) must also provision certificates for the wildcard address used for applications (e.g., *.teleport.example.com).

Step 3/3. Configure RBAC and access the application

  1. Create a role called demo-app-access that allows access to applications with the env:demo label that you assigned to the application that you enrolled earlier:

    kind: role
    version: v7
    metadata:
      name: demo-app-access
    spec:
      allow:
        app_labels:
          env: "demo"
    
  2. Create a user called appuser with the demo-app-access role:

    tctl users add --roles=demo-app-access appuser

    When appuser attempts to access the application you enrolled earlier through the Teleport Web UI, the the Teleport Proxy Service forwards the request with a Teleport-signed JSON web token to the Teleport Application Service. The Application Service checks the user's roles and, since the value of allow.app_labels matches one of the labels assigned to the application, the Application Service forwards the request to the application.

  3. Sign in to the Teleport Web UI as appuser. You should see the option to visit the web application that you enrolled.

Advanced options

Application name

An application name should make a valid sub-domain (<=63 characters, no spaces, only a-z 0-9 - allowed).

After Teleport is running, users can access the app at app-name.proxy_public_addr.com e.g. grafana.teleport.example.com. You can also override public_addr e.g grafana.acme.com if you configure the appropriate DNS entry to point to the Teleport proxy server.

Running the dumper application

For testing and debugging purposes, we provide a built-in debug app called "dumper". It can be turned on using debug_app: true.

app_service:
   enabled: yes
   debug_app: true

The dumper app will dump all the request headers in the response.

Customize public address

For self-hosted environments only

The public address of apps cannot be changed or overridden on cloud-hosted Teleport tenants, due to TLS certificate limitations.

For cloud-hosted customers, apps will always be available at https://<app-name>.example.teleport.sh, where example is the name chosen for your cloud-hosted Teleport tenant.

By default applications are available at <app-name>.<proxy-host>:<proxy-port> address. To override the public address, specify the public_addr field:

- name: "jira"
  uri: "https://localhost:8001"
  public_addr: "jira.example.com"

Skip TLS certificate verification

Danger Zone

This is insecure and not recommended for use in production.

Teleport checks if the certificates presented by the applications are signed by a trusted Certificate Authority. When using self-signed certificates for internal applications, use insecure_skip_verify: true to skip this verification step:

- name: "app"
  uri: "https://localhost:8443"
  public_addr: "app.example.com"
  insecure_skip_verify: true

Some applications are available in a subdirectory. Examples include the Kubernetes Dashboard.. The URI should be updated to include the subdirectory:

- name: "k8s"
  uri: "http://10.0.1.60:8001/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/#/overview"
  public_addr: "k8s.example.com"

Rewrite redirect

To support web apps that perform internal redirects, application access provides an option to rewrite the hostname of the Location header on redirect responses to the application's public address:

- name: "jenkins"
  uri: "https://localhost:8001"
  public_addr: "jenkins.example.com"
  rewrite:
    # Rewrite the "Location" header on redirect responses replacing the
    # host with the public address of this application.
    redirect:
    - "localhost"
    - "jenkins.internal.dev"

Headers passthrough

You can configure application access to inject additional headers in the requests forwarded to a web application.

For apps defined in the teleport.yaml configuration, the headers field of each app is a list of strings. Be careful to quote the entire value to ensure it is parsed correctly.

- name: "dashboard"
  uri: https://localhost:4321
  public_addr: dashboard.example.com
  rewrite:
    headers:
    # Inject a static header.
    - "X-Custom-Header: example"
    # Inject headers with internal/external user traits.
    - "X-Internal-Trait: {{internal.logins}}"
    - "X-External-Trait: {{external.env}}"
    # Inject header with Teleport-signed JWT token.
    - "Authorization: Bearer {{internal.jwt}}"
    # Override Host header.
    - "Host: dashboard.example.com"

In a dynamic app resource, configure header rewrites with the spec.rewrite.headers field. The value is a list of mappings that specify the name and value of each header you would like to rewrite.

kind: app
version: v3
metadata:
  name: "dashboard"
spec:
  uri: https://localhost:4321
  public_addr: dashboard.example.com
  rewrite:
    headers:
      # Inject a static header.
      - name: X-Custom-Header
        value: example
      # Inject headers with internal/external user traits.
      - name: X-Internal-Trait
        value: "{{internal.logins}}"
      - name: X-External-Trait
        value: "{{external.env}}"
      # Inject header with Teleport-signed JWT token.
      - name: Authorization
        value: "Bearer {{internal.jwt}}"
      # Override Host header.
      - name: Host
        value: dashboard.example.com

Headers injected this way override any headers with the same names that may be sent by an application. The following headers are reserved and can't be rewritten:

  • Teleport-Jwt-Assertion
  • Cf-Access-Token
  • Any header matching the pattern X-Teleport-*
  • Any header matching the pattern X-Forwarded-*

Rewritten header values support the same templating variables as role templates. In the example above, X-Internal-Trait header will be populated with the value of internal user trait logins and X-External-Trait header will get the value of the user's external env trait coming from the identity provider.

Additionally, the {{internal.jwt}} template variable will be replaced with a JWT token signed by Teleport that contains user identity information. See Integrating with JWTs for more details.

For full details on configuring Teleport roles, including how Teleport populates the external and internal traits, see the Teleport Access Controls Reference.

Configuring the JWT token

By default, Teleport includes a user's roles and traits in the JWT generated for application access. If your application doesn't care about these values, or you are encountering an error due to exceeding the size limit of HTTP headers, you can configure Teleport to omit this information from the token.

- name: "dashboard"
  uri: https://localhost:4321
  public_addr: dashboard.example.com
  rewrite:
    # Specify whether to include roles or traits in the JWT.
    # Options:
    # - roles-and-traits: include both roles and traits
    # - roles: include only roles
    # - traits: include only traits
    # - none: exclude both roles and traits from the JWT token
    # Default: roles-and-traits
    jwt_claims: roles-and-traits
    headers:
    # Inject header with Teleport-signed JWT token.
    - "Authorization: Bearer {{internal.jwt}}"

Backends-for-Frontends support

By default, Teleport will only attempt to authenticate the user for the requested app when launched from the Web UI. If this is a client application that makes requests to a different backend application that is also protected by Teleport, then the client application will not be able to make requests to that backend application until a user has authenticated with both apps. In order to remedy this, you can add the backend application name in the required_apps field in the client app's spec which will then automatically attempt authentication with each of the listed required apps when a user launches the client application.

- name: 'dashboard'
  uri: https://localhost:4321
  public_addr: dashboard.example.com
  # Optional list of Teleport application names that require a session for this app to function correctly.
  # When launching this app, any app listed here will also be launched, and a session will be created.
  # These sessions follow their respective RBAC policies.
  required_apps:
    - 'my-api'
    - 'prod-database'
    # Add more required app names as needed

CORS support for preflight requests

Teleport does not send any unauthenticated requests to the destination app. This means that any preflight requests sent by an application to another application within Teleport for an API request will return an error and fail. You can specify a CORS spec per application that will respond to these preflight requests. This does not overwrite the destination app's CORS policy for the requested route, but is only used for the OPTION requests sent to the requested route.

- name: 'dashboard'
  uri: https://localhost:4321
  public_addr: dashboard.example.com
  # Optional CORS policy is used for preflight requests only. It does not overwrite the contained
  # app's CORS policy per route but is used by Teleport to respond to unauthenticated OPTION requests.
  # Important Notes:
  # - Each field in the CORS spec is optional.
  # - The allowed_headers field accepts wildcard entries. However, in requests with "allow_credentials: true",
  #   a wildcard is treated as the literal header name "*" without special semantics.
  # - The Authorization header can't be set with a wildcard and always needs to be listed explicitly.
  cors:
    # Specifies which origins are allowed to make cross-origin requests.
    allowed_origins:
      - 'https://example.com'
      - 'https://app.example.com'
    # HTTP methods that are allowed when accessing the resource.
    allowed_methods:
      - 'GET'
      - 'POST'
      - 'PUT'
      - 'DELETE'
      - 'OPTIONS'
    # HTTP headers that can be used during the actual request.
    allowed_headers:
      - 'Content-Type'
      - 'Authorization'
      - 'X-Custom-Header'
    # Headers that browsers are allowed to access.
    exposed_headers:
      - 'Content-Type'
      - 'X-Custom-Response-Header'
    # Indicates whether the request can include credentials.
    allow_credentials: true
    # Indicates how long (in seconds) the results of a preflight request can be cached.
    max_age: 3600

View applications in Teleport

Teleport provides a UI for quickly launching connected applications.

They can be viewed by navigating to a cluster's web UI and selecting the "Applications" tab. The URL structure looks like this:

https://[cluster-url:cluster-port]/web/cluster/[cluster-name]/apps

Logging out of applications

When you log into an application, you'll get a certificate and login session per your defined RBAC. If you want to force log out before this period you can do so by hitting the /teleport-logout endpoint:

  • https://internal-app.teleport.example.com/teleport-logout

Next steps