StepZen is now part of IBM. For the most recent product information and updates go to
https://www.ibm.com/products/stepzen

Manage Configuration and Keys

Configure your API keys and database connections in StepZen

To access the data in your backends via StepZen, you need to specify authentication and connection properties such as usernames, passwords, DSN, authorizations, and so on.

The following sections describe how to specify that information:

What's a config.yaml?

You specify authentication and connection information by passing it to the appropriate connector (@rest, @dbquery, or @graphql). These are managed in a single file named config.yaml`.

The config.yaml file must be placed in the root of your StepZen project, at the same level as your index.graphql file:

my-stepzen-folder
    .
    ├── index.graphql
    ├── config.yaml
    └── schemas

config.yaml is written in YAML to relay information regarding your configuration and keys to StepZen. While a config.yaml is not always required for a schema to work, you'll generally need this file when using a REST service or a database.

What you specify in your config.yaml may differ depending on the connection type, but there are a few lines you will always need:

configurationset:
  - configuration:
      name: api_config
  - configuration: 
      name: database_config
  • configurationset: Parent that contains the full set of configurations.
  • configuration: Defines a new configuration.
  • name: Name of your configuration. This can be anything you choose.

The following subsections provide additional details about config.yaml files:

REST Configurations

If a REST service is public and you do not need an API key, you may not need a configuration. However, you can still use configurations to pass any values into @rest. For example, the following configuration contains a username key:

configurationset:
  - configuration:
      name: dev_config
      username: remotesynth

This configuration value can be used when constructing the endpoint URL, as in the following query:

type Query {
  myArticles: [Article]
    @rest(
      endpoint: "https://dev.to/api/articles?username=$username"
      configuration: "dev_config"
    )
}

In this case, the value of $username will be replaced with the value of username from dev_config (e.g., remotesynth).

Pass an API key via the Authorization Header

If a REST service requires an API key that is passed using the Authorization header, pass it via the Authorization key of the configuration:

configurationset:
  - configuration:
      name: github_config
      Authorization: Bearer MY_PERSONAL_ACCESS_TOKEN

Pass Additional Header Values

Some APIs require that you pass API keys or other values in the header via named keys other than the Authorization header. Pass these in the header by prepending header. to the key name:

configurationset:
  - configuration:
      name: dev_config
      header.api-key: MY_API_KEY

Database Configuration

The database configuration is important. Without it, StepZen can't access your deployed database. StepZen currently supports connections to MySQL, PostgreSQL, and MSSQL databases. MySQL and PostgreSQL require a slightly different type of configuration as described in the following subsections:

Note: Reach out to us on Discord if you are having any trouble connecting to your database.

MySQL Configuration

For MySQL databases, you must pass the DSN that contains the connection information for that MySQL database:

- configuration:
    name: mysql_config
    dsn: username:password@tcp(a.b.c.d:port)/dbname

The dsn value can include the following parameters:

dsn ValueDescriptionExample
usernameYour usernamejohn
passwordYour MySQL database passwordsecretpassword
a.b.c.d:portYour host and port specificationtcp(us.address.from.deployment.service:8090)
dbnameYour MySQL database namemydbname
tls(optional) Enables TLS / SSL encrypted connection to the servertls=true

The example shows the dsn portion:

dsn: john:secretpassword@tcp(us.address.from.deployment.service:8090)/mydbname

If your database requires a TLS / SSL encrypted connection, add tls=true to your dsn string:

dsn: john:secretpassword@tcp(us.address.from.deployment.service:8090)/mydbname?tls=true

Postgres Configuration

For a PostgreSQL database connection, you must provide a configuration with a URI in a format like the following:

configurationset:
  - configuration:
      name: postgresql_config
      uri: postgresql://username:password@address:port/dbname

The uri value can include the following parameters:

uri ValueDescriptionExample
postgresql://You can leave the postgresql://part of the uri as it is
usernameUsername is usernamelucy
passwordPassword in passwordmysecretpassword
addressAddress in addressaddress.from.deployment.service
portPort is port. Optional if not default 5432
dbnameDatabase name in dbnamemydbname
sslmode(optional) Enables TLS / SSL encrypted connection to the serversslmode=true

The following shows a full example for the dsn portion:

uri: 'postgresql://lucy:mysecretpassword@address.from.deployment.service/mydbname'

If your database requires a TLS / SSL encrypted connection, add sslmode=true to your uri string:

uri: 'postgresql://lucy:mysecretpassword@address.from.deployment.service/mydbname?sslmode=true'

PostgreSQL requires passwords containing special characters (like #$%&) to be URL-encoded. If your password is, for example pa$$word, it needs to be encoded as pa%24%24word. Quotes around the uri are required when it is URL-encoded. You can use the tool urlencoder.org to encode your password.

MSSQL Configuration

For MSSQL databases, you must pass the DSN that contains the connection information for that MSSQL database:

configurationset:
  - configuration:
      name: mssql_config
      dsn: "sqlserver://username:password@host:port?database=dbname"

The dsn value can include the following parameters:

dsn ValueDescriptionExample
sqlserver://You can leave the sqlserver://part of the uri as it is
usernameYour usernamelucy
passwordYour passwordmysecretpassword
hostHost name or IP address192.0.2.146
portHost port, the default port is 14331433
databaseYour MSSQL database name.database=mydbname
encrypt(optional) Enables TLS / SSL encrypted connection to the serverencrypt=true

The following shows an example for the dsn portion:

dsn: sqlserver://lucy:mysecretpassword@192.0.2.146:1433?database=mydbname

If your database requires TLS/SSL encrypted connection, add encrypt=true to your dns string:

dsn: sqlserver://lucy:mysecretpassword@192.0.2.146:1433?database=mydbname&encrypt=true

Snowflake Configuration

For Snowflake databases, you must pass the DSN that contains the connection information for that Snowflake database:

configurationset:
  - configuration:
      name: snowflake_config
      dsn: "username:password@account_identifier/database/schemaname?warehouse=warehousename"

The dsn value can include the following parameters:

dsn ValueDescriptionExample
usernameYour usernamelucy
passwordYour passwordmysecretpassword
account_identifierYour account identifierac123456.us-central1.gcp
databaseYour Snowflake database namemydbname
schemanameYour Snowflake schema namemyschemaname
warehousenameYour Snowflake warehouse namewarehouse=mydbname_wh

The account identifier depends upon your Snowflake account edition. For information, see the Snowflake documentation.

The following shows an example for the dsn portion:

dsn: "lucy:mysecretpassword@ac123456.us-centra1.gcp/mydbname/myschemaname?warehouse=mydbname_wh"

Environment Variables

You can use environment variables within your StepZen config.yaml file. This enables you to keep sensitive information such as API keys and DSN strings outside of your code base, while still leveraging it within your schema configuration. The only rule is that the environment variable name must be prefaced with a STEPZEN_.

If there is a .env file in the project folder, StepZen CLI automatically loads all environment variables defined there that are not already set in the CLI's environment.

For example, if you store the DSN information or a MySQL connection within a .env file as follows:

STEPZEN_MYSQL_DSN=username:password@tcp(us-cdbr-east-03.cleardb.com)/database_name

You can then reference the value of STEPZEN_MYSQL_DSN within a configuration inside config.yaml:

configurationset:
  - configuration:
      name: mysql_config
      dsn: STEPZEN_MYSQL_DSN

Note: This doesn't just apply to DSN configurations. You can use environment variables in place of API keys as well.

Authorization Headers in the GraphQL Schema

In some cases, such as when running a @sequence directive, GraphQL arguments can be passed as header variables in an HTTP request. In the example below, an argument of access_token: String is passed to the authorization header as a bearer token:

type Query {
    id: String 
}

type Query {
    my_query(access_token: String): Query
        @rest (
            endpoint: "https://api.example.com/v1/api/"
            headers: [{ name: "Authorization", value: "$access_token" }]
        )
}

Query

When running the GraphQL query, the access_token: String argument is "Bearer <YOUR_ACCESS_TOKEN>" where <YOUR_ACCESS_TOKEN> must be replaced by your own access token, and contain the entire string for the Authorization header:

query MyQuery {
  my_query(
    access_token: "Bearer <YOUR_ACCESS_TOKEN>"
  ) {
    id
  }
}

If the access_token argument is not provided in the query, or if it is explicitly set to null, StepZen resolves the Authorization header to an empty string, "".

This is an example query where there is no access_token argument provided:

query MyQuery {
  my_query {
    id
  }
}

Authorization: "null" is converted to Authorization: "" to prevent server errors and avoid sending unwanted null arguments as headers.

Combine Variables with Strings in Authorization Headers

StepZen also supports strings combined with variables in header arguments.

As shown in the schema below, my_query will combine the GraphQL argument access_token with a literal string Bearer:

my_query(access_token: String): Query
        @rest (
            endpoint: "https://api.example.com/v1/api/"
            headers: [{ name: "Authorization", value: "Bearer $access_token" }]
        )

When my_query is executed, access_token does not need to contain the Bearer string. The schema combines the Bearer string with the access_token:

query MyQuery {
  my_query(
    access_token: "CMORsM63LxIO_4eBAEBAgAAMAEAAAAYY_MDnCSCXsaQLKM_AFzIUdnIEl9qo7Cwj2t1Z_rNAec5zYls6LgB_b8f_BwyE_wf8_-D_fc4sAAAAYAYY9DwfIBgcgA_gwx8GGQAAOIUnAADgAOBCFBZjpguluSl9IBk0ni7_U1o-pPgjSgNuYTFSAFoA"
  ) {
    id
  }
}

The request going to the endpoint https://api.example.com/v1/api/ still sends the Authorization header the same way it did previously ("Authorization": "Bearer CMORsM63LxIO...").

@Sequence Example of Passing access_token as a Variable

Let's say there is an @sequence that sends the_access_token but does not provide the token type Bearer in the string.

Note: Refer to the @sequence documentation to understand how this sequence passes variables between queries.

You do not need to understand @sequence in full detail to know how StepZen uses the access_token to support Authorization headers in this example.

type Auth {
    access_token: String!
    token_type: String!
    expires_in: String!
}

type Query {
    id: String 
}

type Query {
    get_auth: Auth
        @rest(
            method: POST
            contenttype: "application/x-www-form-urlencoded"
            endpoint: "https://api.example.com/v1/api?username={{.Get \"username\" }}&password={{.Get \"password\" }}"
            configuration: "configs"
        )
    my_query(access_token: String): Query
        @rest (
            endpoint: "https://api.example.com/v1/api/"
            headers: [{ name: "Authorization", value: "Bearer $access_token" }]
        )
    """
    returns a query with the new access_token
    """
    query_with_key: Query
        @sequence(
            steps: [
                { query: "get_auth" }
                { query: "my_query" }
            ]
        )
}

type Auth has the field access_token, and in the query_with_key @sequence, the get_auth query passes the access_token to the my_query query.

{
    "token_type": "bearer",
    "refresh_token": "12314-3ee9-4a6b-bc87-134254332",
    "access_token": "CMORsM63LxIO_4eBAEBAgAAMAEAAAAYY_MDnCSCXsaQLKM_AFzIUdnIEl9qo7Cwj2t1Z_rNAec5zYls6LgB_b8f_BwyE_wf8_-D_fc4sAAAAYAYY9DwfIBgcgA_gwx8GGQAAOIUnAADgAOBCFBZjpguluSl9IBk0ni7_U1o-pPgjSgNuYTFSAFoA",
    "expires_in": 21600
}

As shown above, access_token generated by the first step (using get_auth), does not have Bearer preceding the token generated, so my_query must be written with headers: [{ name: "Authorization", value: "Bearer $access_token" }]. StepZen combines the variable access_token being passed in the first step with Bearer added in the schema to properly execute the Authorization header.

my_query(access_token: String): Query
        @rest (
            endpoint: "https://api.example.com/v1/api/"
            headers: [{ name: "Authorization", value: "Bearer $access_token" }]
        )