Skip to content

Latest commit

 

History

History
425 lines (314 loc) · 11.7 KB

TYK_GATEWAY_APPROOV_PYTHON_PLUGIN_EXAMPLE.md

File metadata and controls

425 lines (314 loc) · 11.7 KB

Tyk Gateway - Approov Python Plugin Example

Approov is an API security solution used to verify that requests received by your backend services originate from trusted versions of your mobile apps, and here you can find a full working example for the Tyk API Gateway that is the base for the Approov quickstart.

For more information about how Approov works and why you should use it you can read the Approov Overview at the root of this repo.

Docker Stack

The docker stack provided via the docker-compose.yml file in this repo is used for development proposes and if you are familiar with docker then feel free to use it to follow the quickstart before you try it for real in your project.

For easier use of the docker stack we will use the ./tyk bash script to issue the necessary docker-compose commands.

Setup Env File

Do not forget to properly setup the .env file at the root of this repo before you start the docker stack.

cp .env.example .env

Edit rhe .env file and add a dummy secret:

APPROOV_BASE64_SECRET=h+CX0tOzdAAR9l15bWAqvq7w9olk66daIH+Xk+IAHhVVHszjDzeGobzNnqyRze3lw/WVyWrc2gZfh3XXfBOmww==

This dummy secret was used to sign the valid Approov tokens in the tests that you can run with ./tyk test approov-token.

Build the Docker Stack

The docker stack is composed by the Tyk API Gateway version 4.1 and Redis version 5.0.

./tyk build

The HttpBin API Example

We will create a proxy for httpbin.org where all the API endpoints require a valid and not expired Approov token.

We will use a bash script helper to simplify the usage, while at same time we provide the cURL command being executed by it. You can always see the exact cURL command being executed via the bash script by invoking it in debug mode bash -x ./tyk command.

Creating the Python Plugin Bundle

The Python plugin will run as a Tyk Middleware that needs to be provided has a bundle that is loaded when the Tyk API Gateway it's started, therefore we need to build it before everything else.

./tyk setup python-build-bundle

Start the Tyk Docker Stack

Redis takes sometime to be ready to be used by the Tyk API Gateway, therefore the script will pause for 15 seconds before it returns to the terminal.

./tyk stack up gateway

Tail the Logs

You can omit the tyk-gateway service to follow the logs of all services declared in the docker-compose.yml file.

./tyk logs --follow tyk-gateway

Creating the Tyk Security Policy for Approov

./tyk setup python-plugin-security-policy

or

curl http://localhost:8002/tyk/policies -i -s -H 'x-tyk-authorization: ___YOUR_SUPER_SECRET_HERE___' -H 'Content-Type: application/json' -X POST -d '
      {
        "id": "approov.python",
        "access_rights": {
          "httpbin.org.python": {
            "allowed_urls": [],
            "api_id": "httpbin.org.python",
            "api_name": "HttpBin Python Plugin",
            "versions": [
                "Default"
            ]
          }
        },
        "org_id": "1",
        "active": true,
        "name": "Approov Python Plugin",
        "rate": 0,
        "per": 1,
        "quota_max": -1,
        "state": "active",
        "tags": ["Approov"]
      }'

The output:

HTTP/1.1 200 OK
Content-Type: application/json
Date: Thu, 08 Sep 2022 18:26:25 GMT
Content-Length: 56

{"key":"approov.python","status":"ok","action":"added"}

The Tyk security policy for Approov doesn't require rate limiting or quota usage, because the Approov token check guarantees with a very high degree of confidence that incoming requests are from what the Tyk API Gateway expects, a genuine and unmodified instance of your mobile app, not one that is under attack or that has been tampered with. Bots will not succeed on accessing the API because they are not able to provide an Approov token, and fake tokens will fail the signature check.

Creating the HttpBin API

./tyk setup python-plugin-api

or

