Simple file based access control with API Keys
The simplest way to secure an API with keys is the file based setup described in this document. Access control based on API keys is a subset of the API Management features of Membrane Service Proxy. For a full blown API Management solution with developer and user dashboard please follow to the API Management Github page.
A file that is loaded on startup specifies policies and API keys. The file can be edited manually or e.g. you could generate it out of your users database.
Example: File based Access Control with API Keys using Membrane
Membrane comes with a preconfigured simple API keys example that is ready to run. In this example we will send requests to a service with and without an API key. Go to the $MEMBRANE_HOME/examples/api-management/simple-file-based folder. See and follow the steps in the README.txt.
Example details
This example consists of 2 parts. At first you will have a look at the policy file and see how to configure policies and create API keys that use these policies. The second part takes a look at the Membrane configuration on how to set up API Management with Membrane.
The Policy File
Have a look at the api.yaml in the example folder.
policies: - policy: id: "TrialAppX" serviceProxy: - "Names API" - policy: id: "Customer" rateLimit: requests: '1000' interval: '3600' serviceProxy: - "Web Page" - "Names API" keys: - key: "abcdefg" expires: "2020-01-01T12:00:00" policies: - "TrialAppX" - "Customer" - key: "gfedcba" policies: - "TrialAppX"
The configuration is defined in YAML and split in policies and keys.
The first part of the YAML configuration defines a list of policies. A policy defines rules for a list of services. The policy object has several attributes you can define.
Attribute | Description | Default | Type |
---|---|---|---|
id | The name of the policy | --- | String |
rateLimit (optional) |
|
1000 requests per 3600 seconds | Object |
quota (optional) |
|
1mb per 86400 seconds (1 day) | Object |
unauthenticated (optional) | A policy can be unauthenticated. It then also works when no API key is specified (but doesn't work with wrong API keys) | false | Boolean |
serviceProxy | A list of serviceProxies to which this policy applies | --- | List of Strings |
Note: ratelimit and quota are objects
To use the default values just leave out the attributes you want defaults for.
A service can be covered by multiple policies. The API key decides what policy should be in effect.
The second part of the YAML configuration defines a list of keys. A key defines a list of policies that authorizes the client to use some services. The key object has several attributes you can define.
Attribute | Description | Type | |
---|---|---|---|
key | The API key | --- | String |
expiration (optional) | The expiration date in ISO 8601 format with trailing "Z" | never expire | String |
policies | The list of policies this API key is usable with | --- | List of Strings |
To use the default values just leave out the attributes you want defaults for.
API keys can have multiple policies and those policies can have overlapping services. When such a service is used all rules apply simultaneously, e.g. 2 policies define the "Names API" service and both have a rateLimit and quota then both rateLimits and quotas are in effect.
Membrane Configuration
Have a look at the proxies.xml in the example folder.
<!-- <simpleApiConfig> - this bean is implicitly here when no other api configurator is specified. In this example we use the file base api management--> <router> <!-- To use API Management one has to explicitly specifiy the transport chain of Membrane--> <transport> <ruleMatching /> <exchangeStore /> <dispatching /> <!-- API Management is activated by putting it in the transport chain between dispatching and reverseProxying --> <apiManagement> <!-- API Management currently has 2 interceptors, a rate limiter and quota ( bandwidth limiter ) --> <amRateLimiter/> <amQuota/> </apiManagement> <reverseProxying /> <userFeature /> <httpClient /> </transport> <!-- API Management works with service proxy names. Thus the name attribute needs to be defined --> <serviceProxy port="8080" name="Web Page"> <target host="www.thomas-bayer.com" port="80"/> </serviceProxy> <serviceProxy port="8081" name="Names API"> <path>/restnames</path> <target host="www.thomas-bayer.com" port="80"/> </serviceProxy> <!-- Admin console can always be accessed without an API key so in production environments they have to be secured, e.g. by basic authentication --> <serviceProxy port="9000" name="AdminConsole"> <adminConsole/> </serviceProxy> </router>
In this example we use the file based API Management. This works as default when using API Management. This behaviour can be changed by specifying another bean before the router element, e.g. <etcdRegistryApiConfig>. You can also explicitly define the file based approach by using the <simpleApiConfig> bean.
API Management is part of Membranes transport chain. Here you can add the optional rate limit and quota interceptors.
By default the HeaderKeyRetriever is used that takes the API key from the http authorization header field.
There is also the possibility to collect statistics about requests processed by API Management. For this to work you can add the <amStatisticsCollector> as last interceptor in the apiManagement element. These statistics are then collected in an elastic search instance that you can specify through the attributes of the amStatisticsCollector element.
Attribute | Description |
---|---|
host | Host of the elastic search instance |
clientId | Client id for basic authentication |
clientSecret | Client secret for basic authentication |
Services, for API Management, are defined by specifying the name attribute of serviceProxies. These names are the ones used in the policy file.
Admin consoles are a special case of service. They are always reachable through API Management even when not using an API key. They need to be protected from external access, e.g. by using the basic authentication interceptor of Membrane.
Help needed?
Do you need any help for this example? Then contact us using the Membrane Google Group or send an email to membrane@predic8.com.