1992 lines
76 KiB
Lua
1992 lines
76 KiB
Lua
local cjson = require "cjson"
|
|
local openssl_mac = require "resty.openssl.mac"
|
|
local helpers = require "spec.helpers"
|
|
local uuid = require "kong.tools.uuid"
|
|
local resty_sha256 = require "resty.sha256"
|
|
|
|
local fmt = string.format
|
|
|
|
|
|
local hmac_sha1_binary = function(secret, data)
|
|
return openssl_mac.new(secret, "HMAC", nil, "sha1"):final(data)
|
|
end
|
|
|
|
|
|
local SIGNATURE_NOT_VALID = "HMAC signature cannot be verified"
|
|
|
|
|
|
for _, strategy in helpers.each_strategy() do
|
|
describe("Plugin: hmac-auth (access) [#" .. strategy .. "]", function()
|
|
local proxy_client
|
|
local consumer
|
|
local credential
|
|
local nonexisting_anonymous = uuid.uuid() -- a nonexisting consumer id
|
|
|
|
lazy_setup(function()
|
|
local bp = helpers.get_db_utils(strategy, {
|
|
"routes",
|
|
"services",
|
|
"consumers",
|
|
"plugins",
|
|
"hmacauth_credentials",
|
|
})
|
|
|
|
local route1 = bp.routes:insert {
|
|
hosts = { "hmacauth.test" },
|
|
}
|
|
|
|
local route_grpc = assert(bp.routes:insert {
|
|
protocols = { "grpc" },
|
|
paths = { "/hello.HelloService/" },
|
|
service = assert(bp.services:insert {
|
|
name = "grpc",
|
|
url = helpers.grpcbin_url,
|
|
}),
|
|
})
|
|
|
|
bp.plugins:insert {
|
|
name = "hmac-auth",
|
|
route = { id = route1.id },
|
|
config = {
|
|
clock_skew = 3000,
|
|
realm = "test-realm"
|
|
}
|
|
}
|
|
|
|
bp.plugins:insert {
|
|
name = "hmac-auth",
|
|
route = { id = route_grpc.id },
|
|
config = {
|
|
clock_skew = 3000
|
|
}
|
|
}
|
|
|
|
consumer = bp.consumers:insert {
|
|
username = "bob",
|
|
custom_id = "1234"
|
|
}
|
|
|
|
credential = bp.hmacauth_credentials:insert {
|
|
username = "bob",
|
|
secret = "secret",
|
|
consumer = { id = consumer.id },
|
|
}
|
|
|
|
local anonymous_user = bp.consumers:insert {
|
|
username = "no-body"
|
|
}
|
|
|
|
local route2 = bp.routes:insert {
|
|
hosts = { "hmacauth2.test" },
|
|
}
|
|
|
|
bp.plugins:insert {
|
|
name = "hmac-auth",
|
|
route = { id = route2.id },
|
|
config = {
|
|
anonymous = anonymous_user.id,
|
|
clock_skew = 3000
|
|
}
|
|
}
|
|
|
|
local route3 = bp.routes:insert {
|
|
hosts = { "hmacauth3.test" },
|
|
}
|
|
|
|
bp.plugins:insert {
|
|
name = "hmac-auth",
|
|
route = { id = route3.id },
|
|
config = {
|
|
anonymous = nonexisting_anonymous, -- a non existing consumer id
|
|
clock_skew = 3000
|
|
}
|
|
}
|
|
|
|
local route4 = bp.routes:insert {
|
|
hosts = { "hmacauth4.test" },
|
|
}
|
|
|
|
bp.plugins:insert {
|
|
name = "hmac-auth",
|
|
route = { id = route4.id },
|
|
config = {
|
|
clock_skew = 3000,
|
|
validate_request_body = true
|
|
}
|
|
}
|
|
|
|
local route5 = bp.routes:insert {
|
|
hosts = { "hmacauth5.test" },
|
|
}
|
|
|
|
bp.plugins:insert {
|
|
name = "hmac-auth",
|
|
route = { id = route5.id },
|
|
config = {
|
|
clock_skew = 3000,
|
|
enforce_headers = {"date", "request-line"},
|
|
validate_request_body = true
|
|
}
|
|
}
|
|
|
|
local route6 = bp.routes:insert {
|
|
hosts = { "hmacauth6.test" },
|
|
}
|
|
|
|
bp.plugins:insert {
|
|
name = "hmac-auth",
|
|
route = { id = route6.id },
|
|
config = {
|
|
clock_skew = 3000,
|
|
enforce_headers = {"date", "request-line"},
|
|
algorithms = {"hmac-sha1", "hmac-sha256"},
|
|
validate_request_body = true
|
|
}
|
|
}
|
|
|
|
local route7 = bp.routes:insert {
|
|
hosts = { "hmacauth7.test" },
|
|
}
|
|
|
|
bp.plugins:insert {
|
|
name = "hmac-auth",
|
|
route = { id = route7.id },
|
|
config = {
|
|
anonymous = anonymous_user.username,
|
|
clock_skew = 3000
|
|
}
|
|
}
|
|
|
|
assert(helpers.start_kong {
|
|
database = strategy,
|
|
real_ip_header = "X-Forwarded-For",
|
|
real_ip_recursive = "on",
|
|
trusted_ips = "0.0.0.0/0, ::/0",
|
|
nginx_conf = "spec/fixtures/custom_nginx.template",
|
|
})
|
|
|
|
proxy_client = helpers.proxy_client()
|
|
end)
|
|
|
|
lazy_teardown(function()
|
|
if proxy_client then
|
|
proxy_client:close()
|
|
end
|
|
|
|
helpers.stop_kong()
|
|
end)
|
|
|
|
describe("HMAC Authentication", function()
|
|
describe("when realm is set", function ()
|
|
it("should not be authorized when the hmac credentials are missing", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local res = assert(proxy_client:send {
|
|
method = "POST",
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth.test",
|
|
date = date
|
|
}
|
|
})
|
|
local body = assert.res_status(401, res)
|
|
assert.equal('hmac realm="test-realm"', res.headers["WWW-Authenticate"])
|
|
body = cjson.decode(body)
|
|
assert.equal("Unauthorized", body.message)
|
|
end)
|
|
end)
|
|
|
|
describe("when realm is not set", function ()
|
|
it("should return a 401 with an invalid authorization header", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth6.test",
|
|
date = date,
|
|
["proxy-authorization"] = "this is no hmac token at all is it?",
|
|
},
|
|
})
|
|
assert.res_status(401, res)
|
|
assert.equal('hmac', res.headers["WWW-Authenticate"])
|
|
end)
|
|
end)
|
|
|
|
it("rejects gRPC call without credentials", function()
|
|
local ok, err = helpers.proxy_client_grpc(){
|
|
service = "hello.HelloService.SayHello",
|
|
opts = {},
|
|
}
|
|
assert.falsy(ok)
|
|
assert.matches("Code: Unauthenticated", err)
|
|
end)
|
|
|
|
it("should not be authorized when the HMAC signature is wrong", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local res = assert(proxy_client:send {
|
|
method = "POST",
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth.test",
|
|
date = date,
|
|
authorization = "asd"
|
|
}
|
|
})
|
|
local body = assert.res_status(401, res)
|
|
assert.equal('hmac realm="test-realm"', res.headers["WWW-Authenticate"])
|
|
body = cjson.decode(body)
|
|
assert.equal(SIGNATURE_NOT_VALID, body.message)
|
|
end)
|
|
|
|
it("should not be authorized when the HMAC signature is not properly base64 encoded", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local hmacAuth = [["hmac username="bob",algorithm="hmac-sha1",]]
|
|
.. [[headers="date",signature="not really a base64 encoded value!!!"]]
|
|
local res = assert(proxy_client:send {
|
|
method = "POST",
|
|
headers = {
|
|
["HOST"] = "hmacauth.test",
|
|
date = date,
|
|
authorization = hmacAuth
|
|
}
|
|
})
|
|
local body = assert.res_status(401, res)
|
|
assert.equal('hmac realm="test-realm"', res.headers["WWW-Authenticate"])
|
|
body = cjson.decode(body)
|
|
assert.equal("HMAC signature does not match", body.message)
|
|
end)
|
|
|
|
it("should not be authorized when date header is missing", function()
|
|
local res = assert(proxy_client:send {
|
|
method = "POST",
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth.test",
|
|
authorization = "asd"
|
|
}
|
|
})
|
|
local body = assert.res_status(401, res)
|
|
assert.equal('hmac realm="test-realm"', res.headers["WWW-Authenticate"])
|
|
body = cjson.decode(body)
|
|
assert.equal([[HMAC signature cannot be verified, ]]
|
|
.. [[a valid date or x-date header is]]
|
|
.. [[ required for HMAC Authentication]], body.message)
|
|
end)
|
|
|
|
it("should not be authorized with signature is wrong in proxy-authorization", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local res = assert(proxy_client:send {
|
|
method = "POST",
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth.test",
|
|
date = date,
|
|
["proxy-authorization"] = "asd"
|
|
}
|
|
})
|
|
local body = assert.res_status(401, res)
|
|
assert.equal('hmac realm="test-realm"', res.headers["WWW-Authenticate"])
|
|
body = cjson.decode(body)
|
|
assert.equal(SIGNATURE_NOT_VALID, body.message)
|
|
end)
|
|
|
|
it("should not pass when passing only the digest", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local res = assert(proxy_client:send {
|
|
method = "POST",
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth.test",
|
|
date = date,
|
|
["proxy-authorization"] = "hmac :dXNlcm5hbWU6cGFzc3dvcmQ="
|
|
}
|
|
})
|
|
local body = assert.res_status(401, res)
|
|
assert.equal('hmac realm="test-realm"', res.headers["WWW-Authenticate"])
|
|
body = cjson.decode(body)
|
|
assert.equal(SIGNATURE_NOT_VALID, body.message)
|
|
end)
|
|
|
|
it("should not pass when passing wrong hmac parameters", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local res = assert(proxy_client:send {
|
|
method = "POST",
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth.test",
|
|
date = date,
|
|
["proxy-authorization"] = [[hmac username=,algorithm,]]
|
|
.. [[headers,dXNlcm5hbWU6cGFzc3dvcmQ=]]
|
|
}
|
|
})
|
|
local body = assert.res_status(401, res)
|
|
assert.equal('hmac realm="test-realm"', res.headers["WWW-Authenticate"])
|
|
body = cjson.decode(body)
|
|
assert.equal(SIGNATURE_NOT_VALID, body.message)
|
|
end)
|
|
|
|
it("should not pass when passing wrong hmac parameters", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local res = assert(proxy_client:send {
|
|
method = "POST",
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth.test",
|
|
date = date,
|
|
authorization = [[hmac username=,algorithm,]]
|
|
.. [[headers,dXNlcm5hbWU6cGFzc3dvcmQ=]]
|
|
}
|
|
})
|
|
local body = assert.res_status(401, res)
|
|
assert.equal('hmac realm="test-realm"', res.headers["WWW-Authenticate"])
|
|
body = cjson.decode(body)
|
|
assert.equal(SIGNATURE_NOT_VALID, body.message)
|
|
end)
|
|
|
|
it("should not be authorized when passing only the username", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local res = assert(proxy_client:send {
|
|
method = "POST",
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth.test",
|
|
date = date,
|
|
authorization = "hmac username"
|
|
}
|
|
})
|
|
local body = assert.res_status(401, res)
|
|
assert.equal('hmac realm="test-realm"', res.headers["WWW-Authenticate"])
|
|
body = cjson.decode(body)
|
|
assert.equal(SIGNATURE_NOT_VALID, body.message)
|
|
end)
|
|
|
|
it("should not be authorized when authorization header is missing", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local res = assert(proxy_client:send {
|
|
method = "POST",
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth.test",
|
|
date = date,
|
|
}
|
|
})
|
|
local body = assert.res_status(401, res)
|
|
assert.equal('hmac realm="test-realm"', res.headers["WWW-Authenticate"])
|
|
body = cjson.decode(body)
|
|
assert.equal("Unauthorized", body.message)
|
|
end)
|
|
|
|
it("should not pass with username missing", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local encodedSignature = ngx.encode_base64(hmac_sha1_binary("secret", "date: " .. date))
|
|
local hmacAuth = [[hmac algorithm="hmac-sha1",]]
|
|
.. [[headers="date",signature="]] .. encodedSignature .. [["]]
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth.test",
|
|
date = date,
|
|
authorization = hmacAuth,
|
|
},
|
|
})
|
|
local body = assert.res_status(401, res)
|
|
assert.equal('hmac realm="test-realm"', res.headers["WWW-Authenticate"])
|
|
body = cjson.decode(body)
|
|
assert.not_nil(body.message)
|
|
assert.matches("HMAC signature cannot be verified", body.message)
|
|
end)
|
|
|
|
it("should not pass with signature missing", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local hmacAuth = [[hmac username="bob",algorithm="hmac-sha1",]]
|
|
.. [[headers="date"]]
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth.test",
|
|
date = date,
|
|
authorization = hmacAuth,
|
|
},
|
|
})
|
|
local body = assert.res_status(401, res)
|
|
assert.equal('hmac realm="test-realm"', res.headers["WWW-Authenticate"])
|
|
body = cjson.decode(body)
|
|
assert.not_nil(body.message)
|
|
assert.matches("HMAC signature cannot be verified", body.message)
|
|
end)
|
|
|
|
it("should pass with GET", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local encodedSignature = ngx.encode_base64(hmac_sha1_binary("secret", "date: " .. date))
|
|
local hmacAuth = [[hmac username="bob",algorithm="hmac-sha1",]]
|
|
.. [[headers="date",signature="]] .. encodedSignature .. [["]]
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth.test",
|
|
date = date,
|
|
authorization = hmacAuth,
|
|
},
|
|
})
|
|
local body = assert.res_status(200, res)
|
|
body = cjson.decode(body)
|
|
assert.equal(hmacAuth, body.headers["authorization"])
|
|
end)
|
|
|
|
it("accepts authorized gRPC calls", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local encodedSignature = ngx.encode_base64(hmac_sha1_binary("secret", "date: " .. date))
|
|
local hmacAuth = [[hmac username="bob",algorithm="hmac-sha1",]]
|
|
.. [[headers="date",signature="]] .. encodedSignature .. [["]]
|
|
|
|
local ok, res = helpers.proxy_client_grpc(){
|
|
service = "hello.HelloService.SayHello",
|
|
opts = {
|
|
[""] = ("-H 'Date: %s' -H 'Authorization: %s'"):format(date, hmacAuth),
|
|
},
|
|
}
|
|
assert.truthy(ok)
|
|
assert.same({ reply = "hello noname" }, cjson.decode(res))
|
|
end)
|
|
|
|
it("accepts authorized gRPC calls with @request-target (HTTP/2 test), bug #3789", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local encodedSignature = ngx.encode_base64(hmac_sha1_binary("secret", "date: " .. date ..
|
|
"\n@request-target: " ..
|
|
"post /hello.HelloService/SayHello"))
|
|
local hmacAuth = [[hmac username="bob",algorithm="hmac-sha1",]]
|
|
.. [[headers="date @request-target",signature="]] .. encodedSignature .. [["]]
|
|
|
|
local ok, res = helpers.proxy_client_grpc(){
|
|
service = "hello.HelloService.SayHello",
|
|
opts = {
|
|
[""] = ("-H 'Date: %s' -H 'Authorization: %s'"):format(date, hmacAuth),
|
|
},
|
|
}
|
|
assert.truthy(ok)
|
|
assert.same({ reply = "hello noname" }, cjson.decode(res))
|
|
end)
|
|
|
|
it("should pass with GET and proxy-authorization", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local encodedSignature = ngx.encode_base64(hmac_sha1_binary("secret", "date: " .. date))
|
|
local hmacAuth = [[hmac username="bob",algorithm="hmac-sha1",]]
|
|
.. [[headers="date",signature="]] .. encodedSignature .. [["]]
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth.test",
|
|
date = date,
|
|
["proxy-authorization"] = hmacAuth,
|
|
},
|
|
})
|
|
assert.res_status(200, res)
|
|
end)
|
|
|
|
it("should pass with POST", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local encodedSignature = ngx.encode_base64(hmac_sha1_binary("secret", "date: " .. date))
|
|
local hmacAuth = [[hmac username="bob",algorithm="hmac-sha1",]]
|
|
.. [[headers="date",signature="]] .. encodedSignature .. [["]]
|
|
local res = assert(proxy_client:send {
|
|
method = "POST",
|
|
path = "/request",
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth.test",
|
|
date = date,
|
|
authorization = hmacAuth,
|
|
},
|
|
})
|
|
local body = assert.res_status(200, res)
|
|
body = cjson.decode(body)
|
|
assert.equal(hmacAuth, body.headers["authorization"])
|
|
end)
|
|
|
|
it("should pass with GET and valid authorization and wrong proxy-authorization", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local encodedSignature = ngx.encode_base64(hmac_sha1_binary("secret", "date: " .. date))
|
|
local hmacAuth = [[hmac username="bob",algorithm="hmac-sha1",]]
|
|
.. [[headers="date",signature="]] .. encodedSignature .. [["]]
|
|
local res = assert(proxy_client:send {
|
|
method = "POST",
|
|
path = "/request",
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth.test",
|
|
date = date,
|
|
["proxy-authorization"] = "hmac username",
|
|
authorization = hmacAuth,
|
|
},
|
|
})
|
|
local body = assert.res_status(200, res)
|
|
body = cjson.decode(body)
|
|
assert.equal(hmacAuth, body.headers["authorization"])
|
|
end)
|
|
|
|
it("should pass with GET and invalid authorization and valid proxy-authorization", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local encodedSignature = ngx.encode_base64(
|
|
hmac_sha1_binary("secret", "date: " .. date))
|
|
local hmacAuth = [[hmac username="bob",algorithm="hmac-sha1",]]
|
|
.. [[headers="date",signature="]] .. encodedSignature .. [["]]
|
|
local res = assert(proxy_client:send {
|
|
method = "POST",
|
|
path = "/request",
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth.test",
|
|
date = date,
|
|
["proxy-authorization"] = hmacAuth,
|
|
authorization = "hello",
|
|
},
|
|
})
|
|
assert.res_status(200, res)
|
|
end)
|
|
|
|
it("should pass with GET with content-md5 header", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local encodedSignature = ngx.encode_base64(
|
|
hmac_sha1_binary("secret", "date: " .. date .. "\n" .. "content-md5: md5"))
|
|
local hmacAuth = [[hmac username="bob",algorithm="hmac-sha1",]]
|
|
.. [[headers="date content-md5",signature="]] .. encodedSignature .. [["]]
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth.test",
|
|
date = date,
|
|
["proxy-authorization"] = hmacAuth,
|
|
authorization = "hello",
|
|
["content-md5"] = "md5",
|
|
},
|
|
})
|
|
assert.res_status(200, res)
|
|
end)
|
|
|
|
it("should pass with GET with request-line", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local encodedSignature = ngx.encode_base64(
|
|
hmac_sha1_binary("secret", "date: "
|
|
.. date .. "\n" .. "content-md5: md5" .. "\nGET /request HTTP/1.1"))
|
|
local hmacAuth = [[hmac username="bob", algorithm="hmac-sha1", ]]
|
|
.. [[headers="date content-md5 request-line", signature="]]
|
|
.. encodedSignature .. [["]]
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth.test",
|
|
date = date,
|
|
["proxy-authorization"] = hmacAuth,
|
|
authorization = "hello",
|
|
["content-md5"] = "md5",
|
|
},
|
|
})
|
|
assert.res_status(200, res)
|
|
end)
|
|
|
|
it("should pass with GET with @request-target", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local encodedSignature = ngx.encode_base64(
|
|
hmac_sha1_binary("secret", "date: "
|
|
.. date .. "\n" .. "content-md5: md5" .. "\n@request-target: get /request"))
|
|
local hmacAuth = [[hmac username="bob", algorithm="hmac-sha1", ]]
|
|
.. [[headers="date content-md5 @request-target", signature="]]
|
|
.. encodedSignature .. [["]]
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth.test",
|
|
date = date,
|
|
["proxy-authorization"] = hmacAuth,
|
|
authorization = "hello",
|
|
["content-md5"] = "md5",
|
|
},
|
|
})
|
|
assert.res_status(200, res)
|
|
end)
|
|
|
|
it("should encode http-1 requests as http/1.0", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local encodedSignature = ngx.encode_base64(
|
|
hmac_sha1_binary("secret", "date: "
|
|
.. date .. "\n" .. "content-md5: md5" .. "\nGET /request HTTP/1.0"))
|
|
local hmacAuth = [[hmac username="bob", algorithm="hmac-sha1", ]]
|
|
.. [[headers="date content-md5 request-line", signature="]]
|
|
.. encodedSignature .. [["]]
|
|
local res = assert(proxy_client:send {
|
|
version = 1.0,
|
|
method = "GET",
|
|
path = "/request",
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth.test",
|
|
date = date,
|
|
["proxy-authorization"] = hmacAuth,
|
|
authorization = "hello",
|
|
["content-md5"] = "md5",
|
|
},
|
|
})
|
|
assert.res_status(200, res)
|
|
end)
|
|
|
|
|
|
it("should not pass with GET with wrong username in signature", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local encodedSignature = ngx.encode_base64(
|
|
hmac_sha1_binary("secret", "date: " .. date .. "\n"
|
|
.. "content-md5: md5" .. "\nGET /request HTTP/1.1"))
|
|
local hmacAuth = [[hmac username="bobb", algorithm="hmac-sha1", ]]
|
|
.. [[headers="date content-md5 request-line", signature="]]
|
|
.. encodedSignature .. [["]]
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth.test",
|
|
date = date,
|
|
["proxy-authorization"] = hmacAuth,
|
|
authorization = "hello",
|
|
["content-md5"] = "md5",
|
|
},
|
|
})
|
|
|
|
local body = assert.res_status(401, res)
|
|
assert.equal('hmac realm="test-realm"', res.headers["WWW-Authenticate"])
|
|
body = cjson.decode(body)
|
|
assert.equal(SIGNATURE_NOT_VALID, body.message)
|
|
end)
|
|
|
|
it("should not pass with GET with username blank in signature", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local encodedSignature = ngx.encode_base64(
|
|
hmac_sha1_binary("secret",
|
|
"date: " .. date .. "\n" .. "content-md5: md5" .. "\nGET /request HTTP/1.1"))
|
|
local hmacAuth = [[hmac username="", algorithm="hmac-sha1",]]
|
|
.. [[ headers="date content-md5 request-line", signature="]]
|
|
.. encodedSignature .. [["]]
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth.test",
|
|
date = date,
|
|
["proxy-authorization"] = hmacAuth,
|
|
authorization = "hello",
|
|
["content-md5"] = "md5",
|
|
},
|
|
})
|
|
|
|
local body = assert.res_status(401, res)
|
|
assert.equal('hmac realm="test-realm"', res.headers["WWW-Authenticate"])
|
|
body = cjson.decode(body)
|
|
assert.equal(SIGNATURE_NOT_VALID, body.message)
|
|
end)
|
|
|
|
it("should not pass with GET with username missing in signature", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local encodedSignature = ngx.encode_base64(
|
|
hmac_sha1_binary("secret",
|
|
"date: " .. date .. "\n" .. "content-md5: md5"
|
|
.. "\nGET /request HTTP/1.1"))
|
|
local hmacAuth = [[hmac algorithm="hmac-sha1", ]]
|
|
.. [[headers="date content-md5 request-line", signature="]]
|
|
.. encodedSignature .. [["]]
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth.test",
|
|
date = date,
|
|
["proxy-authorization"] = hmacAuth,
|
|
authorization = "hello",
|
|
["content-md5"] = "md5",
|
|
},
|
|
})
|
|
|
|
local body = assert.res_status(401, res)
|
|
assert.equal('hmac realm="test-realm"', res.headers["WWW-Authenticate"])
|
|
body = cjson.decode(body)
|
|
assert.equal(SIGNATURE_NOT_VALID, body.message)
|
|
end)
|
|
|
|
it("should not pass with GET with wrong hmac headers field name", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local encodedSignature = ngx.encode_base64(
|
|
hmac_sha1_binary("secret", "date: " .. date .. "\n"
|
|
.. "content-md5: md5" .. "\nGET /request HTTP/1.1"))
|
|
local hmacAuth = [[hmac username="bob", algorithm="hmac-sha1", ]]
|
|
.. [[wrong_header="date content-md5 request-line", signature="]]
|
|
.. encodedSignature .. [["]]
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth.test",
|
|
date = date,
|
|
["proxy-authorization"] = hmacAuth,
|
|
authorization = "hello",
|
|
["content-md5"] = "md5",
|
|
},
|
|
})
|
|
local body = assert.res_status(401, res)
|
|
assert.equal('hmac realm="test-realm"', res.headers["WWW-Authenticate"])
|
|
body = cjson.decode(body)
|
|
assert.equal(SIGNATURE_NOT_VALID, body.message)
|
|
end)
|
|
|
|
it("should not pass with GET with wrong hmac signature field name", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local encodedSignature = ngx.encode_base64(
|
|
hmac_sha1_binary("secret", "date: " .. date .. "\n"
|
|
.. "content-md5: md5" .. "\nGET /request HTTP/1.1"))
|
|
local hmacAuth = [[hmac username="bob", algorithm="hmac-sha1",]]
|
|
.. [[ headers="date content-md5 request-line", wrong_signature="]]
|
|
.. encodedSignature .. [["]]
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth.test",
|
|
date = date,
|
|
["proxy-authorization"] = hmacAuth,
|
|
authorization = "hello",
|
|
["content-md5"] = "md5",
|
|
},
|
|
})
|
|
local body = assert.res_status(401, res)
|
|
assert.equal('hmac realm="test-realm"', res.headers["WWW-Authenticate"])
|
|
body = cjson.decode(body)
|
|
assert.equal(SIGNATURE_NOT_VALID, body.message)
|
|
end)
|
|
|
|
it("should not pass with GET with malformed hmac signature field", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local encodedSignature = ngx.encode_base64(
|
|
hmac_sha1_binary("secret", "date: " .. date .. "\n"
|
|
.. "content-md5: md5" .. "\nGET /request HTTP/1.1"))
|
|
local hmacAuth = [[hmac username="bob", algorithm="hmac-sha1"]]
|
|
.. [[ headers="date content-md5 request-line", signature="]]
|
|
.. encodedSignature .. [["]]
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth.test",
|
|
date = date,
|
|
["proxy-authorization"] = hmacAuth,
|
|
authorization = "hello",
|
|
["content-md5"] = "md5",
|
|
},
|
|
})
|
|
local body = assert.res_status(401, res)
|
|
assert.equal('hmac realm="test-realm"', res.headers["WWW-Authenticate"])
|
|
body = cjson.decode(body)
|
|
assert.equal(SIGNATURE_NOT_VALID, body.message)
|
|
end)
|
|
|
|
it("should not pass with GET with malformed hmac headers field", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local encodedSignature = ngx.encode_base64(
|
|
hmac_sha1_binary("secret", "date: " .. date .. "\n"
|
|
.. "content-md5: md5" .. "\nGET /request? HTTP/1.1"))
|
|
local hmacAuth = [[hmac username="bob", algorithm="hmac-sha1" ]]
|
|
.. [[headers=" date content-md5 request-line",signature="]]
|
|
.. encodedSignature .. [["]]
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth.test",
|
|
date = date,
|
|
["proxy-authorization"] = hmacAuth,
|
|
authorization = "hello",
|
|
["content-md5"] = "md5",
|
|
},
|
|
})
|
|
local body = assert.res_status(401, res)
|
|
assert.equal('hmac realm="test-realm"', res.headers["WWW-Authenticate"])
|
|
body = cjson.decode(body)
|
|
assert.equal(SIGNATURE_NOT_VALID, body.message)
|
|
end)
|
|
|
|
it("should pass with GET with no space or space between hmac signatures fields", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local encodedSignature = ngx.encode_base64(
|
|
hmac_sha1_binary("secret", "date: " .. date .. "\n"
|
|
.. "content-md5: md5" .. "\nGET /request HTTP/1.1"))
|
|
local hmacAuth = [[hmac username="bob",algorithm="hmac-sha1",]]
|
|
.. [[ headers="date content-md5 request-line",signature="]]
|
|
.. encodedSignature .. [["]]
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth.test",
|
|
date = date,
|
|
["proxy-authorization"] = hmacAuth,
|
|
authorization = "hello",
|
|
["content-md5"] = "md5",
|
|
},
|
|
})
|
|
assert.res_status(200, res)
|
|
end)
|
|
|
|
it("should not pass with GET with wrong algorithm", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local encodedSignature = ngx.encode_base64(
|
|
openssl_mac.new("secret", "HMAC", nil, "sha256"):final("date: " .. date .. "\n"
|
|
.. "content-md5: md5" .. "\nGET /request HTTP/1.1"))
|
|
local hmacAuth = [[hmac username="bob",algorithm="hmac-sha",]]
|
|
.. [[ headers="date content-md5 request-line",signature="]]
|
|
.. encodedSignature .. [["]]
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth.test",
|
|
date = date,
|
|
["proxy-authorization"] = hmacAuth,
|
|
authorization = "hello",
|
|
["content-md5"] = "md5",
|
|
},
|
|
})
|
|
assert.res_status(401, res)
|
|
assert.equal('hmac realm="test-realm"', res.headers["WWW-Authenticate"])
|
|
end)
|
|
|
|
it("should pass the right headers to the upstream server", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local encodedSignature = ngx.encode_base64(
|
|
openssl_mac.new("secret", "HMAC", nil, "sha256"):final("date: " .. date .. "\n"
|
|
.. "content-md5: md5" .. "\nGET /request HTTP/1.1"))
|
|
local hmacAuth = [[hmac username="bob",algorithm="hmac-sha256",]]
|
|
.. [[ headers="date content-md5 request-line",signature="]]
|
|
.. encodedSignature .. [["]]
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth.test",
|
|
date = date,
|
|
["proxy-authorization"] = hmacAuth,
|
|
authorization = "hello",
|
|
["content-md5"] = "md5",
|
|
},
|
|
})
|
|
local body = assert.res_status(200, res)
|
|
local parsed_body = cjson.decode(body)
|
|
assert.equal(consumer.id, parsed_body.headers["x-consumer-id"])
|
|
assert.equal(consumer.username, parsed_body.headers["x-consumer-username"])
|
|
assert.equal(credential.username, parsed_body.headers["x-credential-identifier"])
|
|
assert.is_nil(parsed_body.headers["x-anonymous-consumer"])
|
|
end)
|
|
|
|
it("should pass with GET with x-date header", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local encodedSignature = ngx.encode_base64(
|
|
hmac_sha1_binary("secret", "x-date: " .. date .. "\n"
|
|
.. "content-md5: md5" .. "\nGET /request HTTP/1.1"))
|
|
local hmacAuth = [[hmac username="bob",algorithm="hmac-sha1",]]
|
|
.. [[ headers="x-date content-md5 request-line",signature="]]
|
|
.. encodedSignature .. [["]]
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth.test",
|
|
["x-date"] = date,
|
|
authorization = hmacAuth,
|
|
["content-md5"] = "md5",
|
|
},
|
|
})
|
|
assert.res_status(200, res)
|
|
end)
|
|
|
|
it("should not pass with GET with both date and x-date missing", function()
|
|
local encodedSignature = ngx.encode_base64(
|
|
hmac_sha1_binary("secret", "content-md5: md5"
|
|
.. "\nGET /request? HTTP/1.1"))
|
|
local hmacAuth = [[hmac username="bob", algorithm="hmac-sha1",]]
|
|
.. [[ headers="content-md5 request-line",signature="]]
|
|
.. encodedSignature .. [["]]
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth.test",
|
|
["proxy-authorization"] = hmacAuth,
|
|
authorization = "hello",
|
|
["content-md5"] = "md5",
|
|
},
|
|
})
|
|
local body = assert.res_status(401, res)
|
|
assert.equal('hmac realm="test-realm"', res.headers["WWW-Authenticate"])
|
|
body = cjson.decode(body)
|
|
assert.equal([[HMAC signature cannot be verified, a valid date or]]
|
|
.. [[ x-date header is required for HMAC Authentication]], body.message)
|
|
end)
|
|
|
|
it("should not pass with GET with x-date malformed", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local encodedSignature = ngx.encode_base64(
|
|
hmac_sha1_binary("secret", "x-date: " .. date .. "\n"
|
|
.. "content-md5: md5" .. "\nGET /request? HTTP/1.1"))
|
|
local hmacAuth = [[hmac username="bob",algorithm="hmac-sha1",]]
|
|
.. [[ headers="x-date content-md5 request-line",signature="]]
|
|
.. encodedSignature .. [["]]
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth.test",
|
|
["x-date"] = "wrong date",
|
|
authorization = hmacAuth,
|
|
["content-md5"] = "md5",
|
|
},
|
|
})
|
|
local body = assert.res_status(401, res)
|
|
assert.equal('hmac realm="test-realm"', res.headers["WWW-Authenticate"])
|
|
body = cjson.decode(body)
|
|
assert.equal([[HMAC signature cannot be verified, a valid date or]]
|
|
.. [[ x-date header is required for HMAC Authentication]], body.message)
|
|
end)
|
|
|
|
it("should pass with GET with x-date malformed but date correct", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local encodedSignature = ngx.encode_base64(
|
|
hmac_sha1_binary("secret", "content-md5: md5"
|
|
.. "\nGET /request HTTP/1.1"))
|
|
local hmacAuth = [[hmac username="bob",algorithm="hmac-sha1",]]
|
|
.. [[ headers="content-md5 request-line",signature="]]
|
|
.. encodedSignature .. [["]]
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth.test",
|
|
["x-date"] = "wrong date",
|
|
date = date,
|
|
authorization = hmacAuth,
|
|
["content-md5"] = "md5",
|
|
},
|
|
})
|
|
assert.res_status(200, res)
|
|
end)
|
|
|
|
it("should pass with x-date malformed but date correct and used for signature", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local encodedSignature = ngx.encode_base64(
|
|
hmac_sha1_binary("secret", "date: " .. date .. "\n"
|
|
.. "content-md5: md5" .. "\nGET /request HTTP/1.1"))
|
|
local hmacAuth = [[hmac username="bob",algorithm="hmac-sha1",]]
|
|
.. [[ headers="date content-md5 request-line",signature="]]
|
|
.. encodedSignature .. [["]]
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth.test",
|
|
["x-date"] = "wrong date",
|
|
date = date,
|
|
authorization = hmacAuth,
|
|
["content-md5"] = "md5",
|
|
},
|
|
})
|
|
assert.res_status(200, res)
|
|
end)
|
|
|
|
it("should with x-date malformed and used for signature but skew test pass", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local encodedSignature = ngx.encode_base64(
|
|
hmac_sha1_binary("secret", "x-date: " .. "wrong date" .. "\n"
|
|
.. "content-md5: md5" .. "\nGET /request HTTP/1.1"))
|
|
local hmacAuth = [[hmac username="bob",algorithm="hmac-sha1",]]
|
|
.. [[ headers="x-date content-md5 request-line",signature="]]
|
|
.. encodedSignature .. [["]]
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth.test",
|
|
["x-date"] = "wrong date",
|
|
date = date,
|
|
authorization = hmacAuth,
|
|
["content-md5"] = "md5",
|
|
},
|
|
})
|
|
assert.res_status(200, res)
|
|
end)
|
|
|
|
it("should pass with date malformed and used for signature but skew test pass", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local encodedSignature = ngx.encode_base64(
|
|
hmac_sha1_binary("secret", "date: " .. "wrong date" .. "\n"
|
|
.. "content-md5: md5" .. "\nGET /request HTTP/1.1"))
|
|
local hmacAuth = [[hmac username="bob",algorithm="hmac-sha1",]]
|
|
.. [[ headers="date content-md5 request-line",signature="]]
|
|
.. encodedSignature .. [["]]
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth.test",
|
|
["x-date"] = date,
|
|
date = "wrong date",
|
|
authorization = hmacAuth,
|
|
["content-md5"] = "md5",
|
|
}
|
|
})
|
|
assert.res_status(200, res)
|
|
end)
|
|
|
|
it("should pass with valid credentials and anonymous", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local encodedSignature = ngx.encode_base64(hmac_sha1_binary("secret", "date: " .. date))
|
|
local hmacAuth = [[hmac username="bob",algorithm="hmac-sha1",]]
|
|
.. [[headers="date",signature="]] .. encodedSignature .. [["]]
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth2.test",
|
|
date = date,
|
|
authorization = hmacAuth,
|
|
},
|
|
})
|
|
local body = assert.res_status(200, res)
|
|
body = cjson.decode(body)
|
|
assert.equal(hmacAuth, body.headers["authorization"])
|
|
assert.equal("bob", body.headers["x-consumer-username"])
|
|
assert.equal(credential.username, body.headers["x-credential-identifier"])
|
|
assert.is_nil(body.headers["x-anonymous-consumer"])
|
|
end)
|
|
|
|
it("should return 401 when body validation enabled and no digest header is present", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local postBody = '{"a":"apple","b":"ball"}'
|
|
local sha256 = resty_sha256:new()
|
|
sha256:update(postBody)
|
|
|
|
local encodedSignature = ngx.encode_base64(
|
|
hmac_sha1_binary("secret", "date: "..date))
|
|
local hmacAuth = [["hmac username="bob",algorithm="hmac-sha1",]]
|
|
..[[headers="date",signature="]]..encodedSignature..[["]]
|
|
local res = assert(proxy_client:send {
|
|
method = "POST",
|
|
path = "/request",
|
|
body = postBody,
|
|
headers = {
|
|
["HOST"] = "hmacauth4.test",
|
|
date = date,
|
|
authorization = hmacAuth,
|
|
}
|
|
})
|
|
local body = assert.res_status(401, res)
|
|
assert.equal('hmac', res.headers["WWW-Authenticate"])
|
|
body = cjson.decode(body)
|
|
assert.equal("HMAC signature does not match", body.message)
|
|
end)
|
|
|
|
it("should return 200 when body validation enabled and no body and no digest header is present", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
|
|
local encodedSignature = ngx.encode_base64(
|
|
hmac_sha1_binary("secret", "date: "..date))
|
|
local hmacAuth = [["hmac username="bob",algorithm="hmac-sha1",]]
|
|
..[[headers="date",signature="]]..encodedSignature..[["]]
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
headers = {
|
|
["HOST"] = "hmacauth4.test",
|
|
date = date,
|
|
authorization = hmacAuth,
|
|
}
|
|
})
|
|
assert.res_status(200, res)
|
|
end)
|
|
|
|
it("should return 200 when body validation enabled and no body and an digest header is present", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local sha256 = resty_sha256:new()
|
|
sha256:update('')
|
|
local digest = "SHA-256=" .. ngx.encode_base64(sha256:final())
|
|
|
|
local encodedSignature = ngx.encode_base64(
|
|
hmac_sha1_binary("secret", "date: "..date.."\n".."digest: "..digest))
|
|
local hmacAuth = [["hmac username="bob",algorithm="hmac-sha1",]]
|
|
..[[headers="date digest",signature="]]..encodedSignature..[["]]
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
headers = {
|
|
["HOST"] = "hmacauth4.test",
|
|
date = date,
|
|
digest = digest,
|
|
authorization = hmacAuth,
|
|
}
|
|
})
|
|
assert.res_status(200, res)
|
|
end)
|
|
|
|
it("should pass with invalid credentials and anonymous", function()
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth2.test",
|
|
},
|
|
})
|
|
local body = assert.res_status(200, res)
|
|
body = cjson.decode(body)
|
|
assert.equal("true", body.headers["x-anonymous-consumer"])
|
|
assert.equal('no-body', body.headers["x-consumer-username"])
|
|
assert.equal(nil, body.headers["x-credential-identifier"])
|
|
end)
|
|
|
|
it("should pass with invalid credentials and username in anonymous", function()
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth7.test",
|
|
},
|
|
})
|
|
local body = assert.res_status(200, res)
|
|
body = cjson.decode(body)
|
|
assert.equal("true", body.headers["x-anonymous-consumer"])
|
|
assert.equal('no-body', body.headers["x-consumer-username"])
|
|
end)
|
|
|
|
it("errors when anonymous user doesn't exist", function()
|
|
finally(function()
|
|
proxy_client = helpers.proxy_client()
|
|
end)
|
|
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
headers = {
|
|
["Host"] = "hmacauth3.test",
|
|
},
|
|
})
|
|
local body = cjson.decode(assert.res_status(500, res))
|
|
assert.same("anonymous consumer " .. nonexisting_anonymous .. " is configured but doesn't exist", body.message)
|
|
end)
|
|
|
|
it("should pass with GET when body validation enabled", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local encodedSignature = ngx.encode_base64(hmac_sha1_binary("secret", "date: "..date))
|
|
local hmacAuth = [["hmac username="bob",algorithm="hmac-sha1",]]
|
|
..[[headers="date",signature="]]..encodedSignature..[["]]
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth4.test",
|
|
date = date,
|
|
authorization = hmacAuth,
|
|
},
|
|
})
|
|
assert.res_status(200, res)
|
|
end)
|
|
|
|
it("should pass with POST when body validation enabled and digest header present", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local postBody = '{"a":"apple","b":"ball"}'
|
|
local sha256 = resty_sha256:new()
|
|
sha256:update(postBody)
|
|
local digest = "SHA-256=" .. ngx.encode_base64(sha256:final())
|
|
|
|
local encodedSignature = ngx.encode_base64(
|
|
hmac_sha1_binary("secret", "date: "..date.."\n".."digest: "..digest))
|
|
local hmacAuth = [["hmac username="bob",algorithm="hmac-sha1",]]
|
|
..[[headers="date digest",signature="]]..encodedSignature..[["]]
|
|
local res = assert(proxy_client:send {
|
|
method = "POST",
|
|
path = "/request",
|
|
body = postBody,
|
|
headers = {
|
|
["HOST"] = "hmacauth4.test",
|
|
date = date,
|
|
digest = digest,
|
|
authorization = hmacAuth,
|
|
},
|
|
})
|
|
assert.res_status(200, res)
|
|
end)
|
|
|
|
it("should pass with POST when body validation enabled but digest header not used", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local postBody = '{"a":"apple","b":"ball"}'
|
|
local sha256 = resty_sha256:new()
|
|
sha256:update(postBody)
|
|
local digest = "SHA-256=" .. ngx.encode_base64(sha256:final())
|
|
|
|
local encodedSignature = ngx.encode_base64(
|
|
hmac_sha1_binary("secret", "date: "..date.."\n".."digest: "..digest))
|
|
local hmacAuth = [["hmac username="bob",algorithm="hmac-sha1",]]
|
|
..[[headers="date digest",signature="]]..encodedSignature..[["]]
|
|
local res = assert(proxy_client:send {
|
|
method = "POST",
|
|
path = "/request",
|
|
body = postBody,
|
|
headers = {
|
|
["HOST"] = "hmacauth4.test",
|
|
date = date,
|
|
digest = digest,
|
|
authorization = hmacAuth,
|
|
},
|
|
})
|
|
assert.res_status(200, res)
|
|
end)
|
|
|
|
it("should not pass with POST when body validation enabled and digest header missing", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local postBody = '{"a":"apple","b":"ball"}'
|
|
local sha256 = resty_sha256:new()
|
|
sha256:update(postBody)
|
|
local digest = "SHA-256=" .. ngx.encode_base64(sha256:final())
|
|
|
|
local encodedSignature = ngx.encode_base64(
|
|
hmac_sha1_binary("secret", "date: "..date.."\n".."digest: "..digest))
|
|
local hmacAuth = [["hmac username="bob",algorithm="hmac-sha1",]]
|
|
..[[headers="date digest",signature="]]..encodedSignature..[["]]
|
|
local res = assert(proxy_client:send {
|
|
method = "POST",
|
|
path = "/request",
|
|
body = postBody,
|
|
headers = {
|
|
["HOST"] = "hmacauth4.test",
|
|
date = date,
|
|
authorization = hmacAuth,
|
|
},
|
|
})
|
|
local body = assert.res_status(401, res)
|
|
assert.equal('hmac', res.headers["WWW-Authenticate"])
|
|
body = cjson.decode(body)
|
|
assert.equal("HMAC signature does not match", body.message)
|
|
end)
|
|
|
|
it("should not pass with POST when body validation enabled and postBody is tampered", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local postBody = '{"a":"apple","b":"ball"}'
|
|
local sha256 = resty_sha256:new()
|
|
sha256:update(postBody)
|
|
local digest = "SHA-256=" .. ngx.encode_base64(sha256:final())
|
|
|
|
local encodedSignature = ngx.encode_base64(
|
|
hmac_sha1_binary("secret", "date: "..date.."\n".."digest: "..digest))
|
|
local hmacAuth = [["hmac username="bob",algorithm="hmac-sha1",]]
|
|
..[[headers="date digest",signature="]]..encodedSignature..[["]]
|
|
local res = assert(proxy_client:send {
|
|
method = "POST",
|
|
path = "/request",
|
|
body = "abc",
|
|
headers = {
|
|
["HOST"] = "hmacauth4.test",
|
|
date = date,
|
|
digest = digest,
|
|
authorization = hmacAuth,
|
|
},
|
|
})
|
|
local body = assert.res_status(401, res)
|
|
assert.equal('hmac', res.headers["WWW-Authenticate"])
|
|
body = cjson.decode(body)
|
|
assert.equal("HMAC signature does not match", body.message)
|
|
end)
|
|
|
|
it("should not pass with POST when body validation enabled and digest header is tampered", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local postBody = '{"a":"apple","b":"ball"}'
|
|
local sha256 = resty_sha256:new()
|
|
sha256:update(postBody)
|
|
local digest = "SHA-256=" .. ngx.encode_base64(sha256:final())
|
|
|
|
local encodedSignature = ngx.encode_base64(
|
|
hmac_sha1_binary("secret", "date: "..date.."\n".."digest: "..digest))
|
|
local hmacAuth = [["hmac username="bob",algorithm="hmac-sha1",]]
|
|
..[[headers="date digest",signature="]]..encodedSignature..[["]]
|
|
local res = assert(proxy_client:send {
|
|
method = "POST",
|
|
path = "/request",
|
|
body = postBody,
|
|
headers = {
|
|
["HOST"] = "hmacauth4.test",
|
|
date = date,
|
|
digest = digest .. "spoofed",
|
|
authorization = hmacAuth,
|
|
}
|
|
})
|
|
local body = assert.res_status(401, res)
|
|
assert.equal('hmac', res.headers["WWW-Authenticate"])
|
|
body = cjson.decode(body)
|
|
assert.equal("HMAC signature does not match", body.message)
|
|
end)
|
|
|
|
it("should pass with GET with request-line", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local encodedSignature = ngx.encode_base64(
|
|
hmac_sha1_binary("secret", "date: "
|
|
.. date .. "\n" .. "content-md5: md5" .. "\nGET /request HTTP/1.1"))
|
|
local hmacAuth = [[hmac username="bob", algorithm="hmac-sha1", ]]
|
|
.. [[headers="date content-md5 request-line", signature="]]
|
|
.. encodedSignature .. [["]]
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth5.test",
|
|
date = date,
|
|
["proxy-authorization"] = hmacAuth,
|
|
["content-md5"] = "md5",
|
|
},
|
|
})
|
|
assert.res_status(200, res)
|
|
end)
|
|
|
|
it("should fail with GET with request-line having query param but signed without query param", function()
|
|
-- hmac-auth signature must include the same query param in request-line: https://github.com/Kong/kong/pull/3339
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local encodedSignature = ngx.encode_base64(
|
|
hmac_sha1_binary("secret", "date: "
|
|
.. date .. "\n" .. "content-md5: md5" .. "\nGET /request HTTP/1.1"))
|
|
local hmacAuth = [[hmac username="bob", algorithm="hmac-sha1", ]]
|
|
.. [[headers="date content-md5 request-line", signature="]]
|
|
.. encodedSignature .. [["]]
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request?name=foo",
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth5.test",
|
|
date = date,
|
|
["proxy-authorization"] = hmacAuth,
|
|
["content-md5"] = "md5",
|
|
},
|
|
})
|
|
assert.res_status(401, res)
|
|
assert.equal('hmac', res.headers["WWW-Authenticate"])
|
|
|
|
encodedSignature = ngx.encode_base64(
|
|
hmac_sha1_binary("secret", "date: "
|
|
.. date .. "\n" .. "content-md5: md5" .. "\nGET /request/ HTTP/1.1"))
|
|
local hmacAuth = [[hmac username="bob", algorithm="hmac-sha1", ]]
|
|
.. [[headers="date content-md5 request-line", signature="]]
|
|
.. encodedSignature .. [["]]
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request/?name=foo",
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth5.test",
|
|
date = date,
|
|
["proxy-authorization"] = hmacAuth,
|
|
["content-md5"] = "md5",
|
|
},
|
|
})
|
|
assert.res_status(401, res)
|
|
assert.equal('hmac', res.headers["WWW-Authenticate"])
|
|
end)
|
|
|
|
it("should pass with GET with request-line having query param", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local encodedSignature = ngx.encode_base64(
|
|
hmac_sha1_binary("secret", "date: "
|
|
.. date .. "\n" .. "content-md5: md5" .. "\nGET /request?name=foo HTTP/1.1"))
|
|
local hmacAuth = [[hmac username="bob", algorithm="hmac-sha1", ]]
|
|
.. [[headers="date content-md5 request-line", signature="]]
|
|
.. encodedSignature .. [["]]
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request?name=foo",
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth5.test",
|
|
date = date,
|
|
["proxy-authorization"] = hmacAuth,
|
|
["content-md5"] = "md5",
|
|
},
|
|
})
|
|
assert.res_status(200, res)
|
|
|
|
encodedSignature = ngx.encode_base64(
|
|
hmac_sha1_binary("secret", "date: "
|
|
.. date .. "\n" .. "content-md5: md5" .. "\nGET /request/?name=foo HTTP/1.1"))
|
|
local hmacAuth = [[hmac username="bob", algorithm="hmac-sha1", ]]
|
|
.. [[headers="date content-md5 request-line", signature="]]
|
|
.. encodedSignature .. [["]]
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request/?name=foo",
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth5.test",
|
|
date = date,
|
|
["proxy-authorization"] = hmacAuth,
|
|
["content-md5"] = "md5",
|
|
},
|
|
})
|
|
assert.res_status(200, res)
|
|
end)
|
|
|
|
it("should pass with GET with request-line having encoded query param", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local escaped_uri = fmt("/request?name=%s",
|
|
ngx.escape_uri("foo bar"))
|
|
local encodedSignature = ngx.encode_base64(
|
|
hmac_sha1_binary("secret", "date: "
|
|
.. date .. "\n" .. "content-md5: md5" .. "\nGET " .. escaped_uri .. " HTTP/1.1"))
|
|
local hmacAuth = [[hmac username="bob", algorithm="hmac-sha1", ]]
|
|
.. [[headers="date content-md5 request-line", signature="]]
|
|
.. encodedSignature .. [["]]
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = escaped_uri,
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth5.test",
|
|
date = date,
|
|
["proxy-authorization"] = hmacAuth,
|
|
["content-md5"] = "md5",
|
|
},
|
|
})
|
|
local body = assert.res_status(200, res)
|
|
local json_body = cjson.decode(body)
|
|
assert.is.equal("foo bar", json_body.uri_args.name)
|
|
|
|
local escaped_uri = fmt("/request?name=%s",
|
|
ngx.escape_uri("foo bár"))
|
|
encodedSignature = ngx.encode_base64(
|
|
hmac_sha1_binary("secret", "date: "
|
|
.. date .. "\n" .. "content-md5: md5" .. "\nGET " .. escaped_uri .." HTTP/1.1"))
|
|
local hmacAuth = [[hmac username="bob", algorithm="hmac-sha1", ]]
|
|
.. [[headers="date content-md5 request-line", signature="]]
|
|
.. encodedSignature .. [["]]
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = escaped_uri,
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth5.test",
|
|
date = date,
|
|
["proxy-authorization"] = hmacAuth,
|
|
["content-md5"] = "md5",
|
|
},
|
|
})
|
|
local body = assert.res_status(200, res)
|
|
local json_body = cjson.decode(body)
|
|
assert.is.equal("foo bár", json_body.uri_args.name)
|
|
end)
|
|
|
|
it("should pass with GET with request-line having multiple query params", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local escaped_uri = fmt("/request?name=%s&address=%s" ,
|
|
ngx.escape_uri("foo bar"),
|
|
ngx.escape_uri("san francisco"))
|
|
local encodedSignature = ngx.encode_base64(
|
|
hmac_sha1_binary("secret", "date: "
|
|
.. date .. "\n" .. "content-md5: md5" .. "\nGET " .. escaped_uri .. " HTTP/1.1"))
|
|
local hmacAuth = [[hmac username="bob", algorithm="hmac-sha1", ]]
|
|
.. [[headers="date content-md5 request-line", signature="]]
|
|
.. encodedSignature .. [["]]
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = escaped_uri,
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth5.test",
|
|
date = date,
|
|
["proxy-authorization"] = hmacAuth,
|
|
["content-md5"] = "md5",
|
|
},
|
|
})
|
|
local body = assert.res_status(200, res)
|
|
local json_body = cjson.decode(body)
|
|
assert.is.equal("foo bar", json_body.uri_args.name)
|
|
assert.is.equal("san francisco", json_body.uri_args.address)
|
|
end)
|
|
|
|
it("should pass with GET with request-line having multiple same query param", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local encodedSignature = ngx.encode_base64(
|
|
hmac_sha1_binary("secret", "date: "
|
|
.. date .. "\n" .. "content-md5: md5" .. "\nGET /request?name=foo&name=bar HTTP/1.1"))
|
|
local hmacAuth = [[hmac username="bob", algorithm="hmac-sha1", ]]
|
|
.. [[headers="date content-md5 request-line", signature="]]
|
|
.. encodedSignature .. [["]]
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request?name=foo&name=bar",
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth5.test",
|
|
date = date,
|
|
["proxy-authorization"] = hmacAuth,
|
|
["content-md5"] = "md5",
|
|
},
|
|
})
|
|
local body = assert.res_status(200, res)
|
|
local json_body = cjson.decode(body)
|
|
assert.is.equal("foo", json_body.uri_args.name[1])
|
|
assert.is.equal("bar", json_body.uri_args.name[2])
|
|
end)
|
|
|
|
it("should pass with GET with request-line having no uri", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local encodedSignature = ngx.encode_base64(
|
|
hmac_sha1_binary("secret", "date: "
|
|
.. date .. "\n" .. "content-md5: md5" .. "\nGET / HTTP/1.1"))
|
|
local hmacAuth = [[hmac username="bob", algorithm="hmac-sha1", ]]
|
|
.. [[headers="date content-md5 request-line", signature="]]
|
|
.. encodedSignature .. [["]]
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth5.test",
|
|
date = date,
|
|
["proxy-authorization"] = hmacAuth,
|
|
["content-md5"] = "md5",
|
|
},
|
|
})
|
|
assert.res_status(200, res)
|
|
end)
|
|
|
|
it("should pass with GET with request-line having encoded path param", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local escaped_uri = fmt("/request/%s/?name=foo&name=bar",
|
|
ngx.escape_uri("some value"))
|
|
local encodedSignature = ngx.encode_base64(
|
|
hmac_sha1_binary("secret", "date: "
|
|
.. date .. "\n" .. "content-md5: md5" .. "\nGET ".. escaped_uri .. " HTTP/1.1"))
|
|
local hmacAuth = [[hmac username="bob", algorithm="hmac-sha1", ]]
|
|
.. [[headers="date content-md5 request-line", signature="]]
|
|
.. encodedSignature .. [["]]
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = escaped_uri,
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth5.test",
|
|
date = date,
|
|
["proxy-authorization"] = hmacAuth,
|
|
["content-md5"] = "md5",
|
|
},
|
|
})
|
|
local body = assert.res_status(200, res)
|
|
local json_body = cjson.decode(body)
|
|
assert.is.equal("foo", json_body.uri_args.name[1])
|
|
assert.is.equal("bar", json_body.uri_args.name[2])
|
|
assert.is.equal("/request/some value/", json_body.vars.uri)
|
|
end)
|
|
|
|
it("should fail with GET when enforced header request-line missing", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local encodedSignature = ngx.encode_base64(
|
|
hmac_sha1_binary("secret", "date: "
|
|
.. date .. "\n" .. "content-md5: md5"))
|
|
local hmacAuth = [[hmac username="bob", algorithm="hmac-sha1", ]]
|
|
.. [[headers="date content-md5", signature="]]
|
|
.. encodedSignature .. [["]]
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth5.test",
|
|
date = date,
|
|
["proxy-authorization"] = hmacAuth,
|
|
["content-md5"] = "md5",
|
|
},
|
|
})
|
|
assert.res_status(401, res)
|
|
assert.equal('hmac', res.headers["WWW-Authenticate"])
|
|
end)
|
|
|
|
it("should pass with GET with hmac-sha384", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local encodedSignature = ngx.encode_base64(
|
|
openssl_mac.new("secret", "HMAC", nil, "sha384"):final("date: " .. date .. "\n"
|
|
.. "content-md5: md5" .. "\nGET /request HTTP/1.1"))
|
|
local hmacAuth = [[hmac username="bob", algorithm="hmac-sha384", ]]
|
|
.. [[headers="date content-md5 request-line", signature="]]
|
|
.. encodedSignature .. [["]]
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth5.test",
|
|
date = date,
|
|
["proxy-authorization"] = hmacAuth,
|
|
["content-md5"] = "md5",
|
|
},
|
|
})
|
|
assert.res_status(200, res)
|
|
end)
|
|
|
|
it("should pass with GET with hmac-sha512", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local encodedSignature = ngx.encode_base64(
|
|
openssl_mac.new("secret", "HMAC", nil, "sha512"):final("date: " .. date .. "\n"
|
|
.. "content-md5: md5" .. "\nGET /request HTTP/1.1"))
|
|
local hmacAuth = [[hmac username="bob", algorithm="hmac-sha512", ]]
|
|
.. [[headers="date content-md5 request-line", signature="]]
|
|
.. encodedSignature .. [["]]
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth5.test",
|
|
date = date,
|
|
["proxy-authorization"] = hmacAuth,
|
|
["content-md5"] = "md5",
|
|
},
|
|
})
|
|
assert.res_status(200, res)
|
|
end)
|
|
|
|
it("should not pass with hmac-sha512", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local encodedSignature = ngx.encode_base64(
|
|
openssl_mac.new("secret", "HMAC", nil, "sha512"):final("date: " .. date .. "\n"
|
|
.. "content-md5: md5" .. "\nGET /request HTTP/1.1"))
|
|
local hmacAuth = [[hmac username="bob", algorithm="hmac-sha512", ]]
|
|
.. [[headers="date content-md5 request-line", signature="]]
|
|
.. encodedSignature .. [["]]
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth6.test",
|
|
date = date,
|
|
["proxy-authorization"] = hmacAuth,
|
|
["content-md5"] = "md5",
|
|
},
|
|
})
|
|
assert.res_status(401, res)
|
|
assert.equal('hmac', res.headers["WWW-Authenticate"])
|
|
end)
|
|
|
|
it("should return a 401 with an invalid authorization header", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth6.test",
|
|
date = date,
|
|
["proxy-authorization"] = "this is no hmac token at all is it?",
|
|
},
|
|
})
|
|
assert.res_status(401, res)
|
|
assert.equal('hmac', res.headers["WWW-Authenticate"])
|
|
end)
|
|
|
|
it("should pass with hmac-sha1", function()
|
|
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local encodedSignature = ngx.encode_base64(
|
|
openssl_mac.new("secret", "HMAC", nil, "sha1"):final("date: " .. date .. "\n"
|
|
.. "content-md5: md5" .. "\nGET /request HTTP/1.1"))
|
|
local hmacAuth = [[hmac username="bob", algorithm="hmac-sha1", ]]
|
|
.. [[headers="date content-md5 request-line", signature="]]
|
|
.. encodedSignature .. [["]]
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
body = {},
|
|
headers = {
|
|
["HOST"] = "hmacauth6.test",
|
|
date = date,
|
|
["proxy-authorization"] = hmacAuth,
|
|
["content-md5"] = "md5",
|
|
},
|
|
})
|
|
assert.res_status(200, res)
|
|
end)
|
|
|
|
end)
|
|
end)
|
|
|
|
describe("Plugin: hmac-auth (access) [#" .. strategy .. "]", function()
|
|
local proxy_client
|
|
local user1
|
|
local user2
|
|
local anonymous
|
|
local hmacAuth
|
|
local hmacDate
|
|
|
|
lazy_setup(function()
|
|
local bp = helpers.get_db_utils(strategy, {
|
|
"routes",
|
|
"services",
|
|
"consumers",
|
|
"plugins",
|
|
"hmacauth_credentials",
|
|
"keyauth_credentials",
|
|
})
|
|
|
|
local service1 = bp.services:insert({
|
|
path = "/request"
|
|
})
|
|
|
|
local route1 = bp.routes:insert {
|
|
hosts = { "logical-and.test" },
|
|
protocols = { "http", "https" },
|
|
service = service1
|
|
}
|
|
|
|
bp.plugins:insert {
|
|
name = "hmac-auth",
|
|
route = { id = route1.id }
|
|
}
|
|
|
|
bp.plugins:insert {
|
|
name = "key-auth",
|
|
route = { id = route1.id }
|
|
}
|
|
|
|
anonymous = bp.consumers:insert {
|
|
username = "Anonymous"
|
|
}
|
|
|
|
user1 = bp.consumers:insert {
|
|
username = "Mickey"
|
|
}
|
|
|
|
user2 = bp.consumers:insert {
|
|
username = "Aladdin"
|
|
}
|
|
|
|
local service2 = bp.services:insert({
|
|
path = "/request"
|
|
})
|
|
|
|
local route2 = bp.routes:insert {
|
|
hosts = { "logical-or.test" },
|
|
protocols = { "http", "https" },
|
|
service = service2
|
|
}
|
|
|
|
bp.plugins:insert {
|
|
name = "hmac-auth",
|
|
route = { id = route2.id },
|
|
config = {
|
|
anonymous = anonymous.id
|
|
}
|
|
}
|
|
|
|
bp.plugins:insert {
|
|
name = "key-auth",
|
|
route = { id = route2.id },
|
|
config = {
|
|
anonymous = anonymous.id
|
|
}
|
|
}
|
|
|
|
bp.keyauth_credentials:insert {
|
|
key = "Mouse",
|
|
consumer = { id = user1.id },
|
|
}
|
|
|
|
local credential = bp.hmacauth_credentials:insert {
|
|
username = "Aladdin",
|
|
secret = "OpenSesame",
|
|
consumer = { id = user2.id },
|
|
}
|
|
|
|
hmacDate = os.date("!%a, %d %b %Y %H:%M:%S GMT")
|
|
local encodedSignature = ngx.encode_base64(hmac_sha1_binary(credential.secret, "date: " .. hmacDate))
|
|
hmacAuth = [[hmac username="]] .. credential.username .. [[",algorithm="hmac-sha1",]]
|
|
.. [[headers="date",signature="]] .. encodedSignature .. [["]]
|
|
|
|
assert(helpers.start_kong({
|
|
database = strategy,
|
|
nginx_conf = "spec/fixtures/custom_nginx.template",
|
|
}))
|
|
proxy_client = helpers.proxy_client()
|
|
end)
|
|
|
|
|
|
lazy_teardown(function()
|
|
if proxy_client then proxy_client:close() end
|
|
helpers.stop_kong()
|
|
end)
|
|
|
|
describe("multiple auth without anonymous, logical AND", function()
|
|
|
|
it("passes with all credentials provided", function()
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
headers = {
|
|
["Host"] = "logical-and.test",
|
|
["apikey"] = "Mouse",
|
|
["Authorization"] = hmacAuth,
|
|
["date"] = hmacDate,
|
|
},
|
|
})
|
|
assert.response(res).has.status(200)
|
|
assert.request(res).has.no.header("x-anonymous-consumer")
|
|
local id = assert.request(res).has.header("x-consumer-id")
|
|
assert.not_equal(id, anonymous.id)
|
|
assert(id == user1.id or id == user2.id,
|
|
string.format("expected %s or %s, got %s", user1.id, user2.id, id))
|
|
end)
|
|
|
|
it("fails 401, with only the first credential provided", function()
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
headers = {
|
|
["Host"] = "logical-and.test",
|
|
["apikey"] = "Mouse",
|
|
},
|
|
})
|
|
assert.response(res).has.status(401)
|
|
assert.equal('hmac', res.headers["WWW-Authenticate"])
|
|
end)
|
|
|
|
it("fails 401, with only the second credential provided", function()
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
headers = {
|
|
["Host"] = "logical-and.test",
|
|
["Authorization"] = hmacAuth,
|
|
["date"] = hmacDate,
|
|
},
|
|
})
|
|
assert.response(res).has.status(401)
|
|
assert.equal('Key', res.headers["WWW-Authenticate"])
|
|
end)
|
|
|
|
it("fails 401, with no credential provided", function()
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
headers = {
|
|
["Host"] = "logical-and.test",
|
|
},
|
|
})
|
|
assert.response(res).has.status(401)
|
|
assert.equal('Key', res.headers["WWW-Authenticate"])
|
|
end)
|
|
|
|
end)
|
|
|
|
describe("multiple auth with anonymous, logical OR", function()
|
|
|
|
it("passes with all credentials provided", function()
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
headers = {
|
|
["Host"] = "logical-or.test",
|
|
["apikey"] = "Mouse",
|
|
["Authorization"] = hmacAuth,
|
|
["date"] = hmacDate,
|
|
},
|
|
})
|
|
assert.response(res).has.status(200)
|
|
assert.request(res).has.no.header("x-anonymous-consumer")
|
|
local id = assert.request(res).has.header("x-consumer-id")
|
|
assert.not_equal(id, anonymous.id)
|
|
assert(id == user1.id or id == user2.id,
|
|
string.format("expected %s or %s, got %s", user1.id, user2.id, id))
|
|
end)
|
|
|
|
it("passes with only the first credential provided", function()
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
headers = {
|
|
["Host"] = "logical-or.test",
|
|
["apikey"] = "Mouse",
|
|
},
|
|
})
|
|
assert.response(res).has.status(200)
|
|
assert.request(res).has.no.header("x-anonymous-consumer")
|
|
local id = assert.request(res).has.header("x-consumer-id")
|
|
assert.not_equal(id, anonymous.id)
|
|
assert.equal(user1.id, id)
|
|
end)
|
|
|
|
it("passes with only the second credential provided", function()
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
headers = {
|
|
["Host"] = "logical-or.test",
|
|
["Authorization"] = hmacAuth,
|
|
["date"] = hmacDate,
|
|
},
|
|
})
|
|
assert.response(res).has.status(200)
|
|
assert.request(res).has.no.header("x-anonymous-consumer")
|
|
local id = assert.request(res).has.header("x-consumer-id")
|
|
assert.not_equal(id, anonymous.id)
|
|
assert.equal(user2.id, id)
|
|
end)
|
|
|
|
it("passes with no credential provided", function()
|
|
local res = assert(proxy_client:send {
|
|
method = "GET",
|
|
path = "/request",
|
|
headers = {
|
|
["Host"] = "logical-or.test",
|
|
},
|
|
})
|
|
assert.response(res).has.status(200)
|
|
assert.request(res).has.header("x-anonymous-consumer")
|
|
local id = assert.request(res).has.header("x-consumer-id")
|
|
assert.equal(id, anonymous.id)
|
|
end)
|
|
|
|
end)
|
|
|
|
end)
|
|
|
|
end
|