ccurl http://localhost:8002/tyk/apis -i -s -H 'x-tyk-authorization: ___YOUR_SUPER_SECRET_HERE___' -H 'Content-Type: application/json' -X POST -d '{
      "api_id": "httpbin.org.python",
      "slug": "httpbin",
      "name": "HttpBin Python Plugin",
      "org_id": "1",
      "auth": {
        "auth_header_name": "Api-Key"
      },
      "definition": {
        "location": "header",
        "key": "x-api-version"
      },
      "version_data": {
        "not_versioned": true,
        "versions": {
          "Default": {
            "name": "Default",
            "use_extended_paths": true
          }
        }
      },
      "proxy": {
        "listen_path": "/",
        "target_url": "https://httpbin.org",
        "strip_listen_path": true
      },
      "active": true,
      "enable_jwt": false,
      "use_keyless": false,
      "custom_middleware_bundle": "bundle.zip"
    }'

The output:

HTTP/1.1 200 OK
Content-Type: application/json
Date: Wed, 31 Aug 2022 17:52:02 GMT
Content-Length: 53

{"key":"httpbin.org","status":"ok","action":"added"}

The keys being modified in the API definition are the keys jwt_* and the key auth_header_name.

Creating the HttpBin API Key

./tyk setup python-plugin-api-key

or

curl http://localhost:8002/tyk/keys/create -i -s -H 'x-tyk-authorization: ___YOUR_SUPER_SECRET_HERE___' -H 'Content-Type: application/json' -X POST -d '{
      "allowance": 1000,
      "rate": 1000,
      "per": 1,
      "expires": -1,
      "quota_max": -1,
      "org_id": "1",
      "quota_renews": 1449051461,
      "quota_remaining": -1,
      "quota_renewal_rate": 60,
      "access_rights": {
        "httpbin.org.python": {
          "api_id": "httpbin.org.python",
          "api_name": "HttpBin Python Plugin",
          "versions": ["Default"]
        }
      },
      "meta_data": {},
      "apply_policy_id": "approov.python"
    }'

The output:

HTTP/1.1 200 OK
Content-Type: application/json
Date: Thu, 08 Sep 2022 18:21:22 GMT
Content-Length: 97

{"key":"1759a7bdfbeec418ca500eb776cb126da","status":"ok","action":"added","key_hash":"03de5816"}

The API key (in this case the string 1759a7bdfbeec418ca500eb776cb126da) is automatically added to the .env file in order to later be used when running the tests with ./tyk test approov-token.

Reload the Tyk API Gateway

For the changes to take effect you need to reload or restart your Tyk API Gateway:

./tyk stack reload

or

curl -i -H 'x-tyk-authorization: ___YOUR_TYK_SUPER_SECRET_HERE___' -s http://localhost:8002/tyk/reload/group
HTTP/1.1 200 OK
Content-Type: application/json
Date: Thu, 08 Sep 2022 18:37:00 GMT
Content-Length: 29

{"status":"ok","message":""}

Now that we have an API protected with Approov it's time to test it, which we will do in the next section.

Testing the Approov Integration

Any incoming API request requires a correctly signed and not expired Approov token, thus we will test several scenarios to ensure that the Approov protection works as expected.

The Tyk API Gateway will only forward the API request to the API endpoint https://httpbin.org/uuid when the Approov token passes the validation, otherwise the API request will be denied.

A valid Approov Token

The Approov token is correctly signed and it's not expired.

./tyk test approov-token valid

or

curl http://localhost:8002/uuid \
  -i \
  -H 'Content-Type: application/json' \
  -H 'Api-Key: 18e64cd239ba847a0a6de4925b6389cfa' \
  -H 'Approov-Token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImtpZCI6IlJFUExBQ0VfV0lUSF9ZT1VSX09SR0FOSVpBVElPTl9JRDg2OTZkYmQ4MDYxZjRiNTM5MDExYWU2OGI0ZmZjNzllIn0.eyJpc3MiOiJhcHByb292LmlvIiwicG9sIjoiaHR0cGJpbi5vcmciLCJleHAiOjQ3MDg2ODMyMDUuODkxOTEyfQ.u-rlLdZgaYUjUpU_wWi7nzeMgae_IfcT7asu22ptXn0'

