Skip to content

Commit 9b1e546

Browse files
authored
fix(security): TLS ssl_verify hardcoding and credential encryption issues (#13203)
1 parent 84996a2 commit 9b1e546

9 files changed

Lines changed: 449 additions & 43 deletions

File tree

apisix/core/utils.lua

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,9 @@ local function get_root_conf(str, conf, field)
421421
local num_of_matches = #matches
422422
for i = 1, num_of_matches - 1 , 1 do
423423
conf = conf[matches[i]]
424+
if type(conf) ~= "table" then
425+
return nil, nil
426+
end
424427
end
425428

426429
-- return the table and the last field
@@ -441,12 +444,12 @@ function _M.check_https(fields, conf, plugin_name)
441444

442445
local new_conf, new_field = get_root_conf(field, conf)
443446
if not new_conf then
444-
return
447+
goto continue
445448
end
446449

447450
local value = new_conf[new_field]
448451
if not value then
449-
return
452+
goto continue
450453
end
451454

452455
if type(value) == "table" then
@@ -456,6 +459,8 @@ function _M.check_https(fields, conf, plugin_name)
456459
else
457460
find_and_log(field, plugin_name, value)
458461
end
462+
463+
::continue::
459464
end
460465
end
461466

apisix/plugins/ai-rag.lua

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,10 @@ local HTTP_BAD_REQUEST = ngx.HTTP_BAD_REQUEST
3131
local schema = {
3232
type = "object",
3333
properties = {
34-
type = "object",
34+
ssl_verify = {
35+
type = "boolean",
36+
default = true,
37+
},
3538
embeddings_provider = {
3639
type = "object",
3740
properties = {
@@ -83,12 +86,18 @@ local _M = {
8386

8487

8588
function _M.check_schema(conf)
89+
core.utils.check_tls_bool({"ssl_verify"}, conf, _M.name)
90+
core.utils.check_https({
91+
"embeddings_provider.azure_openai.endpoint",
92+
"vector_search_provider.azure_ai_search.endpoint",
93+
}, conf, _M.name)
8694
return core.schema.check(schema, conf)
8795
end
8896

8997

9098
function _M.access(conf, ctx)
9199
local httpc = http.new()
100+
local ssl_verify = conf.ssl_verify ~= false
92101
local body_tab, err = core.request.get_json_request_body_table()
93102
if not body_tab then
94103
return HTTP_BAD_REQUEST, err
@@ -120,7 +129,8 @@ function _M.access(conf, ctx)
120129
end
121130

122131
local embeddings, status, err = embeddings_driver.get_embeddings(embeddings_provider_conf,
123-
body_tab["ai_rag"].embeddings, httpc)
132+
body_tab["ai_rag"].embeddings, httpc,
133+
ssl_verify)
124134
if not embeddings then
125135
core.log.error("could not get embeddings: ", err)
126136
return status, err
@@ -129,7 +139,7 @@ function _M.access(conf, ctx)
129139
local search_body = body_tab["ai_rag"].vector_search
130140
search_body.embeddings = embeddings
131141
local res, status, err = vector_search_driver.search(vector_search_provider_conf,
132-
search_body, httpc)
142+
search_body, httpc, ssl_verify)
133143
if not res then
134144
core.log.error("could not get vector_search result: ", err)
135145
return status, err

apisix/plugins/ai-rag/embeddings/azure_openai.lua

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ _M.schema = {
3434
required = { "endpoint", "api_key" }
3535
}
3636

37-
function _M.get_embeddings(conf, body, httpc)
37+
function _M.get_embeddings(conf, body, httpc, ssl_verify)
3838
local body_tab, err = core.json.encode(body)
3939
if not body_tab then
4040
return nil, HTTP_INTERNAL_SERVER_ERROR, err
@@ -46,7 +46,8 @@ function _M.get_embeddings(conf, body, httpc)
4646
["Content-Type"] = "application/json",
4747
["api-key"] = conf.api_key,
4848
},
49-
body = body_tab
49+
body = body_tab,
50+
ssl_verify = ssl_verify,
5051
})
5152

5253
if not res or not res.body then

apisix/plugins/ai-rag/vector-search/azure_ai_search.lua

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ _M.schema = {
3434
}
3535

3636

37-
function _M.search(conf, search_body, httpc)
37+
function _M.search(conf, search_body, httpc, ssl_verify)
3838
local body = {
3939
vectorQueries = {
4040
{
@@ -55,7 +55,8 @@ function _M.search(conf, search_body, httpc)
5555
["Content-Type"] = "application/json",
5656
["api-key"] = conf.api_key,
5757
},
58-
body = final_body
58+
body = final_body,
59+
ssl_verify = ssl_verify,
5960
})
6061

6162
if not res or not res.body then

apisix/plugins/aws-lambda.lua

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,4 +184,14 @@ end
184184

185185
local serverless_obj = require("apisix.plugins.serverless.generic-upstream")
186186

187-
return serverless_obj(plugin_name, plugin_version, priority, request_processor, aws_authz_schema)
187+
local plugin = serverless_obj(plugin_name, plugin_version, priority, request_processor,
188+
aws_authz_schema)
189+
190+
-- encrypt sensitive credential fields at rest
191+
plugin.schema.encrypt_fields = {
192+
"authorization.apikey",
193+
"authorization.iam.accesskey",
194+
"authorization.iam.secretkey",
195+
}
196+
197+
return plugin

apisix/plugins/wolf-rbac.lua

Lines changed: 44 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ local schema = {
4848
type = "string",
4949
default = "X-"
5050
},
51+
ssl_verify = {
52+
type = "boolean",
53+
},
5154
}
5255
}
5356

