Prerequisites
-
Docker version required is 1.20 or subsequent
-
Docker-compose version required is 1.29 or subsequent
-
Access to an Cloudentity tenant
Integrate Standalone Authorizer with Internal API GWs
Create Standalone Authorizer
-
In the workspace of your choice, go to Enforcement > Authorizers.
-
Select CREATE GATEWAY.
-
Select Standalone and provide a display name and a description for your authorizer.
-
Optionally, enable the Create and bind services automatically check box.
Tip
When enabled, all services protected by your Standalone Authorizer instance are discovered and added to the Cloudentity service list automatically when the Standalone Authorizer is connected to Cloudentity. Otherwise, you need to add them manually.
-
On the Gateway Management Quick Start tab, click Download Package.
The
standalone-authorizer.zip
file contains three files:-
.env
that contain OAuth client credentials for your authorizerClient Credentials
In Cloudentity a gateway/authorizer objects consists of two objects: an actual gateway and a client application created for this gateway/authorizer in the System workspace for your tenant. Credentials of this client application are used in client credentials OAuth grant flow call to the Cloudentity’s token endpoint to authenticate your client application.
-
credentials.txt
Docker-login credentials -
docker-compose.yml
responsible for providing your authorizer’s deployment configuration.TLS Certificates
If your Cloudentity service is using a self-signed certificate, or the certificate does not match the hostname that you are using to connect to Cloudentity, you can disable the TLS check by adding the
HTTP_CLIENT_INSECURE_SKIP_VERIFY
environment variable set totrue
to yourdocker-compose.yml
file. See example:environment: - HTTP_CLIENT_INSECURE_SKIP_VERIFY=true
-
-
In your terminal, navigate to the directory where you have unzipped the Standalone Authorizer.
-
Use the following commands to start the authorizer in a Docker container:
cat credentials.txt | docker login docker.cloudentity.io --username acp --password-stdin docker-compose up
After you run the docker-compose up
, you should see output similar to the following:
standalone-authorizer | {"commit":"a1463ff","level":"info","msg":"starting standalone authorizer","time":"2021-10-25T12:10:37Z","version":"latest"}
standalone-authorizer | {"level":"info","msg":"standalone-authorizer listening on https://localhost:9004","time":"2021-10-25T12:10:38Z"}
standalone-authorizer | {"level":"info","msg":"Starting authorizer reload...","time":"2021-10-25T12:10:48Z"}
standalone-authorizer | {"level":"info","msg":"Authorization configuration reloaded (170.685855ms)","time":"2021-10-25T12:10:48Z"}
It means that your Standalone Authorizer instance is successfully running and that it started to load authorization configuration. The authorizer is ready to discover APIs.
Create API Groups
To enable the Standalone Authorizer to discover your APIs, you need to prepare your API definition in a form of a JSON file.
The JSON specification is defined as follows:
Below, you can see an example which defines one endpoint at the /anything
path that supports five
HTTP methods:
Import APIs to Authorizer
Once you have configured the Standalone Authorizer container and prepared a specification for your APIs, you need to import them to your Standalone Authorizer’s instance. When the APIs are imported, you are able to apply access control to them by assigning authorization policies.
Send a PUT
request to the /apis
endpoint of your Standalone Authorizer. See example below:
curl -sSLk -D - -X PUT https://localhost:9004/apis \
--header "content-type:application/json" \
--data @{YOUR_JSON_WITH_API_GROUPS_SPECIFICATION}
Remember to change the {YOUR_JSON_WITH_API_GROUPS_SPECIFICATION}
variable to the name of the
file where you have provided your API specification.
Result
On success, the Standalone Authorizer responds with
HTTP/1.1 204 No Content
. You can also observe the results of this operation in the Cloudentity’s Gateway Management page, by selecting the APIs tab and clicking on your service name.
You can also confirm your API configuration by querying the Standalone Authorizer’s /apis
endpoint:
curl -sSLk -X GET https://localhost:9004/apis \
--header "Accept:application/json"
As the result of this request, you get a list of all APIs imported to your Standalone Authorizer instance.
Note
If the APIs don’t show up under APIs, go to Authorizers and APIs, then click the dots on the right side of the service to unbind and bind the service again.
Apply Authorization Policies
The Standalone Authorizer makes it possible to validate your authorization policies assigned to your
imported APIs by making a POST
request to the /request/validate
endpoint of the Standalone
Authorizer.
If you were to make such a request now, you would see that your APIs do not have any authorization policy assigned at the moment. See example below.
curl -sSLk -D - -X POST https://localhost:9004/request/validate \
--header "content-type:application/json" \
--data '{"api_group":"my-service","method":"GET","path":"/anything"}'
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Date: Wed, 27 Oct 2021 08:45:42 GMT
Content-Length: 0
As you can see, the GET
request results with the HTTP/1.1 200 OK
status. It means that there is
no access control applied for this API at the moment.
Let’s protect your APIs.
-
In the workspace where you have your APIs discovered, go to Enforcement > APIs.
-
Apply an authorization policy to one of your APIs.
-
For the API you wish to set a policy, select the Unrestricted / Protected button.
-
Choose a policy from the list or add a new one.
You can, for example, set the Block API policy for testing purposes.
-
Select Save.
-
-
Make a
POST
request to the/request/validate
endpoint for your Standalone Authorizer. See example below.curl -sSLk -D - -X POST https://localhost:9004/request/validate \ --header "content-type:application/json" \ --data '{"api_group":"my-service","method":"GET","path":"/anything"}'
Learn More
Learn more about the
/request/validate
endpoint’s schema by reading the its schema section.Set the
api_group
parameter to the name of the service you have imported to Cloudentity. Provide the samemethod
andpath
parameter to which you have applied your authorization policy.Result
If you applied the Block API policy to the
GET
method for the/anything
endpoint, the request now returns theHTTP/1.1 403 Access Forbidden
status with the following response body:{"status_code":403,"error":"request in not authorized","details":null}
Tip
To test your API access control, you can also use the
NIST-AAL-1
authorization policy. The policy enforces access protection with an additional requirement: the HTTP request must contain an access token. To test how it works, apply the policy to the endpoint of your choice and make the request with theauthorization
header as in the example below:curl -sSLk -D - -X POST https://localhost:9004/request/validate \ --header "content-type:application/json" \ --data '{"api_group":"new-service","method":"DELETE","path":"/anything","headers":{"authorization":["Bearer '$AT'"]}'
The
$AT
environment variable stands for your access token. To learn more on how to authenticate your client applications, read the Getting started with Cloudentity REST API documentation.
Apply Specific Authorization Policy
The Standalone Authorizer makes it possible to validate access to your imported APIs against a
specific policy,
by making a POST
request to the /policy/validate
endpoint of the Standalone Authorizer.
The policy does not need to be assigned to the API, because it is specified in the authorization
request to the /policy/validate
endpoint of the Standalone Authorizer. Your POST request to /policy/validate
must specify the
policy ID that you wish to apply,
via the policy
key of the JSON request. In this example, we specify the authorization policy
named NIST-AAL-1 API
:
curl -sSLk -D - -X POST https://localhost:9004/policy/validate \
--header "content-type:application/json" \
--data '{"policy":"nist-aal-1_system_api","method":"GET","path":"/anything"}'
The example above results in HTTP status 403, because the policy NIST-AAL-1
requires the
requesting client to present an access token. In the example below, the client’s request
specifies the token
that is be tested by the policy:
curl -sSLk -D - -X POST https://localhost:9004/policy/validate \
--header "content-type:application/json" \
--data '{"token":"'$AT'","policy":"nist-aal-1_system_api","method":"GET","path":"/anything"}'
The $AT
environment variable stands for your access token. To learn more on how to authenticate
your client applications, read the Getting started with Cloudentity REST API
documentation.
Schemas
/request/validate Schema
To validate an HTTP request to a defined Gateway API, POST the request to the Standalone
Authorizer’s /request/validate
endpoint:
curl -sSLk -D - -X POST https://localhost:9004/request/validate \
--header "content-type:application/json" \
--data @request_body.json
The JSON requst body represents the HTTP request that you wish to authorize:
/policy/validate Schema
To validate an HTTP request to a defined Gateway API using a specified authorization policy,
POST the request to the Standalone Authorizer’s /policy/validate
endpoint:
curl -sSLk -D - -X POST https://localhost:9004/policy/validate \
--header "content-type:application/json" \
--data @request_body.json
The JSON request body represents the HTTP request that you wish to authorize:
Note that policies must be specified by the policy ID, rather than the policy name.
Some policies require an access token to be specified in the token
field.
Configure Standalone Authorizer
The Standalone Authorizer can be configured with a file in YAML format, or via environment variables. To generate a template configuration file that is populated with default settings, you can use a Docker image and pipe the output to a configuration file:
docker run --rm docker.cloudentity.io/standalone-authorizer reference > reference_config.yaml
You can use the configuration reference as a basis for your customization. You can omit settings for which the default configuration is satisfactory, specifying only the required values, which are the client ID, client secret, and issuer URL parameters.
ACP_CLIENT_ID: {your_client_id}
ACP_CLIENT_SECRET: {your_client_secret}
ACP_ISSUER_URL: https://{tid}.us.authz.stage.cloudentity.io/{tid}/system
Environment variables can also be used to set these configuration values. The environment variable’s name
are the uppercase version of the YAML name. For example, in the docker-compose.yml
that you downloaded,
you can set the ACP_CLIENT_ID
via the environment variable ACP_CLIENT_ID
:
environment:
- ACP_CLIENT_ID=${CLIENT_ID}
- ACP_CLIENT_SECRET=${CLIENT_SECRET}
- ACP_ISSUER_URL=${ISSUER_URL}
- HTTP_SERVER_PORT=9004
Tip
Note that nested YAML settings can be accessed by joining uppercased names with underscores, as shown in the example above, where the
HTTP_SERVER_PORT=9004
parameter is set.
To run the standalone authorizer with a configuration file, use the --config
option to specify
the YAML file with your configuration.
For example, assuming that you have created a standalone_config.yaml
file in your current
directory your docker run
command would look like the following:
docker run --rm --volume `pwd`:/config:ro docker.cloudentity.io/standalone-authorizer --config /config/standalone_config.yaml
Configuration Reference
# acp
acp:
reload_interval: 1m0s # reload interval
reload_timeout: 30s # reload configuration timeout
issuer_url: https://localhost:8443/sample/system # issuer url
client_id: bqesdrc4m4co2s81mpu0 # client id
client_secret: LH6mAb6PNljvjYMIF-A5RP2bElA5a5bnQah8sG0fsLA # client secret
tenant_id: "" # tenant id
server_id: "" # server id
# http client
http_client:
timeout: 10s # http client timeout
retry_wait_min: 0s # minimum time to wait between retries
retry_wait_max: 0s # maximum time to wait between retries
retry_max: 0 # maximum number of retries
root_ca: "" # root ca that this client should trust (defaults to system root ca)
insecure_skip_verify: false # disable cert verification
disable_follow_redirects: false # disable follow redirects
disable_retry: true # disable retry
# metrics
metrics:
enabled: false # enable metrics endpoint
port: 9000 # metrics endpoint port
# analytics
analytics:
enabled: true # when enabled, events are sent to audit log
# event format
event_format:
include_policy_output: false # when enabled, policy evaluation output is sent to audit log
# sampling
sampling:
probability: 1 # Probability of an event to be published (0.0-1.0)
batch_inverval: 1s # Max duration to wait for a batch to publish
batch_limit: 100 # Max number of events in a batch
limit: 5 # Max number of batches per second to be published
timeout: 5s # Timeout for a single batch to send
workers: 8 # Number of sending workers
# cache
cache:
ttl: 10s # ttl
max_size: 100 # max size
# logging config
logging:
level: info # log level severity
# token echange config
token_exchange:
enabled: false # enable token exchange
# cache
cache:
ttl: 1m0s # ttl
max_size: 1000 # max size
# inject config (supported only for istio authorizer)
inject:
mode: "" # Defines what token should be sent to the target service when token is exchanged
# headers config
headers:
exchanged_token: "" # Defines the name of the header that contains an exchanged token.
original_token: "" # Defines the name of the header that contains an original token.
strip_bearer: false # Allows to strip the bearer prefix in headers
# enforcement config
enforcement:
allow_unknown: false # allow requests with no matching rule
# http client
http_server:
port: 9004 # http port
dangerous_disable_tls: false # diables TLS
# certificate configuration
certificate:
password: "" # key passphrase
cert_path: "" # path to the certificate PEM file
key_path: "" # path to the key PEM file
cert: "" # base64 encoded cert PEM
key: "" # base64 encoded key PEM
generated_key_type: ecdsa # type for generated key if cert and key are not provided (rsa or ecda)
client_auth_type: 0 # client auth type