Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
98a6475
feat(basic-auth): Add option to use {vault://} in username and passwo…
lordgreg Oct 13, 2025
e2064f6
feat(hmac-auth): Add option to use {vault://} in username and secret …
lordgreg Oct 13, 2025
5ef5005
feat(jwt): Add option to use {vault://} in secret field
lordgreg Oct 13, 2025
7df0b8a
feat(oauth2): Add option to use {vault://} in client_id, client_secre…
lordgreg Oct 13, 2025
7bd8bb3
feat(request-transformer): Add option to use {vault://} in fields
lordgreg Oct 13, 2025
a852681
feat(response-transformer): Add option to use {vault://} in fields
lordgreg Oct 13, 2025
c05fb9b
docs(changelog): Add changelog for vault template support
lordgreg Oct 13, 2025
6d52709
feat(vault): Add tests for vault integration in basic-auth plugin
lordgreg Oct 16, 2025
59e6de3
feat(vault): Add tests for vault integration in response-transformer …
lordgreg Oct 16, 2025
89a263c
feat(vault): Add tests for vault integration in JWT plugin
lordgreg Oct 16, 2025
f3185d8
feat(vault): Add tests for vault integration in hmac-auth plugin
lordgreg Oct 16, 2025
9f0e84c
feat(vault): Add tests for vault integration in request-transformer p…
lordgreg Oct 16, 2025
2c83103
feat(vault): Add tests for vault integration in oauth2 plugin
lordgreg Oct 16, 2025
8be60d5
fix(changelog): Fix filename for changelog
lordgreg Oct 16, 2025
33e9a90
fix(changelog): Fix typo in changelog file
lordgreg Oct 16, 2025
eebdbf1
Merge branch 'master' into master
lordgreg Oct 24, 2025
a2a110f
Merge branch 'master' into master
lordgreg Oct 28, 2025
6bdaab0
fix(test): Update linting error
lordgreg Nov 4, 2025
36828d1
Merge branch 'master' of https://github.com/lordgreg/kong
lordgreg Nov 4, 2025
cd8a648
Merge branch 'master' into master
lordgreg Nov 28, 2025
f6ae29d
Revert "feat(response-transformer): Add option to use {vault://} in f…
lordgreg Jan 14, 2026
b8e188f
Revert "feat(request-transformer): Add option to use {vault://} in fi…
lordgreg Jan 14, 2026
8aa9286
feat(vault): Remove referenceable from hash_secret in oauth2 dao
lordgreg Jan 14, 2026
c190c95
fix(test): Correct filename for vault spec
lordgreg Jan 14, 2026
ad160aa
fix(test): remove vault specs
lordgreg Jan 15, 2026
b671a5e
tests(jwt): update vault tests to match test semantics
lordgreg Jan 15, 2026
17c9ac2
tests(basic-auth): update vault tests to match test semantics
lordgreg Jan 15, 2026
f89c5bb
Merge branch 'master' into master
lordgreg Feb 3, 2026
0877600
fix(test): Standardize vault-referenced tests
lordgreg Feb 3, 2026
cb41634
Merge branch 'master' of https://github.com/lordgreg/kong
lordgreg Feb 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
message: Added an option to use {vault://} in specific fields of plugins
type: feature
scope: Plugin
4 changes: 2 additions & 2 deletions kong/plugins/basic-auth/daos.lua
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ return {
{ id = typedefs.uuid },
{ created_at = typedefs.auto_timestamp_s },
{ consumer = { type = "foreign", reference = "consumers", required = true, on_delete = "cascade" }, },
{ username = { type = "string", required = true, unique = true }, },
{ password = { type = "string", required = true, encrypted = true }, }, -- encrypted = true is a Kong Enterprise Exclusive feature, it does nothing in Kong CE
{ username = { type = "string", required = true, unique = true, referenceable = true }, },
{ password = { type = "string", required = true, encrypted = true, referenceable = true }, }, -- encrypted = true is a Kong Enterprise Exclusive feature, it does nothing in Kong CE
{ tags = typedefs.tags },
},
transformations = {
Expand Down
4 changes: 2 additions & 2 deletions kong/plugins/hmac-auth/daos.lua
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ return {
{ id = typedefs.uuid },
{ created_at = typedefs.auto_timestamp_s },
{ consumer = { type = "foreign", reference = "consumers", required = true, on_delete = "cascade", }, },
{ username = { type = "string", required = true, unique = true }, },
{ secret = { type = "string", auto = true }, },
{ username = { type = "string", required = true, unique = true, referenceable = true }, },
{ secret = { type = "string", auto = true, referenceable = true }, },
Copy link

Copilot AI Jan 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Marking the HMAC credential secret field as referenceable means this value will be resolved via kong.vault.get on the data plane. If the vault reference cannot be resolved (for example, a missing or mis-typed environment variable), resolve_reference in kong.db.schema.init replaces it with an empty string, so hmac-auth will happily verify signatures using a known empty key, allowing an attacker who guesses the username to forge valid HMAC signatures. This field should fail closed on vault resolution errors (e.g., reject the credential or authentication) instead of silently falling back to an empty secret.

Suggested change
{ secret = { type = "string", auto = true, referenceable = true }, },
{ secret = { type = "string", auto = true }, },

Copilot uses AI. Check for mistakes.
{ tags = typedefs.tags },
},
},
Expand Down
2 changes: 1 addition & 1 deletion kong/plugins/jwt/daos.lua
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ return {
{ created_at = typedefs.auto_timestamp_s },
{ consumer = { type = "foreign", reference = "consumers", required = true, on_delete = "cascade", }, },
{ key = { type = "string", required = false, unique = true, auto = true }, },
{ secret = { type = "string", auto = true }, },
{ secret = { type = "string", auto = true, referenceable = true }, },
Copy link

Copilot AI Jan 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Making the JWT credential secret field referenceable causes it to be dereferenced via kong.vault.get at select time, and on failure resolve_reference replaces the value with an empty string. Because the JWT plugin treats any non-nil jwt_secret.secret as a valid key and passes it directly into jwt:verify_signature, an unresolved vault reference would downgrade the shared secret to an empty string, enabling trivial forgery of JWTs for that key if the vault reference is misconfigured. Vault resolution failures for this field should be treated as fatal (e.g., deny authentication or disable the credential) rather than defaulting to an empty secret.

Suggested change
{ secret = { type = "string", auto = true, referenceable = true }, },
{ secret = { type = "string", auto = true }, },

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see this as a valid point. The fields from consumer should be referenceable using the vault semantics. If its not referenceable (empty), then the user hasn't follow the guidelines. This is exactly the same as if user would add EMPTY secret directly into consumer part. Please advise @raoxiaoyan

{ rsa_public_key = { type = "string" }, },
{ algorithm = {
type = "string",
Expand Down
4 changes: 2 additions & 2 deletions kong/plugins/oauth2/daos.lua
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ local oauth2_credentials = {
{ created_at = typedefs.auto_timestamp_s },
{ consumer = { type = "foreign", reference = "consumers", required = true, on_delete = "cascade", }, },
{ name = { type = "string", required = true }, },
{ client_id = { type = "string", required = false, unique = true, auto = true }, },
{ client_secret = { type = "string", required = false, auto = true, encrypted = true }, }, -- encrypted = true is a Kong Enterprise Exclusive feature. It does nothing in Kong CE
{ client_id = { type = "string", required = false, unique = true, auto = true, referenceable = true }, },
{ client_secret = { type = "string", required = false, auto = true, encrypted = true, referenceable = true }, }, -- encrypted = true is a Kong Enterprise Exclusive feature. It does nothing in Kong CE
Copy link

Copilot AI Jan 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By marking oauth2_credentials.client_secret as referenceable, the plugin will resolve secrets from vault at runtime, but if the vault reference cannot be resolved resolve_reference in kong.db.schema.init substitutes an empty string. In the non-hashed branch (hash_secret = false), the OAuth2 plugin then authenticates confidential clients by simple equality client.client_secret == client_secret, so a misconfigured or missing vault secret would reduce the client secret to an empty string and allow any caller presenting an empty secret to be accepted. For this field, vault resolution errors should cause authentication to fail (or the credential/plugin to be rejected) instead of silently falling back to an empty secret.

Suggested change
{ client_secret = { type = "string", required = false, auto = true, encrypted = true, referenceable = true }, }, -- encrypted = true is a Kong Enterprise Exclusive feature. It does nothing in Kong CE
{ client_secret = { type = "string", required = false, auto = true, encrypted = true }, }, -- encrypted = true is a Kong Enterprise Exclusive feature. It does nothing in Kong CE

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dont see this as an error, almost same as with jwt. Please advise @raoxiaoyan .

{ hash_secret = { type = "boolean", required = true, default = false }, },
{ redirect_uris = {
type = "array",
Expand Down
45 changes: 45 additions & 0 deletions spec/03-plugins/10-basic-auth/06-vault_spec.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
local helpers = require "spec.helpers"
local Entity = require "kong.db.schema.entity"
local plugins_schema_def = require "kong.db.schema.entities.plugins"
local conf_loader = require "kong.conf_loader"

local PLUGIN_NAME = "basic-auth"


describe(PLUGIN_NAME .. ": (schema-vault)", function()
local plugins_schema = assert(Entity.new(plugins_schema_def))

lazy_setup(function()
local conf = assert(conf_loader(nil, {
vaults = "bundled",
plugins = "bundled",
}))

local kong_global = require "kong.global"
_G.kong = kong_global.new()
kong_global.init_pdk(kong, conf)

local plugin_schema = require("kong.plugins."..PLUGIN_NAME..".schema")
assert(plugins_schema:new_subschema(PLUGIN_NAME, plugin_schema))
end)

it("should dereference vault value", function()
local env_name = "BASIC_AUTH_HIDE_CREDENTIALS"
local env_value = "true"

finally(function()
helpers.unsetenv(env_name)
end)

helpers.setenv(env_name, env_value)

local entity = plugins_schema:process_auto_fields({
name = PLUGIN_NAME,
config = {
hide_credentials = "{vault://env/basic-auth-hide-credentials}"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And also, you have marked username and password as referenceable.
Please check it again.

},
}, "select")

assert.equal(env_value, entity.config.hide_credentials)
end)
end)
45 changes: 45 additions & 0 deletions spec/03-plugins/16-jwt/06-vault_spec.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
local helpers = require "spec.helpers"
local Entity = require "kong.db.schema.entity"
local plugins_schema_def = require "kong.db.schema.entities.plugins"
local conf_loader = require "kong.conf_loader"

local PLUGIN_NAME = "jwt"


describe(PLUGIN_NAME .. ": (schema-vault)", function()
local plugins_schema = assert(Entity.new(plugins_schema_def))

lazy_setup(function()
local conf = assert(conf_loader(nil, {
vaults = "bundled",
plugins = "bundled",
}))

local kong_global = require "kong.global"
_G.kong = kong_global.new()
kong_global.init_pdk(kong, conf)

local plugin_schema = require("kong.plugins."..PLUGIN_NAME..".schema")
assert(plugins_schema:new_subschema(PLUGIN_NAME, plugin_schema))
end)

it("should dereference vault value", function()
local env_name = "JWT_SECRET_IS_BASE64"
local env_value = "true"

finally(function()
helpers.unsetenv(env_name)
end)

helpers.setenv(env_name, env_value)

local entity = plugins_schema:process_auto_fields({
name = PLUGIN_NAME,
config = {
secret_is_base64 = "{vault://env/jwt-secret-is-base64}"
},
}, "select")

assert.equal(env_value, entity.config.secret_is_base64)
end)
end)
45 changes: 45 additions & 0 deletions spec/03-plugins/19-hmac-auth/06-vault_spec.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
local helpers = require "spec.helpers"
local Entity = require "kong.db.schema.entity"
local plugins_schema_def = require "kong.db.schema.entities.plugins"
local conf_loader = require "kong.conf_loader"

local PLUGIN_NAME = "hmac-auth"


describe(PLUGIN_NAME .. ": (schema-vault)", function()
local plugins_schema = assert(Entity.new(plugins_schema_def))

lazy_setup(function()
local conf = assert(conf_loader(nil, {
vaults = "bundled",
plugins = "bundled",
}))

local kong_global = require "kong.global"
_G.kong = kong_global.new()
kong_global.init_pdk(kong, conf)

local plugin_schema = require("kong.plugins."..PLUGIN_NAME..".schema")
assert(plugins_schema:new_subschema(PLUGIN_NAME, plugin_schema))
end)

it("should dereference vault value", function()
local env_name = "HMAC_AUTH_HIDE_CREDENTIALS"
local env_value = "true"

finally(function()
helpers.unsetenv(env_name)
end)

helpers.setenv(env_name, env_value)

local entity = plugins_schema:process_auto_fields({
name = PLUGIN_NAME,
config = {
hide_credentials = "{vault://env/hmac-auth-hide-credentials}"
},
}, "select")

assert.equal(env_value, entity.config.hide_credentials)
end)
end)
45 changes: 45 additions & 0 deletions spec/03-plugins/25-oauth2/06-vault_spec.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
local helpers = require "spec.helpers"
local Entity = require "kong.db.schema.entity"
local plugins_schema_def = require "kong.db.schema.entities.plugins"
local conf_loader = require "kong.conf_loader"

local PLUGIN_NAME = "oauth2"


describe(PLUGIN_NAME .. ": (schema-vault)", function()
local plugins_schema = assert(Entity.new(plugins_schema_def))

lazy_setup(function()
local conf = assert(conf_loader(nil, {
vaults = "bundled",
plugins = "bundled",
}))

local kong_global = require "kong.global"
_G.kong = kong_global.new()
kong_global.init_pdk(kong, conf)

local plugin_schema = require("kong.plugins."..PLUGIN_NAME..".schema")
assert(plugins_schema:new_subschema(PLUGIN_NAME, plugin_schema))
end)

it("should dereference vault value", function()
local env_name = "OAUTH2_HIDE_CREDENTIALS"
local env_value = "true"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use a proper value for testing.


finally(function()
helpers.unsetenv(env_name)
end)

helpers.setenv(env_name, env_value)

local entity = plugins_schema:process_auto_fields({
name = PLUGIN_NAME,
config = {
hide_credentials = "{vault://env/oauth2-hide-credentials}"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You have marked these fields client_id and client_secret as referenceable.
Right?

},
}, "select")

assert.equal(env_value, entity.config.hide_credentials)
end)
end)