The output:

HTTP/1.1 200 OK
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: *
Content-Length: 53
Content-Type: application/json
Date: Wed, 31 Aug 2022 18:34:09 GMT
Server: gunicorn/19.9.0
X-Ratelimit-Limit: -1
X-Ratelimit-Remaining: 0
X-Ratelimit-Reset: 0

{
  "uuid": "afaaeb50-8f15-44cd-b1e2-1a1326bbfede"
}

Approov Token with Invalid Signature

The Approov token provided in the header of the request was signed with a secret not known by the Tyk API Gateway to signal that it cannot trust in the incoming API request.

./tyk test approov-token invalid-signature

or

curl http://localhost:8002/uuid \
  -i \
  -H 'Content-Type: application/json' \
  -H 'Approov-Token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImtpZCI6IlJFUExBQ0VfV0lUSF9ZT1VSX09SR0FOSVpBVElPTl9JRDg2OTZkYmQ4MDYxZjRiNTM5MDExYWU2OGI0ZmZjNzllIn0.eyJpc3MiOiJhcHByb292LmlvIiwicG9sIjoiaHR0cGJpbi5vcmciLCJleHAiOjQ3MDg2ODMyMDUuODkxOTEyfQ.u-rlLdZgaYUjUpU_wWi7nasMgae_IfcT7asu22ptXn0'

The output:

HTTP/1.1 401 Unauthorized
Content-Type: application/json
X-Generator: tyk.io
Date: Thu, 08 Sep 2022 19:19:50 GMT
Content-Length: 31

{
    "error": "Unauthorized"
}

Approov Token Expired

The Approov token provided in the header of the request was correctly signed with the same secret known by the Tyk API Gateway, but the exp claim is in the past, therefore the token it's expired and the incoming API request cannot be served.

./tyk test approov-token expired

or

curl http://localhost:8002/uuid \
  -i \
  -H 'Content-Type: application/json' \
  -H 'Approov-Token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImtpZCI6IlJFUExBQ0VfV0lUSF9ZT1VSX09SR0FOSVpBVElPTl9JRDg2OTZkYmQ4MDYxZjRiNTM5MDExYWU2OGI0ZmZjNzllIn0.eyJpc3MiOiJhcHByb292LmlvIiwicG9sIjoiaHR0cGJpbi5vcmciLCJleHAiOjE2NjE1MzAxMjB9.bdl_U893ahMEV5bEp7mPAIkRr53qVA0iuZs0LqvSIho'

The output:

HTTP/1.1 401 Unauthorized
Content-Type: application/json
X-Generator: tyk.io
Date: Thu, 08 Sep 2022 19:21:42 GMT
Content-Length: 31

{
    "error": "Unauthorized"
}

Approov Token Missing

The Approov token isn't present in the headers of the request therefore the incoming API request cannot be served.

./tyk test approov-token missing

or

curl http://localhost:8002/uuid \
  -i \
  -H 'Content-Type: application/json'

The output:

HTTP/1.1 401 Unauthorized
Content-Type: application/json
X-Generator: tyk.io
Date: Thu, 08 Sep 2022 19:23:57 GMT
Content-Length: 31

{
    "error": "Unauthorized"
}

Approov Token Empty

The Approov token in the headers of the request is empty therefore the incoming API request cannot be served.

./tyk test approov-token empty

or

curl http://localhost:8002/uuid \
  -i \
  -H 'Content-Type: application/json' \
  -H 'Approov-Token: '

The output:

HTTP/1.1 401 Unauthorized
Content-Type: application/json
X-Generator: tyk.io
Date: Thu, 08 Sep 2022 19:25:05 GMT
Content-Length: 31

{
    "error": "Unauthorized"
}

Issues

If you find any issue while following our instructions then just report it here, with the steps to reproduce it, and we will sort it out and/or guide you to the correct path.

Useful Links

If you wish to explore the Approov solution in more depth, then why not try one of the following links as a jumping off point: