Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat] blocking consumer_id for SSL #372

Merged
merged 1 commit into from
Jul 2, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
13 changes: 12 additions & 1 deletion kong/dao/schemas/plugins_configurations.lua
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,18 @@ return {
value = { type = "table", schema = load_value_schema },
enabled = { type = "boolean", default = true }
},
on_insert = function(plugin_t, dao)
on_insert = function(plugin_t, dao, schema)
-- Load the value schema
local value_schema, err = schema.fields.value.schema(plugin_t)
if err then
return false, err
end

-- Check if the schema has a `no_consumer` field
if value_schema.no_consumer and plugin_t.consumer_id ~= nil and plugin_t.consumer_id ~= constants.DATABASE_NULL_ID then
return false, DaoError("No consumer can be configured for that plugin", constants.DATABASE_ERROR_TYPES.SCHEMA)
end

local res, err = dao.plugins_configurations:find_by_keys({
name = plugin_t.name,
api_id = plugin_t.api_id,
Expand Down
2 changes: 1 addition & 1 deletion kong/dao/schemas_validation.lua
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ end

function _M.on_insert(t, schema, dao)
if schema.on_insert and type(schema.on_insert) == "function" then
local valid, err = schema.on_insert(t, dao)
local valid, err = schema.on_insert(t, dao, schema)
if not valid or err then
return false, err
else
Expand Down
1 change: 1 addition & 0 deletions kong/plugins/ssl/schema.lua
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ local function validate_key(v)
end

return {
no_consumer = true,
fields = {
cert = { required = true, type = "string", func = validate_cert },
key = { required = true, type = "string", func = validate_key },
Expand Down
99 changes: 99 additions & 0 deletions spec/plugins/ssl/access_spec.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
local spec_helper = require "spec.spec_helpers"
local ssl_util = require "kong.plugins.ssl.ssl_util"
local url = require "socket.url"
local IO = require "kong.tools.io"
local http_client = require "kong.tools.http_client"
local cjson = require "cjson"
local ssl_fixtures = require "spec.plugins.ssl.fixtures"

local STUB_GET_SSL_URL = spec_helper.STUB_GET_SSL_URL
local STUB_GET_URL = spec_helper.STUB_GET_URL
local API_URL = spec_helper.API_URL

describe("SSL Plugin", function()

setup(function()
spec_helper.prepare_db()
spec_helper.insert_fixtures {
api = {
{ name = "API TESTS 11 (ssl)", public_dns = "ssl1.com", target_url = "http://mockbin.com" },
{ name = "API TESTS 12 (ssl)", public_dns = "ssl2.com", target_url = "http://mockbin.com" },
{ name = "API TESTS 13 (ssl)", public_dns = "ssl3.com", target_url = "http://mockbin.com" }
},
plugin_configuration = {
{ name = "ssl", value = { cert = ssl_fixtures.cert, key = ssl_fixtures.key }, __api = 1 },
{ name = "ssl", value = { cert = ssl_fixtures.cert, key = ssl_fixtures.key, only_https = true }, __api = 2 }
}
}

spec_helper.start_kong()
end)

teardown(function()
spec_helper.stop_kong()
end)

describe("SSL Util", function()

it("should not convert an invalid cert to DER", function()
assert.falsy(ssl_util.cert_to_der("asd"))
end)

it("should convert a valid cert to DER", function()
assert.truthy(ssl_util.cert_to_der(ssl_fixtures.cert))
end)

it("should not convert an invalid key to DER", function()
assert.falsy(ssl_util.key_to_der("asd"))
end)

it("should convert a valid key to DER", function()
assert.truthy(ssl_util.key_to_der(ssl_fixtures.key))
end)

end)

describe("SSL Resolution", function()

it("should return default CERTIFICATE when requesting other APIs", function()
local parsed_url = url.parse(STUB_GET_SSL_URL)
local res = IO.os_execute("(echo \"GET /\"; sleep 2) | openssl s_client -connect "..parsed_url.host..":"..tostring(parsed_url.port).." -servername test4.com")

assert.truthy(res:match("US/ST=California/L=San Francisco/O=Kong/OU=IT/CN=localhost"))
end)

it("should work when requesting a specific API", function()
local parsed_url = url.parse(STUB_GET_SSL_URL)
local res = IO.os_execute("(echo \"GET /\"; sleep 2) | openssl s_client -connect "..parsed_url.host..":"..tostring(parsed_url.port).." -servername ssl1.com")

assert.truthy(res:match("US/ST=California/L=San Francisco/O=Kong/OU=IT/CN=ssl1.com"))
end)

end)

describe("only_https", function()

it("should block request without https", function()
local response, status, headers = http_client.get(STUB_GET_URL, nil, { host = "ssl2.com" })
assert.are.equal(426, status)
assert.are.same("close, Upgrade", headers.connection)
assert.are.same("TLS/1.0, HTTP/1.1", headers.upgrade)
assert.are.same("Please use HTTPS protocol", cjson.decode(response).message)
end)

it("should not block request with https", function()
local _, status = http_client.get(STUB_GET_SSL_URL, nil, { host = "ssl2.com" })
assert.are.equal(200, status)
end)

end)

describe("should work with curl", function()
local response = http_client.get(API_URL.."/apis/", {public_dns="ssl3.com"})
local api_id = cjson.decode(response).data[1].id
local current_path = IO.os_execute("pwd")
local res = IO.os_execute("curl -s -o /dev/null -w \"%{http_code}\" "..API_URL.."/apis/"..api_id.."/plugins/ --form \"name=ssl\" --form \"value.cert=@"..current_path.."/ssl/kong-default.crt\" --form \"value.key=@"..current_path.."/ssl/kong-default.key\"")
assert.are.equal("201", res)
end)

end)
36 changes: 36 additions & 0 deletions spec/plugins/ssl/api_spec.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
local json = require "cjson"
local http_client = require "kong.tools.http_client"
local spec_helper = require "spec.spec_helpers"
local ssl_fixtures = require "spec.plugins.ssl.fixtures"

describe("SSL API", function()
local BASE_URL

setup(function()
spec_helper.prepare_db()
spec_helper.start_kong()
spec_helper.insert_fixtures {
api = {
{name = "mockbin", public_dns = "mockbin.com", target_url = "http://mockbin.com"}
}
}
BASE_URL = spec_helper.API_URL.."/apis/mockbin/plugins/"
end)

teardown(function()
spec_helper.stop_kong()
end)

describe("/apis/:api/plugins", function()

it("should refuse to set a `consumer_id` if asked to", function()
local response, status = http_client.post_multipart(BASE_URL,
{name = "ssl", consumer_id = "0000", ["value.cert"] = ssl_fixtures.cert, ["value.key"] = ssl_fixtures.key}
)
assert.equal(400, status)
local body = json.decode(response)
assert.equal("No consumer can be configured for that plugin", body.message)
end)

end)
end)
32 changes: 32 additions & 0 deletions spec/plugins/ssl/fixtures.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
return {
cert = [[-----BEGIN CERTIFICATE-----
MIICSTCCAbICCQDZ7lxm1iUKmDANBgkqhkiG9w0BAQsFADBpMQswCQYDVQQGEwJV
UzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzEN
MAsGA1UECgwES29uZzELMAkGA1UECwwCSVQxETAPBgNVBAMMCHNzbDEuY29tMB4X
DTE1MDUxOTAwNTAzNloXDTE1MDYxODAwNTAzNlowaTELMAkGA1UEBhMCVVMxEzAR
BgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xDTALBgNV
BAoMBEtvbmcxCzAJBgNVBAsMAklUMREwDwYDVQQDDAhzc2wxLmNvbTCBnzANBgkq
hkiG9w0BAQEFAAOBjQAwgYkCgYEAxOixlvURWF+WfMbG4alhrd3JcavYOGxiBcOv
0qA2v2a89S5JyD43O2uC8TfE6JZc3UT5kjRKRqIA8QDTYn3XGoJwkvYd1w9oXm3R
sZXXbi05PD0oXABtIIbH+0NllXRucdeODlXLi80mCvhVIIDjHifqDRiukecZGapE
rvTsPjMCAwEAATANBgkqhkiG9w0BAQsFAAOBgQCVQdpCfTZLJk0XUu5RnenHpamp
5ZRsdKA+jwE0kwuSWXx/WbsU35GJx1QVrfnmk7qJpwwg/ZbL/KMTUpY21a4ZyITQ
WKHxfY3Klqh18Ll7oBDa9fhuhPE4G8tIum/xY3Z3mHBuXDmBxARD0bOPEJtJQw+H
LGenf2mYrZBfL47wZw==
-----END CERTIFICATE-----]],
key = [[-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDE6LGW9RFYX5Z8xsbhqWGt3clxq9g4bGIFw6/SoDa/Zrz1LknI
Pjc7a4LxN8TollzdRPmSNEpGogDxANNifdcagnCS9h3XD2hebdGxldduLTk8PShc
AG0ghsf7Q2WVdG5x144OVcuLzSYK+FUggOMeJ+oNGK6R5xkZqkSu9Ow+MwIDAQAB
AoGAcYkqPLx5j9ct0ixbKGqd475qFJzdQ0tbCa/XhT7T0nDOqyBRcqBNAHnxOlzJ
sMJiMUNAE8kKusdWe5/aQoQErkVuO9sh1U6sPr7mVD/JWmE08MRzhMwxUVP+HsXM
EZky0M6TWNyghtvyElUiHTIW8quVdjn8oXQIbR/07VXEVmECQQDj6dHJ4XxXIvE1
HQ+49EbbM9l7KFd7t2cpmng1+U4yqMGwNVk3MmEVKU8NiI/BVhznPvp0HH3QyLpV
ShPt9SltAkEA3SzAZ5/UhjycKXgLsgidwDVWOpYweWU7KDsfrr+cSJkmzw7y9WYr
vshdPYA2iSm83aY1vTzwSRV6udpZfBLiHwJBAJ1HfDie3JmdSWtn1LPEDymyDEEL
Q+PiWtTA/nfwxV/8ST16c0i+AXUC/sTOGrZG4MdMFLYP+1sbSksVRc+OwbkCQQCy
DFKfmOUnYyd7oq4XliQYFVfjNgCz2TB0RJROwuV29ANv8GLZ9nQE05tr5QkCBl2K
OUFNo/7zdp0jfIlI/pKVAkA04q30OSEBIHBj/MmapVVSRaQiYfSMLV176nA4xqhz
JkHk9MH9WKKGIchn0LvfUFHxTeBFERoREQo2A82B/WpO
-----END RSA PRIVATE KEY-----]]
}
Loading