> For the complete documentation index, see [llms.txt](https://t1t.gitbook.io/t1c-distribution-service-v3-guide/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://t1t.gitbook.io/t1c-distribution-service-v3-guide/3.0.8/configuration.md).

# Configuration

## Keycloak

Once Keycloak has been deployed, a realm must be created (matching the values defined in the DS API configuration):

![Create Realm](/files/-MD-pGyoTEeP9W4oJmcn)

A client must also be created:

![Create Client](/files/-MD-pqVhwgjpDowNz-0R)

![Configure Client](/files/-MD-qJDp-s2t0cyLCWYq)

{% hint style="info" %}
Configure your client with the correct `Web Origins` and `Valid Redirect URIs` for your setup. If you wish to obtain access tokens via a password grant, enable `Direct Access Grants` and `Implicit Flow`. This may simplify obtaining tokens for an initial setup of the DS
{% endhint %}

In order for the `Kong` gateway to be able to validate the tokens issued by the realm client, the DS keystore must be configured as a `Key Provider`

![Add Keystore - Java Keystore](/files/-MD-rDBoi9ukrqcs_WBG)

![Configure Key Provider](/files/-MD-rOx2Zzh3yXDWrwDD)

When configuring the keystore, specify the keystore path (either mounted as a volume in your container or on the server filesystem) in the `Keystore` field. Also you **must** make sure the keystore has a higher `Priority` value than the other default providers.

{% hint style="warning" %}
The keystore must contain the same key pair as the keystore used by the DS API
{% endhint %}

After creating a user, you can obtain an access token using the implicit flow by performing the following request:

```bash
curl --location --request POST 'http://localhost:9999/auth/realms/trust1connector/protocol/openid-connect/token' \
    --header 'Content-Type: application/x-www-form-urlencoded' \
    --data-urlencode 'client_id=trust1connector' \
    --data-urlencode 'username=test@trust1team.com' \
    --data-urlencode 'password=test_password' \
    --data-urlencode 'grant_type=password'
```

This token can then be used to address the secured DS API endpoints

## Distribution Service API

The configuration of the Distribution Service API can be done entirely through environment variables, or directly by editing the `application.conf` which can be found in the `conf` folder in the server distributable. An overview of both configuration options can be found below.

### Configuration Options

| Key                                                         | Environment Variable                | Type    | Description                                                                                                                                                                                                                        |
| ----------------------------------------------------------- | ----------------------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| t1c-ds.general.**max-page-size**                            | DS\_MAX\_PAGE\_SIZE                 | Integer | The maximum allowed pagination size for results. This can be used in order to prevent the retrieval of too large a sample result. Default value is 100.                                                                            |
| t1c-ds.t1c.**domain**                                       | T1C\_DOMAIN                         | String  | The domain the T1C runs on.                                                                                                                                                                                                        |
| t1c-ds.t1c.**port**                                         | T1C\_PORT                           | Integer | The port the T1C runs on.                                                                                                                                                                                                          |
| t1c-ds.rmc.**label**                                        | RMC\_LABEL                          | String  | The application label that can be used by the RMC web application.                                                                                                                                                                 |
| t1c-ds.development.**include-stacktrace**                   | INCLUDE\_STACKTRACE                 | Boolean | Include a stacktrace in the application's JSON response, which can be useful for debugging purposes. **Must** be set to false in production environments                                                                           |
| t1c-ds.development.**require-gateway-headers**              | REQUIRE\_GATEWAY\_HEADERS           | Boolean | Incoming requests are checked for the presence of a `X-Consumer-Custom-ID` header placed by the gateway                                                                                                                            |
| t1c-ds.keystore.**path**                                    | DS\_KEYSTORE\_PATH                  | String  | The path (can be relative to the application root) to the DS API keystore in PKCS12 format, containing the DS certificate/keypair.                                                                                                 |
| t1c-ds.keystore.**password**                                | DS\_KEYSTORE\_PASSWORD              | String  | The password to the DS API keystore. This is sensitive information. We recommend storing it as an environment variable.                                                                                                            |
| t1c-ds.keystore.**alias**                                   | DS\_KEYSTORE\_ALIAS                 | String  | The alias of the DS API certificate/keypair stored in the keystore.                                                                                                                                                                |
| t1c-ds.security.**enabled**                                 | DS\_SECURITY\_ENABLED               | Boolean | Enables or disables the parsing of JSON web tokens on incoming requests. If set to false, all JWT payloads will be set to a default blank value. This **must** be set to true in production environments.                          |
| t1c-ds.security.jwt.**ds-issuer**                           | DS\_ISSUER                          | String  | The name of the DS API token issuer. It is used to generate JSON web tokens containing digests of configuration files.                                                                                                             |
| t1c-ds.security.jwt.**idp-issuer**                          | DS\_IDP\_ISSUER                     | String  | The name of the IDP token issuer. This is the value that can be found in the `iss` property in tokens issued by your configured IDP client. For Keyloak, this will take the form of `https://{{idp-url}}/auth/realms/{{realmId}}`. |
| t1c-ds.security.jwt.**registration-token-validity-seconds** | DS\_REG\_TOKEN\_VALIDITY\_SECONDS   | Integer | The seconds a token issued for a registration API key should remain valid.                                                                                                                                                         |
| t1c-ds.security.jwt.**application-token-validity-seconds**  | DS\_APP\_TOKEN\_VALIDITY\_SECONDS   | Integer | The seconds a token issued for a label API key should remain valid.                                                                                                                                                                |
| t1c-ds.gateway.**enabled**                                  | DS\_GATEWAY\_ENABLED                | Boolean | Set to false while developing in order to test the DS API without needing a Kong gateway to be available. **Must** be set to true for production environments.                                                                     |
| t1c-ds.gateway.**url**                                      | DS\_GATEWAY\_URL                    | String  | The `Kong` gateway URL. This value is used to generate download links for the Trust1Connector installer.                                                                                                                           |
| t1c-ds.gateway.**admin-url**                                | DS\_GATEWAY\_ADMIN\_URL             | String  | The Kong gateway admin API URL. This URL is used to dynamically create API keys for labels and versions.                                                                                                                           |
| t1c-ds.gateway.**ds-base-path**                             | DS\_GATEWAY\_BASE\_PATH             | String  | Used for generation of download links. If you route the DS on a non-default path, i.e. not on the root of the `Kong` gateway, you can specify it here. Default value is an empty string                                            |
| t1c-ds.gateway.config.consumers.**registration**            | DS\_GATEWAY\_CONSUMER\_REGISTRATION | String  | The `username` and `custom_id` of the registration consumer entity on the `Kong` gateway.                                                                                                                                          |
| t1c-ds.gateway.config.consumers.**application**             | DS\_GATEWAY\_CONSUMER\_APPLICATION  | String  | The `username`  and `custom_id` of the registration application entity on the `Kong` gateway.                                                                                                                                      |
| t1c-ds.gateway.config.consumers.**user**                    | DS\_GATEWAY\_CONSUMER\_USER         | String  | The `username` and `custom_id` of the registration consumer entity on the `Kong` gateway.                                                                                                                                          |
| slick.dbs.default.db.**url**                                | T1C\_DB\_URL                        | String  | The JNDI value for the PostgreSQL database to be used by the DS API, e. `jdbc:postgresql://localhost:5433/t1c-ds`                                                                                                                  |
| slick.dbs.default.db.**user**                               | T1C\_DS\_DB\_USER                   | String  | The PostgreSQL database username that has owner access to the `t1c-ds` database. We recommend storing this information as an environment variable.                                                                                 |
| slick.dbs.default.db.**password**                           | T1C\_DS\_DB\_PWD                    | String  | The PostgreSQL database user's password. We recommend storing this information as an environment variable.                                                                                                                         |
| play.evolutions.db.default.**enabled**                      | T1C\_EVOLUTIONS\_ENABLED            | Boolean | Toggle whether database evolutions are enabled. We recommend setting it to `false` in production environments and manually updating the database models with a script.                                                             |
| play.evolutions.db.default.**autoApply**                    | T1C\_EVOLUTIONS\_AUTO               | Boolean | Toggle whether database evolutions are automatically applied. We recommend setting it to `false` in production environments and manually updating the database models with a script.                                               |
| play.evolutions.db.default.**autoApplyDowns**               | T1C\_EVOLUTIONS\_AUTO\_DOWNS        | Boolean | Toggle whether database evolution downgrades are automatically applied. This **must** be set to `false` in production environments or data loss may occur.                                                                         |
| play.http.secret.**key**                                    | PLAY\_SECRET                        | String  | A secret used for built-in encryption utilities, signing session cookies and CSRF tokens, amongst other. This value **must** be set, and must be unique per environment.                                                           |
| pidfile.**path**                                            | PIDFILE\_PATH                       | String  | The path where the RUNNING\_PID file will be created. For dockerized environments, this must be set to `/dev/null`                                                                                                                 |

### Sample Configuration File

```javascript
# Version -> should match version in build.sbt
app.version = "3.0.0"

# Application specific config. Every property is duplicated with a value that can be read from the environment variables
# So that we can reuse the same config file in various environments
t1c-ds {
  general {
    max-page-size = 100
    max-page-size = ${?DS_MAX_PAGE_SIZE}
  }
  development {
    include-stacktrace = true
    include-stacktrace = ${?INCLUDE_STACKTRACE}
    require-gateway-headers = false
    require-gateway-headers = ${?REQUIRE_GATEWAY_HEADERS}
  }
  keystore {
    path = "conf/t1cds.p12"
    path = ${?DS_KEYSTORE_PATH}
    password = "v8%j22HVvHEiC9>e"
    password = ${?DS_KEYSTORE_PASSWORD}
    alias = "t1cds"
    alias = ${?DS_KEYSTORE_ALIAS}
  }
  security {
    enabled = false
    enabled = ${?DS_SECURITY_ENABLED}
    jwt {
      ds-issuer = "t1c-ds"
      ds-issuer = ${?DS_ISSUER}
      # For example
      # idp-issuer = "https://idp.t1t.io/auth/realms/trust1connector"
      idp-issuer = "http://localhost:9999/auth/realms/trust1connector"
      idp-issuer = ${?DS_IDP_ISSUER}
      registration-token-validity-seconds = 600
      registration-token-validity-seconds = ${?DS_REG_TOKEN_VALIDITY_SECONDS}
      application-token-validity-seconds = 600
      application-token-validity-seconds = ${?DS_APP_TOKEN_VALIDITY_SECONDS}
    }
  }
  gateway {
    enabled = true
    enabled = ${?DS_GATEWAY_ENABLED}
    url = "http://localhost:8000"
    url = ${?DS_GATEWAY_URL}
    admin-url = "http://localhost:8001"
    admin-url = ${?DS_GATEWAY_ADMIN_URL}
    # If the DS isn't hosted on the root of the gateway, set the path prefix here
    ds-base-path = ""
    ds-base-path = ${?DS_GATEWAY_BASE_PATH}
    config {
      consumers {
        registration = "t1cds-reg"
        application = "t1cds-app"
        user = "t1cds-user"
        registration = ${?DS_GATEWAY_CONSUMER_REGISTRATION}
        application = ${?DS_GATEWAY_CONSUMER_APPLICATION}
        user = ${?DS_GATEWAY_CONSUMER_USER}
      }
    }
  }
}

slick {
  db.default.logSql=true
  dbs.default.profile = "slick.jdbc.PostgresProfile$"
  dbs.default.db.driver = "org.postgresql.Driver"
  dbs.default.db.url = "jdbc:postgresql://localhost:5433/t1c-ds"
  dbs.default.db.url = ${?T1C_DB_URL}
  dbs.default.db.user = "postgres"
  dbs.default.db.user = ${?T1C_DS_DB_USER}
  dbs.default.db.password = "postgres"
  dbs.default.db.password = ${?T1C_DS_DB_PWD}
  # dbs.default.db.numThreads = 20
  # dbs.default.db.maxConnections = 20
}

## Evolutions
# https://www.playframework.com/documentation/latest/Evolutions
# ~~~~~
# Evolutions allows database scripts to be automatically run on startup in dev mode
# for database migrations. You must enable this by adding to build.sbt:
#
# libraryDependencies += evolutions
#
## Evolutions
play.evolutions {
  db.default.enabled = true
  db.default.autoApply = true
  db.default.autoApplyDowns = true
  schema = "public"
  db.default.enabled = ${?T1C_EVOLUTIONS_ENABLED}
  db.default.autoApply = ${?T1C_EVOLUTIONS_AUTO}
  db.default.autoApplyDowns = ${?T1C_EVOLUTIONS_AUTO_DOWNS}
  schema = ${?T1C_EVOLUTIONS_SCHEMA}
}

# This is the main configuration file for the application.
# https://www.playframework.com/documentation/latest/ConfigFile
# https://www.playframework.com/documentation/latest/Configuration
# ~~~~~
# Play uses HOCON as its configuration file format.  HOCON has a number
# of advantages over other config formats, but there are two things that
# can be used when modifying settings.
#
# You can include other configuration files in this main application.conf file:
#include "extra-config.conf"
#
# You can declare variables and substitute for them:
#mykey = ${some.value}
#
# And if an environment variable exists when there is no other subsitution, then
# HOCON will fall back to substituting environment variable:
#mykey = ${JAVA_HOME}

## Akka
# https://www.playframework.com/documentation/latest/ScalaAkka#Configuration
# https://www.playframework.com/documentation/latest/JavaAkka#Configuration
# ~~~~~
# Play uses Akka internally and exposes Akka Streams and actors in Websockets and
# other streaming HTTP responses.
akka {
  # "akka.log-config-on-start" is extraordinarly useful because it log the complete
  # configuration at INFO level, including defaults and overrides, so it s worth
  # putting at the very top.
  #
  # Put the following in your conf/logback.xml file:
  #
  # <logger name="akka.actor" level="INFO" />
  #
  # And then uncomment this line to debug the configuration.
  #
  #log-config-on-start = true
}

## Secret key
# https://www.playframework.com/documentation/latest/ApplicationSecret
# ~~~~~
# The secret key is used to sign Play's session cookie.
# This must be changed for production, but we don't recommend you change it in this file.
play.http.secret.key = ${?PLAY_SECRET}
pidfile.path = ${?PIDFILE_PATH}

## Modules
# https://www.playframework.com/documentation/latest/Modules
# ~~~~~
# Control which modules are loaded when Play starts.  Note that modules are
# the replacement for "GlobalSettings", which are deprecated in 2.5.x.
# Please see https://www.playframework.com/documentation/latest/GlobalSettings
# for more information.
#
# You can also extend Play functionality by using one of the publically available
# Play modules: https://playframework.com/documentation/latest/ModuleDirectory
play.modules {
  # By default, Play will load any class called Module that is defined
  # in the root package (the "app" directory), or you can define them
  # explicitly below.
  # If there are any built-in modules that you want to disable, you can list them here.
  #enabled += my.application.Module

  # If there are any built-in modules that you want to disable, you can list them here.
  #disabled += ""
}

## IDE
# https://www.playframework.com/documentation/latest/IDE
# ~~~~~
# Depending on your IDE, you can add a hyperlink for errors that will jump you
# directly to the code location in the IDE in dev mode. The following line makes
# use of the IntelliJ IDEA REST interface:
#play.editor="http://localhost:63342/api/file/?file=%s&line=%s"

## Internationalisation
# https://www.playframework.com/documentation/latest/JavaI18N
# https://www.playframework.com/documentation/latest/ScalaI18N
# ~~~~~
# Play comes with its own i18n settings, which allow the user's preferred language
# to map through to internal messages, or allow the language to be stored in a cookie.
play.i18n {
  # The application languages
  langs = [ "en" ]

  # Whether the language cookie should be secure or not
  #langCookieSecure = true

  # Whether the HTTP only attribute of the cookie should be set to true
  #langCookieHttpOnly = true
}

## Filters
# https://www.playframework.com/documentation/latest/ScalaHttpFilters
# https://www.playframework.com/documentation/latest/JavaHttpFilters
# ~~~~~
# Filters run code on every request. They can be used to perform
# common logic for all your actions, e.g. adding common headers.
#
play.filters {

  # Enabled filters are run automatically against Play.
  # CSRFFilter, AllowedHostFilters, and SecurityHeadersFilters are enabled by default.

  # Disabled filters remove elements from the enabled list.
  disabled += play.filters.hosts.AllowedHostsFilter
}

## Play HTTP settings
# ~~~~~
play.http {
  ## Router
  # https://www.playframework.com/documentation/latest/JavaRouting
  # https://www.playframework.com/documentation/latest/ScalaRouting
  # ~~~~~
  # Define the Router object to use for this application.
  # This router will be looked up first when the application is starting up,
  # so make sure this is the entry point.
  # Furthermore, it's assumed your route file is named properly.
  # So for an application router like `my.application.Router`,
  # you may need to define a router file `conf/my.application.routes`.
  # Default to Routes in the root package (aka "apps" folder) (and conf/routes)
  #router = my.application.Router

  ## Action Creator
  # https://www.playframework.com/documentation/latest/JavaActionCreator
  # ~~~~~
  #actionCreator = null

  ## ErrorHandler
  # https://www.playframework.com/documentation/latest/JavaRouting
  # https://www.playframework.com/documentation/latest/ScalaRouting
  # ~~~~~
  # If null, will attempt to load a class called ErrorHandler in the root package,
  #errorHandler = null

  ## Session & Flash
  # https://www.playframework.com/documentation/latest/JavaSessionFlash
  # https://www.playframework.com/documentation/latest/ScalaSessionFlash
  # ~~~~~
  session {
    # Sets the cookie to be sent only over HTTPS.
    #secure = true

    # Sets the cookie to be accessed only by the server.
    #httpOnly = true

    # Sets the max-age field of the cookie to 5 minutes.
    # NOTE: this only sets when the browser will discard the cookie. Play will consider any
    # cookie value with a valid signature to be a valid session forever. To implement a server side session timeout,
    # you need to put a timestamp in the session and check it at regular intervals to possibly expire it.
    #maxAge = 300

    # Sets the domain on the session cookie.
    #domain = "example.com"
  }

  flash {
    # Sets the cookie to be sent only over HTTPS.
    #secure = true

    # Sets the cookie to be accessed only by the server.
    #httpOnly = true
  }
}

## Netty Provider
# https://www.playframework.com/documentation/latest/SettingsNetty
# ~~~~~
play.server.netty {
  # Whether the Netty wire should be logged
  #log.wire = true

  # If you run Play on Linux, you can use Netty's native socket transport
  # for higher performance with less garbage.
  #transport = "native"
}

## WS (HTTP Client)
# https://www.playframework.com/documentation/latest/ScalaWS#Configuring-WS
# ~~~~~
# The HTTP client primarily used for REST APIs.  The default client can be
# configured directly, but you can also create different client instances
# with customized settings. You must enable this by adding to build.sbt:
#
# libraryDependencies += ws // or javaWs if using java
#
play.ws {
  # Sets HTTP requests not to follow 302 requests
  #followRedirects = false

  # Sets the maximum number of open HTTP connections for the client.
  #ahc.maxConnectionsTotal = 50

  ## WS SSL
  # https://www.playframework.com/documentation/latest/WsSSL
  # ~~~~~
  ssl {
    # Configuring HTTPS with Play WS does not require programming.  You can
    # set up both trustManager and keyManager for mutual authentication, and
    # turn on JSSE debugging in development with a reload.
    #debug.handshake = true
    #trustManager = {
    #  stores = [
    #    { type = "JKS", path = "exampletrust.jks" }
    #  ]
    #}
  }
}

## Cache
# https://www.playframework.com/documentation/latest/JavaCache
# https://www.playframework.com/documentation/latest/ScalaCache
# ~~~~~
# Play comes with an integrated cache API that can reduce the operational
# overhead of repeated requests. You must enable this by adding to build.sbt:
#
# libraryDependencies += cache
#
play.cache {
  # If you want to bind several caches, you can bind the individually
  #bindCaches = ["db-cache", "user-cache", "session-cache"]
}

## Filters
# https://www.playframework.com/documentation/latest/ScalaHttpFilters
# https://www.playframework.com/documentation/latest/JavaHttpFilters
# ~~~~~
# Filters run code on every request. They can be used to perform
# common logic for all your actions, e.g. adding common headers.
#

## Filter Configuration
# https://www.playframework.com/documentation/latest/Filters
# ~~~~~
# There are a number of built-in filters that can be enabled and configured
# to give Play greater security.
#
play.filters.disabled += play.filters.csrf.CSRFFilter
play.filters {
  ## CORS filter configuration
  # https://www.playframework.com/documentation/latest/CorsFilter
  # ~~~~~
  # CORS is a protocol that allows web applications to make requests from the browser
  # across different domains.
  # NOTE: You MUST apply the CORS configuration before the CSRF filter, as CSRF has
  # dependencies on CORS settings.
  cors {
    # Filter paths by a whitelist of path prefixes
    #pathPrefixes = ["/some/path", ...]

    # The allowed origins. If null, all origins are allowed.
    #allowedOrigins = ["https://www.example.com"]

    # The allowed HTTP methods. If null, all methods are allowed
    #allowedHttpMethods = ["GET", "POST"]
  }

  ## CSRF Filter
  # https://www.playframework.com/documentation/latest/ScalaCsrf#Applying-a-global-CSRF-filter
  # https://www.playframework.com/documentation/latest/JavaCsrf#Applying-a-global-CSRF-filter
  # ~~~~~
  # Play supports multiple methods for verifying that a request is not a CSRF request.
  # The primary mechanism is a CSRF token. This token gets placed either in the query string
  # or body of every form submitted, and also gets placed in the users session.
  # Play then verifies that both tokens are present and match.
  csrf {
    # Sets the cookie to be sent only over HTTPS
    #cookie.secure = true

    # Defaults to CSRFErrorHandler in the root package.
    #errorHandler = MyCSRFErrorHandler
  }

  ## Security headers filter configuration
  # https://www.playframework.com/documentation/latest/SecurityHeaders
  # ~~~~~
  # Defines security headers that prevent XSS attacks.
  # If enabled, then all options are set to the below configuration by default:
  headers {
    # The X-Frame-Options header. If null, the header is not set.
    #frameOptions = "DENY"

    # The X-XSS-Protection header. If null, the header is not set.
    #xssProtection = "1; mode=block"

    # The X-Content-Type-Options header. If null, the header is not set.
    #contentTypeOptions = "nosniff"

    # The X-Permitted-Cross-Domain-Policies header. If null, the header is not set.
    #permittedCrossDomainPolicies = "master-only"

    # The Content-Security-Policy header. If null, the header is not set.
    #contentSecurityPolicy = "default-src 'self'"
  }

  ## Allowed hosts filter configuration
  # https://www.playframework.com/documentation/latest/AllowedHostsFilter
  # ~~~~~
  # Play provides a filter that lets you configure which hosts can access your application.
  # This is useful to prevent cache poisoning attacks.
  hosts {
    # Allow requests to example.com, its subdomains, and localhost:9000.
    #allowed = [".example.com", "localhost:9000"]
  }
}
```

## Kong

The `Kong` gateway can be configured in 2 ways:

1. By letting the DS bootstrap the gateway using its default and configured values
2. By running a script

{% hint style="info" %}
The second option requires that the machine the script is executed on can access the admin API of the Kong Gateway.
{% endhint %}

### DS Bootstrapping

Using a valid token obtained from Keycloak, execute the following request:

```javascript
curl --location --request POST 'http://localhost:4600/v3/gateway/bootstrap' \
--header 'Authorization: Bearer eyJ...MZA' \
--header 'Content-Type: application/json' \
--data-raw '{
    "dsServiceName": "t1c-ds-v3",
    "dsServiceHost": "t1c-ds",
    "dsPort": 9000
}'
```

| Property      | Description                                                                    |
| ------------- | ------------------------------------------------------------------------------ |
| dsServiceName | The name of the DS API service to create on the gateway. Can be freely chosen. |
| dsServiceHost | The hostname of the DS API service                                             |
| dsPort        | The port to which the gateway can proxy requests                               |

### Script

You can also run a script to configure the `Kong` gateway. However, you need to adjust the script to your needs prior to executing it. You **must** also run it on  a device on which `curl` is available.

```javascript
# Adjust the service host and port to the correct values, as well as the gateway admin URL

# Create service
curl \
  --verbose \
  --request PUT \
  --header 'Content-Type: application/json' \
  --data '{"name":"t1c-ds-v3","host":"t1c-ds","port":9000}' \
  'http://localhost:8001/services/t1c-ds-v3'
# Create JWT Auth route
curl \
  --verbose \
  --request PUT \
  --header 'Content-Type: application/json' \
  --data '{"name":"jwt-route","strip_path":false,"paths":["/v3/configurations/","/v3/configurations","/v3/devices/","/v3/devices","/v3/gateway/","/v3/labels/","/v3/labels","/v3/organizations/","/v3/organizations","/v3/registration/","/v3/versions/","/v3/versions","/v3/transactions/"]}' \
  'http://localhost:8001/services/t1c-ds-v3/routes/jwt-route'
# Create Key Auth route
curl \
  --verbose \
  --request PUT \
  --header 'Content-Type: application/json' \
  --data '{"name":"key-auth-route","strip_path":false,"paths":["/v3/tokens/"]}' \
  'http://localhost:8001/services/t1c-ds-v3/routes/key-auth-route'
# Create No-Auth route
curl \
  --verbose \
  --request PUT \
  --header 'Content-Type: application/json' \
  --data '{"name":"no-auth-route","strip_path":false,"paths":["/v3/system/","/v3/device/","/v3/downloads/","/rmc/","/rmc","/mgt/","/mgt","/"]}' \
  'http://localhost:8001/services/t1c-ds-v3/routes/no-auth-route'
# Create JWT route plugin
curl \
  --verbose \
  --request POST \
  --header 'Content-Type: application/json' \
  --data '{"name":"jwt","route":{"name":"jwt-route"},"config":{"run_on_preflight":false,"claims_to_verify":["exp"]}}' \
  'http://localhost:8001/routes/jwt-route/plugins'
# Create Key-Auth route plugin
curl \
  --verbose \
  --request POST \
  --header 'Content-Type: application/json' \
  --data '{"name":"key-auth","route":{"name":"key-auth-route"},"config":{"run_on_preflight":false}}' \
  'http://localhost:8001/routes/key-auth-route/plugins'
# Create User consumer
curl \
  --verbose \
  --request PUT \
  --header 'Content-Type: application/json' \
  --data '{"username":"t1cds-user","custom_id":"t1cds-user"}' \
  'http://localhost:8001/consumers/t1cds-user'
# Create Registration consumer
curl \
  --verbose \
  --request PUT \
  --header 'Content-Type: application/json' \
  --data '{"username":"t1cds-reg","custom_id":"t1cds-reg"}' \
  'http://localhost:8001/consumers/t1cds-reg'
# Create Application consumer
curl \
  --verbose \
  --request PUT \
  --header 'Content-Type: application/json' \
  --data '{"username":"t1cds-app","custom_id":"t1cds-app"}' \
  'http://localhost:8001/consumers/t1cds-app'
# Create Registration consumer JWT plugin. Replace the rsa_public_key by the PEM encoded DS public key
curl \
  --verbose \
  --request POST \
  --header 'Content-Type: application/json' \
  --data '{"key":"t1cds-reg","algorithm":"RS256","rsa_public_key":"-----BEGIN PUBLIC KEY-----\n ... [[PEM PUBLIC KEY]] ... \n-----END PUBLIC KEY-----\n"}' \
  'http://localhost:8001/consumers/t1cds-reg/jwt'
# Create Application consumer JWT plugin. Replace the rsa_public_key by the PEM encoded DS public key
curl \
  --verbose \
  --request POST \
  --header 'Content-Type: application/json' \
  --data '{"key":"t1cds-app","algorithm":"RS256","rsa_public_key":"-----BEGIN PUBLIC KEY-----\n ... [[PEM PUBLIC KEY]] ... \n-----END PUBLIC KEY-----\n"}' \
  'http://localhost:8001/consumers/t1cds-app/jwt'
# Create User consumer JWT plugin. Replace the rsa_public_key by the PEM encoded DS public key
curl \
  --verbose \
  --request POST \
  --header 'Content-Type: application/json' \
  --data '{"key":"http://localhost:9999/auth/realms/trust1connector","algorithm":"RS256","rsa_public_key":"-----BEGIN PUBLIC KEY-----\n ... [[PEM PUBLIC KEY]] ... \n-----END PUBLIC KEY-----\n"}' \
  'http://localhost:8001/consumers/t1cds-user/jwt'
```

The script contains requests to create every required entity on the `Kong` gateway. An overview can be found in the table below:

| Entity Name    | Entity Type | Enabled Plugins                                                                 | Paths                                                                                                                                                                                                                                         |
| -------------- | ----------- | ------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| t1c-ds-v3      | Service     |                                                                                 |                                                                                                                                                                                                                                               |
| jwt-route      | Route       | `jwt`                                                                           | "/v3/configurations/", "/v3/configurations", "/v3/devices/", "/v3/devices", "/v3/gateway/", "/v3/labels/", "/v3/labels", "/v3/organizations/", "/v3/organizations", "/v3/registration/", "/v3/versions/", "/v3/versions", "/v3/transactions/" |
| key-auth-route | Route       | `key-auth`                                                                      | "/v3/tokens/"                                                                                                                                                                                                                                 |
| no-auth-route  | Route       |                                                                                 | "/v3/system/", "/v3/device/", "/v3/downloads/", "/rmc/", "/rmc", "/mgt/", "/mgt", "/"                                                                                                                                                         |
| t1cds-reg      | Consumer    | `jwt` (`key-auth` plugin will be dynamically added when creating a new version) |                                                                                                                                                                                                                                               |
| t1cds-app      | Consumer    | `jwt` (`key-auth` plugin will be dynamically added when creating a new label)   |                                                                                                                                                                                                                                               |
| t1cds-user     | Consumer    | `jwt`                                                                           |                                                                                                                                                                                                                                               |