@@ -108,7 +111,7 @@ local function new_headers()
108111
end
109112

110113
-- timeout in ms
111-
local function http_req(method, uri, body, myheaders, timeout)
114+
local function http_req(method, uri, body, myheaders, timeout, ssl_verify)
112115
if not myheaders then
113116
myheaders = new_headers()
114117
end
@@ -122,7 +125,7 @@ local function http_req(method, uri, body, myheaders, timeout)
122125
method = method,
123126
headers = myheaders,
124127
body = body,
125-
ssl_verify = false
128+
ssl_verify = ssl_verify == true,
126129
})
127130

128131
if not res then
@@ -134,21 +137,23 @@ local function http_req(method, uri, body, myheaders, timeout)
134137
return res
135138
end
136139

137-
local function http_get(uri, myheaders, timeout)
138-
return http_req("GET", uri, nil, myheaders, timeout)
140+
local function http_get(uri, myheaders, timeout, ssl_verify)
141+
return http_req("GET", uri, nil, myheaders, timeout, ssl_verify)
139142
end
140143

141144

142145
function _M.check_schema(conf)
143-
local check = {"server"}
144-
core.utils.check_https(check, conf, plugin_name)
145-
core.log.info("input conf server: ", conf.server)
146-
147146
local ok, err = core.schema.check(schema, conf)
148147
if not ok then
149148
return false, err
150149
end
151150

151+
local check = {"server"}
152+
core.utils.check_https(check, conf, plugin_name)
153+
core.log.info("input conf server: ", conf.server)
154+
155+
core.utils.check_tls_bool({"ssl_verify"}, conf, plugin_name)
156+
152157
return true
153158
end
154159

@@ -170,7 +175,8 @@ local function fetch_rbac_token(ctx)
170175
end
171176

172177

173-
local function check_url_permission(server, appid, action, resName, client_ip, wolf_token)
178+
local function check_url_permission(server, appid, action, resName,
179+
client_ip, wolf_token, ssl_verify)
174180
local retry_max = 3
175181
local errmsg
176182
local userInfo
@@ -186,7 +192,7 @@ local function check_url_permission(server, appid, action, resName, client_ip, w
186192

187193
for i = 1, retry_max do
188194
-- TODO: read apisix info.
189-
res, err = http_get(url, headers, timeout)
195+
res, err = http_get(url, headers, timeout, ssl_verify)
190196
if err then
191197
break
192198
else
@@ -271,9 +277,10 @@ function _M.rewrite(conf, ctx)
271277
end
272278
core.log.info("consumer appid: ", appid)
273279
local server = cur_consumer.auth_conf.server
280+
local ssl_verify = cur_consumer.auth_conf.ssl_verify
274281

275282
local res = check_url_permission(server, appid, action, url,
276-
client_ip, wolf_token)
283+
client_ip, wolf_token, ssl_verify)
277284
core.log.info(" check_url_permission(appid: ", appid,
278285
", action: ", action, ", url: ", url,
279286
") res status: ", res.status, ", err: ", res.err)
@@ -341,43 +348,47 @@ local function get_consumer(appid)
341348
return consumer
342349
end
343350

