Skip to content
This repository was archived by the owner on Feb 12, 2022. It is now read-only.

Commit b487cf1

Browse files
authored
Automate Admin API access (#22)
1 parent 4963885 commit b487cf1

File tree

5 files changed

+156
-58
lines changed

5 files changed

+156
-58
lines changed

ADMIN.md

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
Admin Console for Kong on Heroku
2+
================================
3+
Console access is primarily useful for performing `kong` CLI commands against the deployed app. Most administrative features do not require console access and instead are available through the [Kong Admin API](README.md#user-content-admin-api).
4+
5+
### Admin console
6+
7+
Use Kong CLI and the Admin API in a [one-off dyno](https://devcenter.heroku.com/articles/one-off-dynos):
8+
9+
✏️ *Replace `$APP_NAME` with the Heroku app name.*
10+
11+
```bash
12+
heroku run bash --app $APP_NAME
13+
14+
# Run Kong in the background of the one-off dyno:
15+
~ $ bin/background-start
16+
17+
# Then, use `curl` to issue Admin API commands
18+
# and `jq` to format the output:
19+
# (Note: the `$KONG_ADMIN_LISTEN` variable is already defined)
20+
~ $ curl http://$KONG_ADMIN_LISTEN | jq .
21+
22+
# Example CLI commands:
23+
# (Note: some commands require the config file and others the prefix)
24+
# (Note: the `$KONG_CONF` variable is already defined)
25+
~ $ kong migrations list -c $KONG_CONF
26+
~ $ kong health -p /app/.heroku
27+
```
28+
29+
### Proxy & protect the Admin API
30+
Kong's Admin API has no built-in authentication. Its exposure must be limited to a restricted, private network. For Kong on Heroku, the Admin API listens privately on `localhost:8001`.
31+
32+
To make Kong Admin accessible from other locations, let's setup Kong itself to proxy its Admin API with key authentication, HTTPS-enforcement, and request rate & size limiting.
33+
34+
⚠️ **This [Admin API proxy is generated automatically](README.md#user-content-admin-api) during the initial deployment's release**, if the `KONG_HEROKU_ADMIN_KEY` config var is set, such as when [using the automated app setup](README.md#user-content-deploy).
35+
36+
From the [admin console](#user-content-admin-console):
37+
```bash
38+
# Create the authenticated `/kong-admin` API, targeting the localhost port:
39+
curl http://localhost:8001/services/ -i -X POST \
40+
--data 'name=kong-admin' \
41+
--data 'protocol=http' \
42+
--data 'port=8001' \
43+
--data 'host=localhost'
44+
# Note the Service ID returned in previous response, use it in place of `$SERVICE_ID`.
45+
curl http://localhost:8001/plugins/ -i -X POST \
46+
--data 'name=request-size-limiting' \
47+
--data "config.allowed_payload_size=8" \
48+
--data "service_id=$SERVICE_ID"
49+
curl http://localhost:8001/plugins/ -i -X POST \
50+
--data 'name=rate-limiting' \
51+
--data "config.minute=5" \
52+
--data "service_id=$SERVICE_ID"
53+
curl http://localhost:8001/plugins/ -i -X POST \
54+
--data 'name=key-auth' \
55+
--data "config.hide_credentials=true" \
56+
--data "service_id=$SERVICE_ID"
57+
curl http://localhost:8001/plugins/ -i -X POST \
58+
--data 'name=acl' \
59+
--data "config.whitelist=kong-admin" \
60+
--data "service_id=$SERVICE_ID"
61+
curl http://localhost:8001/routes/ -i -X POST \
62+
--data 'paths[]=/kong-admin' \
63+
--data 'protocols[]=https' \
64+
--data "service.id=$SERVICE_ID"
65+
66+
# Create a consumer with username and authentication credentials:
67+
curl http://localhost:8001/consumers/ -i -X POST \
68+
--data 'username=heroku-admin'
69+
curl http://localhost:8001/consumers/heroku-admin/acls -i -X POST \
70+
--data 'group=kong-admin'
71+
curl http://localhost:8001/consumers/heroku-admin/key-auth -i -X POST -d ''
72+
# …this response contains the `"key"`, use it for `$ADMIN_KEY` below.
73+
```
74+
75+
Now, access Kong's Admin API via the protected, public-facing proxy:
76+
77+
✏️ *Replace variables such as `$APP_NAME` with values for your unique deployment.*
78+
79+
```bash
80+
# Set the request header:
81+
curl -H "apikey: $ADMIN_KEY" https://$APP_NAME.herokuapp.com/kong-admin/status
82+
# or use query params:
83+
curl https://$APP_NAME.herokuapp.com/kong-admin/status?apikey=$ADMIN_KEY
84+
```

README.md

Lines changed: 44 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ Deploy [Kong 0.14 Community Edition](https://konghq.com/kong-community-edition/)
1313
* [Deploy](#user-content-deploy)
1414
* [Connect local to Heroku app](#user-content-connect-local-to-heroku-app)
1515
* [Admin console](#user-content-admin-console)
16+
* [Admin API](#user-content-admin-api)
17+
* [The API Key](#user-content-admin-api-key)
18+
* [Accessing](#user-content-accessing-the-external-admin-api)
19+
* [Disabling](#user-content-disabling-the-external-admin-api)
1620
* [Proxy & protect the Admin API](#user-content-proxy--protect-the-admin-api)
1721
* [Upgrade guide](#user-content-upgrade-guide)
1822
* [Customization](#user-content-customization)
@@ -55,7 +59,7 @@ Use the deploy button to create a Kong app in your Heroku account:
5559

5660
### Connect local to Heroku app
5761

58-
To use Admin console on a freshly-deployed app, clone and connect this repo (or your own fork) to the Heroku app:
62+
To make changes to the Kong app's source, clone and connect this repo (or your own fork) to the Heroku app:
5963

6064
```bash
6165
git clone https://github.com/heroku/heroku-kong.git
@@ -68,77 +72,60 @@ heroku info
6872

6973
### Admin console
7074

71-
Use Kong CLI and the Admin API in a [one-off dyno](https://devcenter.heroku.com/articles/one-off-dynos):
75+
To gain local console access to Kong deployed on Heroku, see [ADMIN](ADMIN.md).
7276

73-
```bash
74-
heroku run bash
77+
Console access is primarily useful for performing `kong` CLI commands against the deployed app. Most administrative features do not require console access and instead are available through the Kong Admin API.
78+
79+
### Admin API
80+
81+
When this app is deployed to Heroku, it automatically provisions a protected, external-facing proxy to [Kong's Admin API](https://docs.konghq.com/0.14.x/admin-api/), secured by the `KONG_HEROKU_ADMIN_KEY` config var.
82+
83+
#### Admin API key
7584

76-
# Run Kong in the background of the one-off dyno:
77-
~ $ bin/background-start
85+
`KONG_HEROKU_ADMIN_KEY` is generated automatically when this app is [deployed using the automated app setup](#user-content-deploy).
7886

79-
# Then, use `curl` to issue Admin API commands
80-
# and `jq` to format the output:
81-
~ $ curl http://$KONG_ADMIN_LISTEN | jq .
87+
You can explicitly set a new admin key value:
8288

83-
# Example CLI commands:
84-
# (note some commands require the config file and others the prefix)
85-
~ $ kong migrations list -c $KONG_CONF
86-
~ $ kong health -p /app/.heroku
89+
```bash
90+
heroku config:set KONG_HEROKU_ADMIN_KEY=xxxxx
91+
git commit --allow-empty -m 'deploy to set new admin key'
92+
git push heroku master
8793
```
8894

89-
### Proxy & protect the Admin API
90-
Kong's Admin API has no built-in authentication. Its exposure must be limited to a restricted, private network. For Kong on Heroku, the Admin API listens privately on `localhost:8001`.
95+
⚠️ **Always set a unique, cryptographically strong key value.** A weak admin key may result in the proxy being compromised and abused by malicious actors.
96+
97+
#### Accessing the external Admin API
98+
99+
Make HTTPS requests using a tool like [`curl`](https://curl.haxx.se) or [Paw.cloud](https://paw.cloud):
91100

92-
To make Kong Admin accessible from other locations, let's setup Kong itself to proxy its Admin API with key authentication, HTTPS-enforcement, and request rate & size limiting.
101+
1. Base URL of the app's [Kong Admin API](https://docs.konghq.com/0.14.x/admin-api/) is `https://$APP_NAME.herokuapp.com/kong-admin`
102+
2. Set the current [admin key](#user-content-admin-api-key) in the `apikey` HTTP header
103+
104+
For example, set the current admin key into a local shell variable:
93105

94-
From the [admin console](#user-content-admin-console):
95106
```bash
96-
# Create the authenticated `/kong-admin` API, targeting the localhost port:
97-
curl http://localhost:8001/services/ -i -X POST \
98-
--data 'name=kong-admin' \
99-
--data 'protocol=http' \
100-
--data 'port=8001' \
101-
--data 'host=localhost'
102-
# Note the Service ID returned in previous response, use it in place of `$SERVICE_ID`.
103-
curl http://localhost:8001/plugins/ -i -X POST \
104-
--data 'name=request-size-limiting' \
105-
--data "config.allowed_payload_size=8" \
106-
--data "service_id=$SERVICE_ID"
107-
curl http://localhost:8001/plugins/ -i -X POST \
108-
--data 'name=rate-limiting' \
109-
--data "config.minute=5" \
110-
--data "service_id=$SERVICE_ID"
111-
curl http://localhost:8001/plugins/ -i -X POST \
112-
--data 'name=key-auth' \
113-
--data "config.hide_credentials=true" \
114-
--data "service_id=$SERVICE_ID"
115-
curl http://localhost:8001/plugins/ -i -X POST \
116-
--data 'name=acl' \
117-
--data "config.whitelist=kong-admin" \
118-
--data "service_id=$SERVICE_ID"
119-
curl http://localhost:8001/routes/ -i -X POST \
120-
--data 'paths[]=/kong-admin' \
121-
--data 'protocols[]=https' \
122-
--data "service.id=$SERVICE_ID"
107+
KONG_HEROKU_ADMIN_KEY=`heroku config:get KONG_HEROKU_ADMIN_KEY`
108+
```
123109

124-
# Create a consumer with username and authentication credentials:
125-
curl http://localhost:8001/consumers/ -i -X POST \
126-
--data 'username=8th-wonder'
127-
curl http://localhost:8001/consumers/8th-wonder/acls -i -X POST \
128-
--data 'group=kong-admin'
129-
curl http://localhost:8001/consumers/8th-wonder/key-auth -i -X POST -d ''
130-
# …this response contains the `"key"`, use it for `$ADMIN_KEY` below.
110+
Now use the following HTTP request style to interact with the [Kong's Admin API](https://docs.konghq.com/0.14.x/admin-api/):
111+
112+
✏️ *Replace the variable `$APP_NAME` with value for your unique deployment.*
113+
114+
```bash
115+
curl -H "apikey: $KONG_HEROKU_ADMIN_KEY" https://$APP_NAME.herokuapp.com/kong-admin/status
131116
```
132117

133-
Now, access Kong's Admin API via the protected, public-facing proxy:
118+
#### Disabling the external Admin API
134119

135-
✏️ *Replace variables such as `$APP_NAME` with values for your unique deployment.*
120+
If you prefer to only use the [console-based Admin API](ADMIN.md), then this externally-facing proxy can be disabled:
136121

137122
```bash
138-
# Set the request header:
139-
curl -H "apikey: $ADMIN_KEY" https://$APP_NAME.herokuapp.com/kong-admin/status
140-
# or use query params:
141-
curl https://$APP_NAME.herokuapp.com/kong-admin/status?apikey=$ADMIN_KEY
123+
curl -H "apikey: $KONG_HEROKU_ADMIN_KEY" https://$APP_NAME.herokuapp.com/kong-admin/services/kong-admin/routes
124+
# For the returned Route's `id`,
125+
curl -H "apikey: $KONG_HEROKU_ADMIN_KEY" -X DELETE https://$APP_NAME.herokuapp.com/kong-admin/routes/$ROUTE_ID
126+
# Now there's no longer admin access!
127+
# Finally, clear out the old admin key value.
128+
heroku config:unset KONG_HEROKU_ADMIN_KEY
142129
```
143130

144131
### Upgrade guide

app.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,11 @@
1717
}],
1818
"addons": [
1919
"heroku-postgresql"
20-
]
20+
],
21+
"env": {
22+
"KONG_HEROKU_ADMIN_KEY": {
23+
"description": "A secret key for accessing Kong's Admin API via public proxy at /kong-admin",
24+
"generator": "secret"
25+
}
26+
}
2127
}

bin/prerelease

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#!/usr/bin/env bash
2+
set -u
3+
4+
# Only run this if Kong's tables have not be initialized.
5+
psql $DATABASE_URL -c "SELECT 1 FROM consumers"
6+
data_exists=$?
7+
8+
if [ ! $data_exists -eq 0 ] && [ -n "$KONG_HEROKU_ADMIN_KEY" ]
9+
then
10+
echo "Loading base Kong config to enable secure proxy to Admin API"
11+
pg_restore --verbose --clean --no-acl --no-owner -d "$DATABASE_URL" $HOME/config/pg-heroku-admin.dump
12+
fi
13+
14+
set -e
15+
16+
if [ -n "$KONG_HEROKU_ADMIN_KEY" ]
17+
then
18+
echo "Setting Admin API key to value of KONG_HEROKU_ADMIN_KEY"
19+
# This `id` matches the "kong-admin" keyauth_credentials record contained in "config/pg-heroku-admin.dump"
20+
psql "$DATABASE_URL" -c "UPDATE keyauth_credentials SET key='$KONG_HEROKU_ADMIN_KEY' WHERE id='ac8af1d3-377a-41ae-9fd5-dbf98c599c5c';"
21+
fi

config/pg-heroku-admin.dump

61.9 KB
Binary file not shown.

0 commit comments

Comments
 (0)