608 lines
19 KiB
Lua
608 lines
19 KiB
Lua
local cjson = require "cjson"
|
|
local hybrid_helper = require "spec.hybrid"
|
|
local random_string = require("kong.tools.rand").random_string
|
|
local uuid = require("kong.tools.uuid").uuid
|
|
|
|
|
|
hybrid_helper.run_for_each_deploy({}, function(helpers, strategy, deploy, rpc, rpc_sync)
|
|
describe("Plugin: key-auth (API) [" .. helpers.format_tags() .. "]", function()
|
|
local consumer
|
|
local admin_client
|
|
local bp
|
|
local db
|
|
local route1
|
|
local route2
|
|
|
|
lazy_setup(function()
|
|
bp, db = helpers.get_db_utils(strategy, {
|
|
"routes",
|
|
"services",
|
|
"plugins",
|
|
"consumers",
|
|
"keyauth_credentials",
|
|
})
|
|
|
|
route1 = bp.routes:insert {
|
|
hosts = { "keyauth1.test" },
|
|
}
|
|
|
|
route2 = bp.routes:insert {
|
|
hosts = { "keyauth2.test" },
|
|
}
|
|
|
|
consumer = bp.consumers:insert({
|
|
username = "bob"
|
|
}, { nulls = true })
|
|
|
|
assert(helpers.start_kong({
|
|
database = strategy,
|
|
nginx_conf = "spec/fixtures/custom_nginx.template",
|
|
}))
|
|
|
|
admin_client = helpers.admin_client()
|
|
end)
|
|
lazy_teardown(function()
|
|
if admin_client then
|
|
admin_client:close()
|
|
end
|
|
|
|
helpers.stop_kong()
|
|
end)
|
|
|
|
describe("/consumers/:consumer/key-auth", function()
|
|
describe("POST", function()
|
|
after_each(function()
|
|
db:truncate("keyauth_credentials")
|
|
end)
|
|
it("creates a key-auth credential with key", function()
|
|
local res = assert(admin_client:send {
|
|
method = "POST",
|
|
path = "/consumers/bob/key-auth",
|
|
body = {
|
|
key = "1234"
|
|
},
|
|
headers = {
|
|
["Content-Type"] = "application/json"
|
|
}
|
|
})
|
|
local body = assert.res_status(201, res)
|
|
local json = cjson.decode(body)
|
|
assert.equal(consumer.id, json.consumer.id)
|
|
assert.equal("1234", json.key)
|
|
end)
|
|
it("creates a key-auth auto-generating a unique key", function()
|
|
local res = assert(admin_client:send {
|
|
method = "POST",
|
|
path = "/consumers/bob/key-auth",
|
|
body = {},
|
|
headers = {
|
|
["Content-Type"] = "application/json"
|
|
}
|
|
})
|
|
local body = assert.res_status(201, res)
|
|
local json = cjson.decode(body)
|
|
assert.equal(consumer.id, json.consumer.id)
|
|
assert.is_string(json.key)
|
|
|
|
local first_key = json.key
|
|
db:truncate("keyauth_credentials")
|
|
|
|
local res = assert(admin_client:send {
|
|
method = "POST",
|
|
path = "/consumers/bob/key-auth",
|
|
body = {},
|
|
headers = {
|
|
["Content-Type"] = "application/json"
|
|
}
|
|
})
|
|
local body = assert.res_status(201, res)
|
|
local json = cjson.decode(body)
|
|
assert.equal(consumer.id, json.consumer.id)
|
|
assert.is_string(json.key)
|
|
|
|
assert.not_equal(first_key, json.key)
|
|
end)
|
|
it("creates a key-auth credential with tags", function()
|
|
local res = assert(admin_client:send {
|
|
method = "POST",
|
|
path = "/consumers/bob/key-auth",
|
|
body = {
|
|
key = "keyauth-with-tags",
|
|
tags = { "tag1", "tag2"},
|
|
},
|
|
headers = {
|
|
["Content-Type"] = "application/json"
|
|
}
|
|
})
|
|
local body = assert.res_status(201, res)
|
|
local json = cjson.decode(body)
|
|
assert.equal(consumer.id, json.consumer.id)
|
|
assert.equal("tag1", json.tags[1])
|
|
assert.equal("tag2", json.tags[2])
|
|
end)
|
|
it("creates a key-auth credential with a ttl", function()
|
|
local res = assert(admin_client:send {
|
|
method = "POST",
|
|
path = "/consumers/bob/key-auth",
|
|
body = {
|
|
ttl = 1,
|
|
},
|
|
headers = {
|
|
["Content-Type"] = "application/json"
|
|
}
|
|
})
|
|
local body = assert.res_status(201, res)
|
|
local json = cjson.decode(body)
|
|
assert.equal(consumer.id, json.consumer.id)
|
|
assert.is_string(json.key)
|
|
|
|
ngx.sleep(3)
|
|
|
|
local id = json.id
|
|
local res = assert(admin_client:send {
|
|
method = "GET",
|
|
path = "/consumers/bob/key-auth/" .. id,
|
|
})
|
|
assert.res_status(404, res)
|
|
end)
|
|
end)
|
|
|
|
describe("GET", function()
|
|
lazy_setup(function()
|
|
for i = 1, 3 do
|
|
assert(bp.keyauth_credentials:insert {
|
|
consumer = { id = consumer.id }
|
|
})
|
|
end
|
|
end)
|
|
lazy_teardown(function()
|
|
db:truncate("keyauth_credentials")
|
|
end)
|
|
it("retrieves the first page", function()
|
|
local res = assert(admin_client:send {
|
|
method = "GET",
|
|
path = "/consumers/bob/key-auth"
|
|
})
|
|
local body = assert.res_status(200, res)
|
|
local json = cjson.decode(body)
|
|
assert.is_table(json.data)
|
|
assert.equal(3, #json.data)
|
|
end)
|
|
end)
|
|
|
|
describe("GET #ttl", function()
|
|
lazy_setup(function()
|
|
for i = 1, 3 do
|
|
bp.keyauth_credentials:insert({
|
|
consumer = { id = consumer.id },
|
|
}, { ttl = 10 })
|
|
end
|
|
end)
|
|
lazy_teardown(function()
|
|
db:truncate("keyauth_credentials")
|
|
end)
|
|
it("entries contain ttl when specified", function()
|
|
local res = assert(admin_client:send {
|
|
method = "GET",
|
|
path = "/consumers/bob/key-auth"
|
|
})
|
|
local body = assert.res_status(200, res)
|
|
local json = cjson.decode(body)
|
|
assert.is_table(json.data)
|
|
for _, credential in ipairs(json.data) do
|
|
assert.not_nil(credential.ttl)
|
|
end
|
|
end)
|
|
end)
|
|
end)
|
|
|
|
describe("/consumers/:consumer/key-auth/:id", function()
|
|
local credential
|
|
before_each(function()
|
|
db:truncate("keyauth_credentials")
|
|
credential = bp.keyauth_credentials:insert {
|
|
consumer = { id = consumer.id },
|
|
}
|
|
end)
|
|
describe("GET", function()
|
|
it("retrieves key-auth credential by id", function()
|
|
local res = assert(admin_client:send {
|
|
method = "GET",
|
|
path = "/consumers/bob/key-auth/" .. credential.id
|
|
})
|
|
local body = assert.res_status(200, res)
|
|
local json = cjson.decode(body)
|
|
assert.equal(credential.id, json.id)
|
|
end)
|
|
it("retrieves key-auth credential by key", function()
|
|
local res = assert(admin_client:send {
|
|
method = "GET",
|
|
path = "/consumers/bob/key-auth/" .. credential.key
|
|
})
|
|
local body = assert.res_status(200, res)
|
|
local json = cjson.decode(body)
|
|
assert.equal(credential.id, json.id)
|
|
end)
|
|
it("retrieves credential by id only if the credential belongs to the specified consumer", function()
|
|
assert(bp.consumers:insert {
|
|
username = "alice"
|
|
})
|
|
|
|
local res = assert(admin_client:send {
|
|
method = "GET",
|
|
path = "/consumers/bob/key-auth/" .. credential.id
|
|
})
|
|
assert.res_status(200, res)
|
|
|
|
res = assert(admin_client:send {
|
|
method = "GET",
|
|
path = "/consumers/alice/key-auth/" .. credential.id
|
|
})
|
|
assert.res_status(404, res)
|
|
end)
|
|
it("key-auth credential contains #ttl", function()
|
|
local credential = bp.keyauth_credentials:insert({
|
|
consumer = { id = consumer.id },
|
|
}, { ttl = 10 })
|
|
local res = assert(admin_client:send {
|
|
method = "GET",
|
|
path = "/consumers/bob/key-auth/" .. credential.id
|
|
})
|
|
local body = assert.res_status(200, res)
|
|
local json = cjson.decode(body)
|
|
assert.equal(credential.id, json.id)
|
|
assert.not_nil(json.ttl)
|
|
end)
|
|
end)
|
|
|
|
describe("PUT", function()
|
|
after_each(function()
|
|
db:truncate("keyauth_credentials")
|
|
end)
|
|
it("creates a key-auth credential with key", function()
|
|
local res = assert(admin_client:send {
|
|
method = "PUT",
|
|
path = "/consumers/bob/key-auth/1234",
|
|
body = {},
|
|
headers = {
|
|
["Content-Type"] = "application/json"
|
|
}
|
|
})
|
|
local body = assert.res_status(200, res)
|
|
local json = cjson.decode(body)
|
|
assert.equal(consumer.id, json.consumer.id)
|
|
assert.equal("1234", json.key)
|
|
end)
|
|
it("creates a key-auth credential auto-generating the key", function()
|
|
local res = assert(admin_client:send {
|
|
method = "PUT",
|
|
path = "/consumers/bob/key-auth/c16bbff7-5d0d-4a28-8127-1ee581898f11",
|
|
body = {},
|
|
headers = {
|
|
["Content-Type"] = "application/json"
|
|
}
|
|
})
|
|
local body = assert.res_status(200, res)
|
|
local json = cjson.decode(body)
|
|
assert.equal(consumer.id, json.consumer.id)
|
|
assert.is_string(json.key)
|
|
end)
|
|
end)
|
|
|
|
describe("PATCH", function()
|
|
it("updates a credential by id", function()
|
|
local res = assert(admin_client:send {
|
|
method = "PATCH",
|
|
path = "/consumers/bob/key-auth/" .. credential.id,
|
|
body = { key = "4321" },
|
|
headers = {
|
|
["Content-Type"] = "application/json"
|
|
}
|
|
})
|
|
local body = assert.res_status(200, res)
|
|
local json = cjson.decode(body)
|
|
assert.equal("4321", json.key)
|
|
end)
|
|
it("updates a credential by key", function()
|
|
local res = assert(admin_client:send {
|
|
method = "PATCH",
|
|
path = "/consumers/bob/key-auth/" .. credential.key,
|
|
body = { key = "4321UPD" },
|
|
headers = {
|
|
["Content-Type"] = "application/json"
|
|
}
|
|
})
|
|
local body = assert.res_status(200, res)
|
|
local json = cjson.decode(body)
|
|
assert.equal("4321UPD", json.key)
|
|
end)
|
|
describe("errors", function()
|
|
it("handles invalid input", function()
|
|
local res = assert(admin_client:send {
|
|
method = "PATCH",
|
|
path = "/consumers/bob/key-auth/" .. credential.id,
|
|
body = { key = 123 },
|
|
headers = {
|
|
["Content-Type"] = "application/json"
|
|
}
|
|
})
|
|
local body = assert.res_status(400, res)
|
|
local json = cjson.decode(body)
|
|
assert.same({ key = "expected a string" }, json.fields)
|
|
end)
|
|
end)
|
|
end)
|
|
|
|
describe("DELETE", function()
|
|
it("deletes a credential", function()
|
|
local res = assert(admin_client:send {
|
|
method = "DELETE",
|
|
path = "/consumers/bob/key-auth/" .. credential.id,
|
|
})
|
|
assert.res_status(204, res)
|
|
end)
|
|
describe("errors", function()
|
|
it("returns 400 on invalid input", function()
|
|
local res = assert(admin_client:send {
|
|
method = "DELETE",
|
|
path = "/consumers/bob/key-auth/blah"
|
|
})
|
|
assert.res_status(404, res)
|
|
end)
|
|
it("returns 404 if not found", function()
|
|
local res = assert(admin_client:send {
|
|
method = "DELETE",
|
|
path = "/consumers/bob/key-auth/00000000-0000-0000-0000-000000000000"
|
|
})
|
|
assert.res_status(404, res)
|
|
end)
|
|
end)
|
|
end)
|
|
end)
|
|
describe("/plugins for route", function()
|
|
it("fails with invalid key_names", function()
|
|
local key_name = "hello\\world"
|
|
local res = assert(admin_client:send {
|
|
method = "POST",
|
|
path = "/plugins",
|
|
body = {
|
|
name = "key-auth",
|
|
route = { id = route1.id },
|
|
config = {
|
|
key_names = {key_name},
|
|
},
|
|
},
|
|
headers = {
|
|
["Content-Type"] = "application/json"
|
|
}
|
|
})
|
|
assert.response(res).has.status(400)
|
|
local body = assert.response(res).has.jsonbody()
|
|
assert.equal("bad header name 'hello\\world', allowed characters are A-Z, a-z, 0-9, '_', and '-'",
|
|
body.fields.config.key_names[1])
|
|
end)
|
|
it("succeeds with valid key_names", function()
|
|
local key_name = "hello-world"
|
|
local res = assert(admin_client:send {
|
|
method = "POST",
|
|
path = "/plugins",
|
|
body = {
|
|
route = { id = route2.id },
|
|
name = "key-auth",
|
|
config = {
|
|
key_names = {key_name},
|
|
},
|
|
},
|
|
headers = {
|
|
["Content-Type"] = "application/json"
|
|
}
|
|
})
|
|
assert.response(res).has.status(201)
|
|
local body = assert.response(res).has.jsonbody()
|
|
assert.equal(key_name, body.config.key_names[1])
|
|
end)
|
|
end)
|
|
describe("/key-auths", function()
|
|
local consumer2
|
|
|
|
describe("GET", function()
|
|
lazy_setup(function()
|
|
db:truncate("keyauth_credentials")
|
|
|
|
for i = 1, 3 do
|
|
bp.keyauth_credentials:insert {
|
|
consumer = { id = consumer.id },
|
|
}
|
|
end
|
|
|
|
consumer2 = bp.consumers:insert {
|
|
username = "bob-the-buidler",
|
|
}
|
|
|
|
for i = 1, 3 do
|
|
bp.keyauth_credentials:insert {
|
|
consumer = { id = consumer2.id },
|
|
}
|
|
end
|
|
end)
|
|
|
|
it("retrieves all the key-auths with trailing slash", function()
|
|
local res = assert(admin_client:send {
|
|
method = "GET",
|
|
path = "/key-auths/",
|
|
})
|
|
local body = assert.res_status(200, res)
|
|
local json = cjson.decode(body)
|
|
assert.is_table(json.data)
|
|
assert.equal(6, #json.data)
|
|
end)
|
|
it("retrieves all the key-auths without trailing slash", function()
|
|
local res = assert(admin_client:send {
|
|
method = "GET",
|
|
path = "/key-auths",
|
|
})
|
|
local body = assert.res_status(200, res)
|
|
local json = cjson.decode(body)
|
|
assert.is_table(json.data)
|
|
assert.equal(6, #json.data)
|
|
end)
|
|
it("paginates through the key-auths", function()
|
|
local res = assert(admin_client:send {
|
|
method = "GET",
|
|
path = "/key-auths?size=3",
|
|
})
|
|
local body = assert.res_status(200, res)
|
|
local json_1 = cjson.decode(body)
|
|
assert.is_table(json_1.data)
|
|
assert.equal(3, #json_1.data)
|
|
|
|
res = assert(admin_client:send {
|
|
method = "GET",
|
|
path = "/key-auths",
|
|
query = {
|
|
size = 3,
|
|
offset = json_1.offset,
|
|
}
|
|
})
|
|
body = assert.res_status(200, res)
|
|
local json_2 = cjson.decode(body)
|
|
assert.is_table(json_2.data)
|
|
assert.equal(3, #json_2.data)
|
|
|
|
assert.not_same(json_1.data, json_2.data)
|
|
assert.is_nil(json_2.offset) -- last page
|
|
end)
|
|
end)
|
|
|
|
describe("POST", function()
|
|
lazy_setup(function()
|
|
db:truncate("keyauth_credentials")
|
|
end)
|
|
|
|
it("does not create key-auth credential when missing consumer", function()
|
|
local res = assert(admin_client:send {
|
|
method = "POST",
|
|
path = "/key-auths",
|
|
body = {
|
|
key = "1234",
|
|
},
|
|
headers = {
|
|
["Content-Type"] = "application/json"
|
|
}
|
|
})
|
|
local body = assert.res_status(400, res)
|
|
local json = cjson.decode(body)
|
|
assert.same("schema violation (consumer: required field missing)", json.message)
|
|
end)
|
|
|
|
it("creates key-auth credential", function()
|
|
local res = assert(admin_client:send {
|
|
method = "POST",
|
|
path = "/key-auths",
|
|
body = {
|
|
key = "1234",
|
|
consumer = {
|
|
id = consumer.id
|
|
}
|
|
},
|
|
headers = {
|
|
["Content-Type"] = "application/json"
|
|
}
|
|
})
|
|
local body = assert.res_status(201, res)
|
|
local json = cjson.decode(body)
|
|
assert.equal("1234", json.key)
|
|
end)
|
|
end)
|
|
end)
|
|
|
|
describe("/key-auths/:credential_key_or_id", function()
|
|
describe("PUT", function()
|
|
lazy_setup(function()
|
|
db:truncate("keyauth_credentials")
|
|
end)
|
|
|
|
it("does not create key-auth credential when missing consumer", function()
|
|
local res = assert(admin_client:send {
|
|
method = "PUT",
|
|
path = "/key-auths/1234",
|
|
body = { },
|
|
headers = {
|
|
["Content-Type"] = "application/json"
|
|
}
|
|
})
|
|
local body = assert.res_status(400, res)
|
|
local json = cjson.decode(body)
|
|
assert.same("schema violation (consumer: required field missing)", json.message)
|
|
end)
|
|
|
|
it("creates key-auth credential", function()
|
|
local res = assert(admin_client:send {
|
|
method = "PUT",
|
|
path = "/key-auths/1234",
|
|
body = {
|
|
consumer = {
|
|
id = consumer.id
|
|
}
|
|
},
|
|
headers = {
|
|
["Content-Type"] = "application/json"
|
|
}
|
|
})
|
|
local body = assert.res_status(200, res)
|
|
local json = cjson.decode(body)
|
|
assert.equal("1234", json.key)
|
|
end)
|
|
end)
|
|
end)
|
|
|
|
describe("/key-auths/:credential_key_or_id/consumer", function()
|
|
describe("GET", function()
|
|
local credential
|
|
|
|
lazy_setup(function()
|
|
db:truncate("keyauth_credentials")
|
|
credential = bp.keyauth_credentials:insert {
|
|
consumer = { id = consumer.id },
|
|
}
|
|
end)
|
|
|
|
it("retrieve Consumer from a credential's id", function()
|
|
local res = assert(admin_client:send {
|
|
method = "GET",
|
|
path = "/key-auths/" .. credential.id .. "/consumer"
|
|
})
|
|
local body = assert.res_status(200, res)
|
|
local json = cjson.decode(body)
|
|
assert.same(consumer, json)
|
|
end)
|
|
it("retrieve a Consumer from a credential's key", function()
|
|
local res = assert(admin_client:send {
|
|
method = "GET",
|
|
path = "/key-auths/" .. credential.key .. "/consumer"
|
|
})
|
|
local body = assert.res_status(200, res)
|
|
local json = cjson.decode(body)
|
|
assert.same(consumer, json)
|
|
end)
|
|
it("returns 404 for a random non-existing id", function()
|
|
local res = assert(admin_client:send {
|
|
method = "GET",
|
|
path = "/key-auths/" .. uuid() .. "/consumer"
|
|
})
|
|
assert.res_status(404, res)
|
|
end)
|
|
it("returns 404 for a random non-existing key", function()
|
|
local res = assert(admin_client:send {
|
|
method = "GET",
|
|
path = "/key-auths/" .. random_string() .. "/consumer"
|
|
})
|
|
assert.res_status(404, res)
|
|
end)
|
|
end)
|
|
|
|
|
|
end)
|
|
end)
|
|
end)
|