344-
local function request_to_wolf_server(method, uri, headers, body)
351+
local function request_to_wolf_server(method, uri, headers, body, ssl_verify)
345352
headers["Content-Type"] = "application/json; charset=utf-8"
346353
local timeout = 1000 * 5
347-
core.log.info("request to wolf-server [method: ", method,
348-
", uri: ", uri, ", timeout: ", timeout, "] ....")
349-
local res, err = http_req(method, uri, core.json.encode(body), headers, timeout)
350-
if not res then
351-
core.log.error("request to wolf-server [method: ", method,
352-
", uri: ", uri, "] failed! err: ", err)
354+
local request_debug = core.json.delay_encode(
355+
{method = method, uri = uri, timeout = timeout}
356+
)
357+
358+
core.log.info("request [", request_debug, "] ....")
359+
local encoded_body, err = core.json.encode(body)
360+
if not encoded_body then
361+
core.log.error("request [", request_debug, "] failed! err: ", err)
353362
return core.response.exit(500,
354363
fail_response("request to wolf-server failed!")
355364
)
356365
end
357-
core.log.info("request to wolf-server [method: ", method,
358-
", uri: ", uri, "] status: ", res.status)
359366

360-
if res.status ~= 200 then
361-
core.log.error("request to wolf-server [method: ", method,
362-
", uri: ", uri, "] failed! status: ", res.status)
367+
local res, err = http_req(method, uri, encoded_body, headers, timeout, ssl_verify)
368+
if not res then
369+
core.log.error("request [", request_debug, "] failed! err: ", err)
363370
return core.response.exit(500,
364-
fail_response("request to wolf-server failed!")
371+
fail_response("request to wolf-server failed!")
365372
)
366373
end
374+
core.log.info("request [", request_debug, "] status: ", res.status)
375+
376+
if res.status ~= 200 then
377+
core.log.error("request [", request_debug, "] failed! status: ",
378+
res.status)
379+
return core.response.exit(500, fail_response("request to wolf-server failed!"))
380+
end
367381
local body, err = json.decode(res.body)
368382
if not body then
369-
core.log.error("request to wolf-server [method: ", method,
370-
", uri: ", uri, "] failed! err:", err)
383+
core.log.error("request [", request_debug, "] failed! err:", err)
371384
return core.response.exit(500, fail_response("request to wolf-server failed!"))
372385
end
373386
if not body.ok then
374-
core.log.error("request to wolf-server [method: ", method,
375-
", uri: ", uri, "] failed! reason: ", body.reason)
387+
core.log.error("request [", request_debug, "] failed! reason: ", body.reason)
376388
return core.response.exit(200, fail_response("request to wolf-server failed!"))
377389
end
378390

379-
core.log.info("request to wolf-server [method: ", method,
380-
", uri: ", uri, "] success")
391+
core.log.info("request [", request_debug, "] success!")
381392
return body
382393
end
383394

@@ -396,7 +407,7 @@ local function wolf_rbac_login()
396407

397408
local uri = consumer.auth_conf.server .. '/wolf/rbac/login.rest'
398409
local headers = new_headers()
399-
local body = request_to_wolf_server('POST', uri, headers, args)
410+
local body = request_to_wolf_server('POST', uri, headers, args, consumer.auth_conf.ssl_verify)
400411

401412
local userInfo = body.data.userInfo
402413
local wolf_token = body.data.token
@@ -440,7 +451,7 @@ local function wolf_rbac_change_pwd()
440451
local uri = consumer.auth_conf.server .. '/wolf/rbac/change_pwd'
441452
local headers = new_headers()
442453
headers['x-rbac-token'] = wolf_token
443-
request_to_wolf_server('POST', uri, headers, args)
454+
request_to_wolf_server('POST', uri, headers, args, consumer.auth_conf.ssl_verify)
444455
core.response.exit(200, success_response('success to change password', { }))
445456
end
446457

@@ -455,7 +466,7 @@ local function wolf_rbac_user_info()
455466
local uri = consumer.auth_conf.server .. '/wolf/rbac/user_info'
456467
local headers = new_headers()
457468
headers['x-rbac-token'] = wolf_token
458-
local body = request_to_wolf_server('GET', uri, headers, {})
469+
local body = request_to_wolf_server('GET', uri, headers, {}, consumer.auth_conf.ssl_verify)
459470
local userInfo = body.data.userInfo
460471
core.response.exit(200, success_response(nil, {user_info = userInfo}))
461472
end

0 commit comments

Comments
 (0)