Skip to content

Commit

Permalink
feat: autogenerate admin api key if not passed (#11080)
Browse files Browse the repository at this point in the history
Signed-off-by: Ashish Tiwari <[email protected]>
Co-authored-by: Peter Zhu <[email protected]>
Co-authored-by: Abhishek Choudhary <[email protected]>
  • Loading branch information
3 people authored Apr 10, 2024
1 parent 4df549c commit c6b9f99
Show file tree
Hide file tree
Showing 262 changed files with 3,269 additions and 879 deletions.
29 changes: 18 additions & 11 deletions .github/workflows/source-install.yml
Original file line number Diff line number Diff line change
Expand Up @@ -88,17 +88,24 @@ jobs:
- name: Test apisix
run: |
curl http://127.0.0.1:9180/apisix/admin/routes/1 \
-H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"uri": "/get",
"upstream": {
"type": "roundrobin",
"nodes": {
"127.0.0.1:8088": 1
}
}
}'
wget https://github.com/mikefarah/yq/releases/download/3.4.1/yq_linux_amd64 -O /usr/bin/yq && sudo chmod +x /usr/bin/yq
get_admin_key() {
local admin_key=$(yq '.deployment.admin.admin_key[0].key' conf/config.yaml)
echo "$admin_key"
}
export admin_key=$(get_admin_key); echo $admin_key
cat conf/config.yaml
curl -v http://127.0.0.1:9180/apisix/admin/routes/1 \
-H "X-API-KEY: $admin_key" -X PUT -d '
{
"uri": "/get",
"upstream": {
"type": "roundrobin",
"nodes": {
"127.0.0.1:8088": 1
}
}
}'
result_code=`curl -I -m 10 -o /dev/null -s -w %{http_code} http://127.0.0.1:9080/get`
if [[ $result_code -ne 200 ]]; then
printf "result_code: %s\n" "$result_code"
Expand Down
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ ENV_DOCKER_COMPOSE ?= docker-compose --project-directory $(CURDIR) -p $(proj
ENV_NGINX ?= $(ENV_NGINX_EXEC) -p $(CURDIR) -c $(CURDIR)/conf/nginx.conf
ENV_NGINX_EXEC := $(shell command -v openresty 2>/dev/null || command -v nginx 2>/dev/null)
ENV_OPENSSL_PREFIX ?= /usr/local/openresty/openssl3
ENV_LIBYAML_INSTALL_PREFIX ?= /usr
ENV_LUAROCKS ?= luarocks
## These variables can be injected by luarocks
ENV_INST_PREFIX ?= /usr
Expand Down Expand Up @@ -131,6 +132,7 @@ deps: install-runtime
mkdir -p ~/.luarocks; \
$(ENV_LUAROCKS) config $(ENV_LUAROCKS_FLAG_LOCAL) variables.OPENSSL_LIBDIR $(addprefix $(ENV_OPENSSL_PREFIX), /lib); \
$(ENV_LUAROCKS) config $(ENV_LUAROCKS_FLAG_LOCAL) variables.OPENSSL_INCDIR $(addprefix $(ENV_OPENSSL_PREFIX), /include); \
$(ENV_LUAROCKS) config $(ENV_LUAROCKS_FLAG_LOCAL) variables.YAML_DIR $(ENV_LIBYAML_INSTALL_PREFIX); \
$(ENV_LUAROCKS) install apisix-master-0.rockspec --tree deps --only-deps $(ENV_LUAROCKS_SERVER_OPT); \
else \
$(call func_echo_warn_status, "WARNING: You're not using LuaRocks 3.x; please remove the luarocks and reinstall it via https://raw.githubusercontent.com/apache/apisix/master/utils/linux-install-luarocks.sh"); \
Expand Down
1 change: 1 addition & 0 deletions apisix-master-0.rockspec
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ description = {

dependencies = {
"lua-resty-ctxdump = 0.1-0",
"lyaml = 6.2.8",
"api7-lua-resty-dns-client = 7.0.1",
"lua-resty-template = 2.0",
"lua-resty-etcd = 1.10.5",
Expand Down
2 changes: 1 addition & 1 deletion apisix/admin/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ local function set_ctx_and_check_token()
local ok, err = check_token(api_ctx)
if not ok then
core.log.warn("failed to check token: ", err)
core.response.exit(401, { error_msg = "failed to check token" })
core.response.exit(401, { error_msg = "failed to check token", description = err })
end
end

Expand Down
7 changes: 2 additions & 5 deletions apisix/cli/ops.lua
Original file line number Diff line number Diff line change
Expand Up @@ -221,12 +221,9 @@ Please modify "admin_key" in conf/config.yaml .
end

if admin.key == "" then
util.die(help:format("ERROR: missing valid Admin API token."), "\n")
end

if admin.key == "edd1c9f034335f136f87ad84b625c8f1" then
stderr:write(
help:format([[WARNING: using fixed Admin API token has security risk.]]),
help:format([[WARNING: using empty Admin API.
This will trigger APISIX to automatically generate a random Admin API token.]]),
"\n"
)
end
Expand Down
79 changes: 72 additions & 7 deletions apisix/core/id.lua
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,19 @@

local fetch_local_conf = require("apisix.core.config_local").local_conf
local try_read_attr = require("apisix.core.table").try_read_attr
local profile = require("apisix.core.profile")
local log = require("apisix.core.log")
local uuid = require('resty.jit-uuid')
local uuid = require("resty.jit-uuid")
local lyaml = require("lyaml")
local smatch = string.match
local open = io.open


local prefix = ngx.config.prefix()
local type = type
local ipairs = ipairs
local string = string
local math = math
local prefix = ngx.config.prefix()
local pairs = pairs
local ngx_exit = ngx.exit
local apisix_uid

local _M = {version = 0.1}
Expand Down Expand Up @@ -62,18 +68,77 @@ local function write_file(path, data)
end


local function generate_yaml(table)
-- By default lyaml will parse null values as []
-- The following logic is a workaround so that null values are parsed as null
local function replace_null(tbl)
for k, v in pairs(tbl) do
if type(v) == "table" then
replace_null(v)
elseif v == nil then
tbl[k] = "<PLACEHOLDER>"
end
end
end

-- Replace null values with "<PLACEHOLDER>"
replace_null(table)
local yaml = lyaml.dump({ table })
yaml = yaml:gsub("<PLACEHOLDER>", "null"):gsub("%[%s*%]", "null")
return yaml
end


_M.gen_uuid_v4 = uuid.generate_v4


--- This will autogenerate the admin key if it's passed as an empty string in the configuration.
local function autogenerate_admin_key(default_conf)
local changed = false
-- Check if deployment.role is either traditional or control_plane
local deployment_role = default_conf.deployment and default_conf.deployment.role
if deployment_role and (deployment_role == "traditional" or
deployment_role == "control_plane") then
-- Check if deployment.admin.admin_key is not nil and it's an empty string
local admin_keys = try_read_attr(default_conf, "deployment", "admin", "admin_key")
if admin_keys and type(admin_keys) == "table" then
for i, admin_key in ipairs(admin_keys) do
if admin_key.role == "admin" and admin_key.key == "" then
changed = true
admin_keys[i].key = ""
for _ = 1, 32 do
admin_keys[i].key = admin_keys[i].key ..
string.char(math.random(65, 90) + math.random(0, 1) * 32)
end
end
end
end
end
return default_conf,changed
end


function _M.init()
local local_conf = fetch_local_conf()

local local_conf, changed = autogenerate_admin_key(local_conf)
if changed then
local yaml_conf = generate_yaml(local_conf)
local local_conf_path = profile:yaml_path("config")
local ok, err = write_file(local_conf_path, yaml_conf)
if not ok then
log.error("failed to write updated local configuration: ", err)
ngx_exit(-1)
end
end

--allow user to specify a meaningful id as apisix instance id
local uid_file_path = prefix .. "/conf/apisix.uid"
apisix_uid = read_file(uid_file_path)
if apisix_uid then
return
end

--allow user to specify a meaningful id as apisix instance id
local local_conf = fetch_local_conf()
local id = try_read_attr(local_conf, "apisix", "id")
if id then
apisix_uid = local_conf.apisix.id
Expand All @@ -89,6 +154,7 @@ function _M.init()
end
end


---
-- Returns the instance id of the running APISIX
--
Expand All @@ -100,5 +166,4 @@ function _M.get()
return apisix_uid
end


return _M
8 changes: 4 additions & 4 deletions benchmark/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ sleep 3

#############################################
echo -e "\n\napisix: $worker_cnt worker + $upstream_cnt upstream + no plugin"

curl http://127.0.0.1:9180/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
admin_key=$(yq '.deployment.admin.admin_key[0].key' conf/config.yaml | sed 's/"//g')
curl http://127.0.0.1:9180/apisix/admin/routes/1 -H "X-API-KEY: $admin_key" -X PUT -d '
{
"uri": "/hello",
"plugins": {
Expand All @@ -100,8 +100,8 @@ sleep 1

#############################################
echo -e "\n\napisix: $worker_cnt worker + $upstream_cnt upstream + 2 plugins (limit-count + prometheus)"

curl http://127.0.0.1:9180/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
admin_key=$(yq '.deployment.admin.admin_key[0].key' conf/config.yaml | sed 's/"//g')
curl http://127.0.0.1:9180/apisix/admin/routes/1 -H "X-API-KEY: $admin_key" -X PUT -d '
{
"uri": "/hello",
"plugins": {
Expand Down
1 change: 1 addition & 0 deletions ci/centos7-ci.sh
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ install_dependencies() {
cpanminus perl \
openssl-devel

yum install -y libyaml-devel
# install newer curl
yum makecache
yum install -y libnghttp2-devel
Expand Down
3 changes: 3 additions & 0 deletions ci/common.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export_version_info() {

export_or_prefix() {
export OPENRESTY_PREFIX="/usr/local/openresty"

export PATH=$OPENRESTY_PREFIX/nginx/sbin:$OPENRESTY_PREFIX/luajit/bin:$OPENRESTY_PREFIX/bin:$PATH
export OPENSSL_PREFIX=$OPENRESTY_PREFIX/openssl3
export OPENSSL_BIN=$OPENSSL_PREFIX/bin/openssl
Expand Down Expand Up @@ -178,6 +179,8 @@ GRPC_SERVER_EXAMPLE_VER=20210819
linux_get_dependencies () {
apt update
apt install -y cpanminus build-essential libncurses5-dev libreadline-dev libssl-dev perl libpcre3 libpcre3-dev libldap2-dev
apt-get install -y libyaml-dev
wget https://github.com/mikefarah/yq/releases/download/3.4.1/yq_linux_amd64 -O /usr/bin/yq && sudo chmod +x /usr/bin/yq
}

function start_grpc_server_example() {
Expand Down
2 changes: 1 addition & 1 deletion ci/redhat-ci.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ install_dependencies() {
wget tar gcc gcc-c++ automake autoconf libtool make unzip git sudo openldap-devel hostname patch \
which ca-certificates pcre pcre-devel xz \
openssl-devel

yum install -y libyaml-devel
yum install -y --disablerepo=* --enablerepo=ubi-8-appstream-rpms --enablerepo=ubi-8-baseos-rpms cpanminus perl

# install newer curl
Expand Down
8 changes: 5 additions & 3 deletions conf/config-default.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,8 @@ nginx_config: # Config for render the template to generate n
stream:
enable_access_log: false # Enable stream proxy access logging.
access_log: logs/access_stream.log # Location of the stream access log.
access_log_format: "$remote_addr [$time_local] $protocol $status $bytes_sent $bytes_received $session_time" # Customize log format: http://nginx.org/en/docs/varindex.html
access_log_format: |
"$remote_addr [$time_local] $protocol $status $bytes_sent $bytes_received $session_time" # Customize log format: http://nginx.org/en/docs/varindex.html
access_log_format_escape: default # Escape default or json characters in variables.
lua_shared_dict: # Nginx Lua shared memory zone. Size units are m or k.
etcd-cluster-health-check-stream: 10m
Expand Down Expand Up @@ -208,7 +209,8 @@ nginx_config: # Config for render the template to generate n
enable_access_log: true # Enable HTTP proxy access logging.
access_log: logs/access.log # Location of the access log.
access_log_buffer: 16384 # buffer size of access log.
access_log_format: "$remote_addr - $remote_user [$time_local] $http_host \"$request\" $status $body_bytes_sent $request_time \"$http_referer\" \"$http_user_agent\" $upstream_addr $upstream_status $upstream_response_time \"$upstream_scheme://$upstream_host$upstream_uri\""
access_log_format: |
"$remote_addr - $remote_user [$time_local] $http_host \"$request\" $status $body_bytes_sent $request_time \"$http_referer\" \"$http_user_agent\" $upstream_addr $upstream_status $upstream_response_time \"$upstream_scheme://$upstream_host$upstream_uri\""
# Customize log format: http://nginx.org/en/docs/varindex.html
access_log_format_escape: default # Escape default or json characters in variables.
keepalive_timeout: 60s # Set the maximum time for which TCP connection keeps alive.
Expand Down Expand Up @@ -643,7 +645,7 @@ deployment: # Deployment configurations
admin_key:
-
name: admin # admin: write access to configurations.
key: edd1c9f034335f136f87ad84b625c8f1 # Set API key for the admin of Admin API.
key: '' # Set API key for the admin of Admin API.
role: admin
-
name: viewer # viewer: read-only to configurations.
Expand Down
2 changes: 1 addition & 1 deletion conf/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,5 @@ deployment:
admin:
admin_key:
- name: admin
key: edd1c9f034335f136f87ad84b625c8f1 # using fixed API token has security risk, please update it when you deploy to production environment
key: '' # using fixed API token has security risk, please update it when you deploy to production environment. If passed empty then will be autogenerated by APISIX and will be written back here. Recommended is to use external mechanism to generate and store the token.
role: admin
27 changes: 18 additions & 9 deletions docs/en/latest/FAQ.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,19 @@ Let's take an example query `foo.com/product/index.html?id=204&page=2` and consi

There are two different ways to achieve this in Apache APISIX:

:::note
You can fetch the `admin_key` from `config.yaml` and save to an environment variable with the following command:

```bash
admin_key=$(yq '.deployment.admin.admin_key[0].key' conf/config.yaml | sed 's/"//g')
```

:::

1. Using the `vars` field in a [Route](terminology/route.md):

```shell
curl -i http://127.0.0.1:9180/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
curl -i http://127.0.0.1:9180/apisix/admin/routes/1 -H "X-API-KEY: $admin_key" -X PUT -d '
{
"uri": "/index.html",
"vars": [
Expand All @@ -136,7 +145,7 @@ curl -i http://127.0.0.1:9180/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335
}
}'

curl -i http://127.0.0.1:9180/apisix/admin/routes/2 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
curl -i http://127.0.0.1:9180/apisix/admin/routes/2 -H "X-API-KEY: $admin_key" -X PUT -d '
{
"uri": "/index.html",
"vars": [
Expand All @@ -163,7 +172,7 @@ Apache APISIX provides several different ways to achieve this:
1. Setting `http_to_https` to `true` in the [redirect](plugins/redirect.md) Plugin:

```shell
curl http://127.0.0.1:9180/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
curl http://127.0.0.1:9180/apisix/admin/routes/1 -H "X-API-KEY: $admin_key" -X PUT -d '
{
"uri": "/hello",
"host": "foo.com",
Expand All @@ -178,7 +187,7 @@ curl http://127.0.0.1:9180/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f1
2. Advanced routing with `vars` in the redirect Plugin:

```shell
curl -i http://127.0.0.1:9180/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
curl -i http://127.0.0.1:9180/apisix/admin/routes/1 -H "X-API-KEY: $admin_key" -X PUT -d '
{
"uri": "/hello",
"host": "foo.com",
Expand All @@ -201,7 +210,7 @@ curl -i http://127.0.0.1:9180/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f03433
3. Using the `serverless` Plugin:

```shell
curl -i http://127.0.0.1:9180/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
curl -i http://127.0.0.1:9180/apisix/admin/routes/1 -H "X-API-KEY: $admin_key" -X PUT -d '
{
"uri": "/hello",
"plugins": {
Expand Down Expand Up @@ -392,7 +401,7 @@ deployment:
2. Add a proxy Route for the Apache APISIX dashboard:

```shell
curl -i http://127.0.0.1:9180/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
curl -i http://127.0.0.1:9180/apisix/admin/routes/1 -H "X-API-KEY: $admin_key" -X PUT -d '
{
"uris":[ "/*" ],
"name":"apisix_proxy_dashboard",
Expand All @@ -416,7 +425,7 @@ curl -i http://127.0.0.1:9180/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f03433
You can use the `vars` field in a Route for matching regular expressions:

```shell
curl -i http://127.0.0.1:9180/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
curl -i http://127.0.0.1:9180/apisix/admin/routes/1 -H "X-API-KEY: $admin_key" -X PUT -d '
{
"uri": "/*",
"vars": [
Expand Down Expand Up @@ -452,7 +461,7 @@ For more info on using `vars` refer to [lua-resty-expr](https://github.com/api7/
Yes. The example below shows configuring the FQDN `httpbin.default.svc.cluster.local` (a Kubernetes service):

```shell
curl http://127.0.0.1:9180/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
curl http://127.0.0.1:9180/apisix/admin/routes/1 -H "X-API-KEY: $admin_key" -X PUT -d '
{
"uri": "/ip",
"upstream": {
Expand Down Expand Up @@ -554,7 +563,7 @@ You can check [this post](https://juejin.cn/post/6965778290619449351) for a more
To strip a prefix from a path in your route, like to take `/foo/get` and strip it to `/get`, you can use the [proxy-rewrite](plugins/proxy-rewrite.md) Plugin:

```shell
curl -i http://127.0.0.1:9180/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
curl -i http://127.0.0.1:9180/apisix/admin/routes/1 -H "X-API-KEY: $admin_key" -X PUT -d '
{
"uri": "/foo/*",
"plugins": {
Expand Down
Loading

0 comments on commit c6b9f99

Please sign in to comment.