Skip to content

Commit

Permalink
feat(gRPC): support user/password
Browse files Browse the repository at this point in the history
Signed-off-by: spacewander <spacewanderlzx@gmail.com>
  • Loading branch information
spacewander committed Dec 8, 2022
1 parent 5822eca commit 221aeff
Show file tree
Hide file tree
Showing 7 changed files with 289 additions and 6 deletions.
4 changes: 0 additions & 4 deletions apisix/cli/snippet.lua
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,6 @@ server {

local function is_grpc_used(env, etcd)
local is_grpc_available = env.use_apisix_base
if etcd.user then
-- TODO: support user/password
is_grpc_available = false
end
return is_grpc_available and etcd.use_grpc
end

Expand Down
3 changes: 1 addition & 2 deletions apisix/core/etcd.lua
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,7 @@ local function _new(etcd_conf)
end

if etcd_conf.use_grpc then
-- TODO: let lua-resty-etcd support more use cases
if etcd.user or ngx_get_phase() == "init" then
if ngx_get_phase() == "init" then
etcd_conf.use_grpc = false
else
local ok = pcall(require, "resty.grpc")
Expand Down
2 changes: 2 additions & 0 deletions ci/linux_apisix_current_luarocks_runner.sh
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ script() {
ulimit -n -S
ulimit -n -H

git clone https://github.com/spacewander/lua-resty-etcd.git -b f1 --depth 1
cp lua-resty-etcd/lib/resty/etcd/*.lua /usr/local/share/lua/5.1/resty/etcd/
for f in ./t/cli/test_*.sh; do
PATH="$PATH" "$f"
done
Expand Down
2 changes: 2 additions & 0 deletions ci/linux_openresty_common_runner.sh
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ script() {
sleep 1
done

git clone https://github.com/spacewander/lua-resty-etcd.git -b f1 --depth 1
cp lua-resty-etcd/lib/resty/etcd/*.lua deps/share/lua/5.1/resty/etcd/
# APISIX_ENABLE_LUACOV=1 PERL5LIB=.:$PERL5LIB prove -Itest-nginx/lib -r t
FLUSH_ETCD=1 prove --timer -Itest-nginx/lib -I./ -r $TEST_FILE_SUB_DIR | tee /tmp/test.result
rerun_flaky_tests /tmp/test.result
Expand Down
70 changes: 70 additions & 0 deletions t/cli/test_etcd_grpc.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#!/usr/bin/env bash

#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

# 'make init' operates scripts and related configuration files in the current directory
# The 'apisix' command is a command in the /usr/local/apisix,
# and the configuration file for the operation is in the /usr/local/apisix/conf

. ./t/cli/common.sh

exit_if_not_customed_nginx

# check etcd while enable auth
git checkout conf/config.yaml

export ETCDCTL_API=3
etcdctl version
etcdctl --endpoints=127.0.0.1:2379 user add "root:apache-api6"
etcdctl --endpoints=127.0.0.1:2379 role add root
etcdctl --endpoints=127.0.0.1:2379 user grant-role root root
etcdctl --endpoints=127.0.0.1:2379 user get root
etcdctl --endpoints=127.0.0.1:2379 auth enable
etcdctl --endpoints=127.0.0.1:2379 --user=root:apache-api6 del /apisix --prefix

echo '
deployment:
role: traditional
role_traditional:
config_provider: etcd
etcd:
host:
- http://127.0.0.1:2379
prefix: /apisix
timeout: 30
use_grpc: true
user: root
password: apache-api6
' > conf/config.yaml

make run
sleep 1

code=$(curl -o /dev/null -s -w %{http_code} http://127.0.0.1:9180/apisix/admin/routes -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1')
make stop

if [ ! $code -eq 200 ]; then
echo "failed: could not work with etcd"
exit 1
fi

echo "passed: work well with etcd auth enabled"

etcdctl --endpoints=127.0.0.1:2379 --user=root:apache-api6 auth disable
etcdctl --endpoints=127.0.0.1:2379 role delete root
etcdctl --endpoints=127.0.0.1:2379 user delete root
106 changes: 106 additions & 0 deletions t/core/etcd-grpc-auth-fail.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
BEGIN {
$ENV{"ETCD_ENABLE_AUTH"} = "false";
delete $ENV{"FLUSH_ETCD"};
}

use t::APISIX;

my $nginx_binary = $ENV{'TEST_NGINX_BINARY'} || 'nginx';
my $version = eval { `$nginx_binary -V 2>&1` };

if ($version !~ m/\/apisix-nginx-module/) {
plan(skip_all => "apisix-nginx-module not installed");
} else {
plan('no_plan');
}


repeat_each(1);
no_long_string();
no_root_location();
log_level("info");

# Authentication is enabled at etcd and credentials are set
system('etcdctl --endpoints="http://127.0.0.1:2379" user add root:5tHkHhYkjr6cQY');
system('etcdctl --endpoints="http://127.0.0.1:2379" role add root');
system('etcdctl --endpoints="http://127.0.0.1:2379" user grant-role root root');
system('etcdctl --endpoints="http://127.0.0.1:2379" role list');
system('etcdctl --endpoints="http://127.0.0.1:2379" user user list');
# Grant the user access to the specified directory
system('etcdctl --endpoints="http://127.0.0.1:2379" user add apisix:abc123');
system('etcdctl --endpoints="http://127.0.0.1:2379" role add apisix');
system('etcdctl --endpoints="http://127.0.0.1:2379" user grant-role apisix apisix');
system('etcdctl --endpoints=http://127.0.0.1:2379 role grant-permission apisix --prefix=true readwrite /apisix/');
system('etcdctl --endpoints="http://127.0.0.1:2379" auth enable');

run_tests;

# Authentication is disabled at etcd
system('etcdctl --endpoints="http://127.0.0.1:2379" --user root:5tHkHhYkjr6cQY auth disable');
system('etcdctl --endpoints="http://127.0.0.1:2379" user delete root');
system('etcdctl --endpoints="http://127.0.0.1:2379" role delete root');
system('etcdctl --endpoints="http://127.0.0.1:2379" user delete apisix');
system('etcdctl --endpoints="http://127.0.0.1:2379" role delete apisix');
__DATA__

=== TEST 1: Set and Get a value pass
--- config
location /t {
content_by_lua_block {
local core = require("apisix.core")
local key = "/test_key"
local val = "test_value"
local res, err = core.etcd.set(key, val)
ngx.say(err)
}
}
--- request
GET /t
--- error_log eval
qr /(insufficient credentials code: 401|etcdserver: user name is empty)/



=== TEST 2: etcd grants permissions with a different prefix than the one used by apisix, etcd will forbidden
--- config
location /t {
content_by_lua_block {
local core = require("apisix.core")
local key = "/test_key"
local val = "test_value"
local res, err = core.etcd.set(key, val)
ngx.say(err)
}
}
--- yaml_config
deployment:
role: traditional
role_traditional:
config_provider: etcd
etcd:
host:
- "http://127.0.0.1:2379"
use_grpc: false
prefix: "/apisix"
user: apisix
password: abc123
--- request
GET /t
--- error_log eval
qr /etcd forbidden code: 403/
108 changes: 108 additions & 0 deletions t/core/etcd-grpc-auth.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
BEGIN {
$ENV{"ETCD_ENABLE_AUTH"} = "true";
delete $ENV{"FLUSH_ETCD"};
}

use t::APISIX;

my $nginx_binary = $ENV{'TEST_NGINX_BINARY'} || 'nginx';
my $version = eval { `$nginx_binary -V 2>&1` };

if ($version !~ m/\/apisix-nginx-module/) {
plan(skip_all => "apisix-nginx-module not installed");
} else {
plan('no_plan');
}


repeat_each(1);
no_long_string();
no_root_location();
log_level("info");

# Authentication is enabled at etcd and credentials are set
system('etcdctl --endpoints="http://127.0.0.1:2379" user add root:5tHkHhYkjr6cQY');
system('etcdctl --endpoints="http://127.0.0.1:2379" role add root');
system('etcdctl --endpoints="http://127.0.0.1:2379" user grant-role root root');
system('etcdctl --endpoints="http://127.0.0.1:2379" role list');
system('etcdctl --endpoints="http://127.0.0.1:2379" user user list');
# Grant the user access to the specified directory
system('etcdctl --endpoints="http://127.0.0.1:2379" user add apisix:abc123');
system('etcdctl --endpoints="http://127.0.0.1:2379" role add apisix');
system('etcdctl --endpoints="http://127.0.0.1:2379" user grant-role apisix apisix');
system('etcdctl --endpoints=http://127.0.0.1:2379 role grant-permission apisix --prefix=true readwrite /apisix');
system('etcdctl --endpoints="http://127.0.0.1:2379" auth enable');

run_tests;

# Authentication is disabled at etcd
system('etcdctl --endpoints="http://127.0.0.1:2379" --user root:5tHkHhYkjr6cQY auth disable');
system('etcdctl --endpoints="http://127.0.0.1:2379" user delete root');
system('etcdctl --endpoints="http://127.0.0.1:2379" role delete root');
system('etcdctl --endpoints="http://127.0.0.1:2379" user delete apisix');
system('etcdctl --endpoints="http://127.0.0.1:2379" role delete apisix');


__DATA__

=== TEST 1: Set and Get a value pass with authentication
--- config
location /t {
content_by_lua_block {
local core = require("apisix.core")
local key = "/test_key"
local val = "test_value"
core.etcd.set(key, val)
local res, err = core.etcd.get(key)
ngx.say(res.body.node.value)
core.etcd.delete(val)
}
}
--- request
GET /t
--- response_body
test_value



=== TEST 2: etcd grants permissions with the same prefix as apisix uses, etcd is normal
--- config
location /t {
content_by_lua_block {
local core = require("apisix.core")
local key = "/test_key"
local val = "test_value"
local res, err = core.etcd.set(key, val)
ngx.say(err)
}
}
--- yaml_config
deployment:
role: traditional
role_traditional:
config_provider: etcd
etcd:
use_grpc: true
host:
- "http://127.0.0.1:2379"
prefix: "/apisix"
user: apisix
password: abc123
--- request
GET /t

0 comments on commit 221aeff

Please sign in to comment.