Skip to content

Commit

Permalink
feat: blocking consumer_id for SSL
Browse files Browse the repository at this point in the history
Handled with a custom check in SSL's `on_insert` event. Waiting for
global plugins implementation for a cleaner, more generic solution.

Fix #322
  • Loading branch information
thibaultcha committed Jun 30, 2015
1 parent a7a4e2d commit 8d5e6b6
Show file tree
Hide file tree
Showing 8 changed files with 213 additions and 197 deletions.
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()
local fixtures = 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

0 comments on commit 8d5e6b6

Please sign in to comment.