Generic HTTP Authentication

Secretless includes several connectors that provide a convenient way for connecting to services. If you don't see a connector for your target service, rather than writing a new connector, you can use the Generic HTTP Connector to write a Secretless configuration to tell the generic connector how to modify your HTTP requests to enable authentication to your target service.

Overview

The Generic HTTP Connector works by injecting any credential you choose directly into an HTTP header or query parameter. You define the header name or query field and the credential to inject. The Generic HTTP Connector supports a majority of the authentication methods required by most APIs, which helps you save time and minimizes the need to interact directly with the target service's API.

The Generic HTTP Connector enables you to:

  • Create a header with any name. You can populate the header with:

    • Any credential

    • Any combination of credentials and literal strings

    • Any supported transformation of any combination of credentials and fixed strings

  • Add a query parameter to your HTTP request URL and populate the value of the query parameter using any of the methods mentioned above for headers.

  • Add a valid OAuth1 Authorization header to your request.

 

You can also configure the Generic HTTP Connector to concatenate credentials, or even encode them in base64.

Configure a Generic HTTP Connector

Before you configure the Generic HTTP Connector, it is important to understand the authentication scheme used by the target service and the config keys required for your environment. It may be helpful to familiarize yourself with the API documentation for the target service. You'll want to know, for example, if special headers are required for authentication, or if authentication happens using query parameters.

Add the relevant config keys from the table below to the service definition config section in your secretless.yml file. For more information, see Secretless Configuration. Click the links in the following table to learn more about each config key.

Config Keys

Description

headers

The set of Headers to inject into the HTTP request

queryParams

The set of Query parameters to inject into the HTTP request

oauth1

The set of keys used to build the OAuth1 Authorization header for your request

credentialValidations

Constraints that must be applied to the values of any credentials that Secretless retrieves for you

 

Refer to your credentials using the credential name preceded by a .

For example, .username and .password refer to the credentials usernameand password, respectively. At runtime, Secretless replaces these credential references with your real credentials.

Headers

The headers config key provides each header name as a YAML key. The header value is given using a Go text template, defined in the text/template package, to interpolate the values of the Secretless credentials.

Example 1

In the following example, a header name, X-ApiKey is used:

 
version: 2
services:
  my_example_service:
    connector: generic_http
    listenOn: tcp://0.0.0.0:8080
    credentials:
      apikey:
        from: conjur
        get: my-services-api-key
    config:
      credentialValidations:
        apikey: '^[A-Z0-9]+$'
      headers:
        "X-ApiKey": "{{ .apikey }}"
      forceSSL: true
      authenticateURLsMatching:
        - ^http
                        

In this example:

  • my-services-api-key is the fully qualified Conjur ID of the API key.

  • apikey: '^[A-Z0-9]+$' tells Secretless that to be a valid API key, the credential value must consist of only uppercase letters and digits.

  • ^http tells Secretless that this connector should be applied to all requests (any request that includes the string http).

Example 2

In the following example, a basic authentication-conformant Authorization header is added to any HTTP request that Secretless proxies.

 
version: 2
services:
  service_requiring_basic_auth:
    connector: generic_http
    listenOn: tcp://0.0.0.0:8080
    credentials:
      username:
        from: conjur
        get: someuser
      password:
        from: conjur
        get: somepassword
      address:
        from: conjur
        get: address
    config:
      credentialValidations:
        username: '[^:]+'    # username cannot contain a colon
      headers:
        Authorization: "Basic {{ printf \"%s:%s\" .username .password | base64 }}"
      queryParams:
        location: "{{ .address }}"
      forceSSL: true
      authenticateURLsMatching:
        - ^http
                        

Query parameters

The queryParams config key provides key-value pairs that Secretless transforms into a query string. The query string is appended to your existing request URL without replacing any existing query parameters.

Each query parameter is given as a YAML key. The query parameter value is given using a Go text template, defined in the text/template package to interpolate the values of the Secretless credentials. In Example 2 , the query parameter key is location.

Using the Secretless configuration in Example 2 , if the original request URL appears as follows:

 
http://anything.com/foo?fruit=apple

after proxying through Secretless, your request URL would be:

 
http://anything.com/foo?location=valueofaddress&fruit=apple

OAuth1

Add the oauth1 config key to your Secretless configuration if Secretless should add an OAuth1 Authorization header to your request. This is needed if you are connecting to a target service that uses OAuth1 authentication. oauth1 includes four keys whose values are given using a Go text template, defined in the text/template package, to interpolate the values of the Secretless credentials.

Key

Description

consumer_key

A value used by the client to identify itself to the service provider

consumer_secret

A secret used by the client to establish ownership of the consumer key

token

A value used by the client to gain access to the protected resources on behalf of the user, instead of using the client’s service provider credentials

token_secret

A secret used by the client to establish ownership of a given token

 

Declaring an Authorization header in the config section of secretless.yml while a value is included in oauth1, is not supported and causes the following error message to display: authorization header already exists, cannot override header.

For example:

 
version: 2
services:
  oauth1-service:
    connector: generic_http
    listenOn: tcp://0.0.0.0:8080
    credentials:
      consumer_key:
        from: conjur
        get: somekey
      consumer_secret:
        from: conjur
        get: someconsumersecret
      token:
        from: conjur
        get: sometoken
      token_secret:
        from: conjur
        get: sometokensecret
    config:
      oauth1:
        consumer_key: "{{ .consumer_key }}"
        consumer_secret: "{{ .consumer_secret }}"
        token: "{{ .token }}"
        token_secret: "{{ .token_secret }}"
      forceSSL: true
      authenticateURLsMatching:
        - ^http
                        

Credential validations

In credentialValidations, specify constraints that must be applied to the values of any credentials Secretless retrieves for you. Use regular expressions to define validations for the values.

The example below tells us that the expected value of apikey consists solely of uppercase letters and digits.

 
apikey: '^[A-Z0-9]+$'
 

If the rule expressed in credentialValidations is violated at runtime, Secretless logs an appropriate error message.

 

After you've configured the relevant sections of the secretless.yml file, add the configuration information under the config YAML key / in the config section for the service definition.

For further assistance writing generic connector configurations, refer to our library of example configurations.

Limitations

  • Some HTTP APIs require more involved authentication. For example, they might require you to read the HTTP body content and create a hashed signature of it using a secret key. Currently, the Generic HTTP Connector does not support use cases like these, although it may in the future.

  • Secretless supports the functions available in the Go text/template package, and any additional functions that Secretless makes available. Currently, base64 is the only supported function beyond the defaults of the text/template package, however, we plan to add more functions in the future.

To request a function, create an issue or pull request in our GitHub repository.