# # 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. # use t::APISIX 'no_plan'; repeat_each(1); log_level('info'); no_root_location(); no_shuffle(); add_block_preprocessor(sub { my ($block) = @_; if (!$block->apisix_json) { my $json_config = <<_EOC_; { "routes": [ { "uri": "/hello", "upstream": { "nodes": { "127.0.0.1:1980": 1 }, "type": "roundrobin" } } ] } _EOC_ $block->set_value("apisix_json", $json_config); } }); run_tests(); __DATA__ === TEST 1: validate secret/vault: wrong schema --- apisix_json { "routes": [ { "uri": "/hello", "upstream": { "nodes": { "127.0.0.1:1980": 1 }, "type": "roundrobin" } } ], "secrets": [ { "id": "vault/1", "prefix": "kv/apisix", "token": "root", "uri": "127.0.0.1:8200" } ] } --- config location /t { content_by_lua_block { local secret = require("apisix.secret") local values = secret.secrets() ngx.say(#values) } } --- request GET /t --- response_body 0 --- error_log property "uri" validation failed: failed to match pattern "^[^\\/]+:\\/\\/([\\da-zA-Z.-]+|\\[[\\da-fA-F:]+\\])(:\\d+)?" === TEST 2: validate secrets: manager not exits --- apisix_json { "routes": [ { "uri": "/hello", "upstream": { "nodes": { "127.0.0.1:1980": 1 }, "type": "roundrobin" } } ], "secrets": [ { "id": "hhh/1", "prefix": "kv/apisix", "token": "root", "uri": "127.0.0.1:8200" } ] } --- config location /t { content_by_lua_block { local secret = require("apisix.secret") local values = secret.secrets() ngx.say(#values) } } --- request GET /t --- response_body 0 --- error_log secret manager not exits === TEST 3: load config normal --- apisix_json { "routes": [ { "uri": "/hello", "upstream": { "nodes": { "127.0.0.1:1980": 1 }, "type": "roundrobin" } } ], "secrets": [ { "id": "vault/1", "prefix": "kv/apisix", "token": "root", "uri": "http://127.0.0.1:8200" } ] } --- config location /t { content_by_lua_block { local secret = require("apisix.secret") local values = secret.secrets() ngx.say("len: ", #values) ngx.say("id: ", values[1].value.id) ngx.say("prefix: ", values[1].value.prefix) ngx.say("token: ", values[1].value.token) ngx.say("uri: ", values[1].value.uri) } } --- request GET /t --- response_body len: 1 id: vault/1 prefix: kv/apisix token: root uri: http://127.0.0.1:8200 === TEST 4: store secret into vault --- exec VAULT_TOKEN='root' VAULT_ADDR='http://0.0.0.0:8200' vault kv put kv/apisix/apisix-key key=value --- response_body Success! Data written to: kv/apisix/apisix-key === TEST 5: secret.fetch_by_uri: start with $secret:// --- apisix_json { "routes": [ { "uri": "/hello", "upstream": { "nodes": { "127.0.0.1:1980": 1 }, "type": "roundrobin" } } ], "secrets": [ { "id": "vault/1", "prefix": "kv/apisix", "token": "root", "uri": "http://127.0.0.1:8200" } ] } --- config location /t { content_by_lua_block { local secret = require("apisix.secret") local value = secret.fetch_by_uri("$secret://vault/1/apisix-key/key") ngx.say(value) } } --- request GET /t --- response_body value === TEST 6: secret.fetch_by_uri, wrong ref format: wrong type --- config location /t { content_by_lua_block { local secret = require("apisix.secret") local _, err = secret.fetch_by_uri(1) ngx.say(err) } } --- request GET /t --- response_body error secret_uri type: number === TEST 7: secret.fetch_by_uri, wrong ref format: wrong prefix --- config location /t { content_by_lua_block { local secret = require("apisix.secret") local _, err = secret.fetch_by_uri("secret://") ngx.say(err) } } --- request GET /t --- response_body error secret_uri prefix: secret:// === TEST 8: secret.fetch_by_uri, error format: no secret manager --- config location /t { content_by_lua_block { local secret = require("apisix.secret") local _, err = secret.fetch_by_uri("$secret://") ngx.say(err) } } --- request GET /t --- response_body error format: no secret manager === TEST 9: secret.fetch_by_uri, error format: no secret conf id --- config location /t { content_by_lua_block { local secret = require("apisix.secret") local _, err = secret.fetch_by_uri("$secret://vault/") ngx.say(err) } } --- request GET /t --- response_body error format: no secret conf id === TEST 10: secret.fetch_by_uri, error format: no secret key id --- config location /t { content_by_lua_block { local secret = require("apisix.secret") local _, err = secret.fetch_by_uri("$secret://vault/2/") ngx.say(err) } } --- request GET /t --- response_body error format: no secret key id === TEST 11: secret.fetch_by_uri, no config --- config location /t { content_by_lua_block { local secret = require("apisix.secret") local _, err = secret.fetch_by_uri("$secret://vault/2/bar") ngx.say(err) } } --- request GET /t --- response_body no secret conf, secret_uri: $secret://vault/2/bar === TEST 12: secret.fetch_by_uri, no sub key value --- apisix_json { "routes": [ { "uri": "/hello", "upstream": { "nodes": { "127.0.0.1:1980": 1 }, "type": "roundrobin" } } ], "secrets": [ { "id": "vault/1", "prefix": "kv/apisix", "token": "root", "uri": "http://127.0.0.1:8200" } ] } --- config location /t { content_by_lua_block { local secret = require("apisix.secret") local value = secret.fetch_by_uri("$secret://vault/1/apisix-key/bar") ngx.say(value) } } --- request GET /t --- response_body nil === TEST 13: fetch_secrets env: no cache --- main_config env secret=apisix; --- config location /t { content_by_lua_block { local secret = require("apisix.secret") local refs = { key = "jack", secret = "$env://secret" } local new_refs = secret.fetch_secrets(refs) assert(new_refs ~= refs) ngx.say(refs.secret) ngx.say(new_refs.secret) ngx.say(new_refs.key) } } --- request GET /t --- response_body $env://secret apisix jack --- error_log_like qr/retrieve secrets refs/ === TEST 14: fetch_secrets env: cache --- main_config env secret=apisix; --- config location /t { content_by_lua_block { local secret = require("apisix.secret") local refs = { key = "jack", secret = "$env://secret" } local refs_1 = secret.fetch_secrets(refs, true, "key", 1) local refs_2 = secret.fetch_secrets(refs, true, "key", 1) assert(refs_1 == refs_2) ngx.say(refs_1.secret) ngx.say(refs_2.secret) } } --- request GET /t --- response_body apisix apisix --- grep_error_log eval qr/retrieve secrets refs/ --- grep_error_log_out retrieve secrets refs === TEST 15: fetch_secrets env: table nesting --- main_config env secret=apisix; --- config location /t { content_by_lua_block { local secret = require("apisix.secret") local refs = { key = "jack", user = { username = "apisix", passsword = "$env://secret" } } local new_refs = secret.fetch_secrets(refs) ngx.say(new_refs.user.passsword) } } --- request GET /t --- response_body apisix === TEST 16: fetch_secrets: wrong refs type --- main_config env secret=apisix; --- config location /t { content_by_lua_block { local secret = require("apisix.secret") local refs = "wrong" local new_refs = secret.fetch_secrets(refs) ngx.say(new_refs) } } --- request GET /t --- response_body nil