Skip to content

Commit

Permalink
Merge remote-tracking branch 'Mashape/master'
Browse files Browse the repository at this point in the history
* Mashape/master:
  fix(cli) re-enable search in $PATH for nginx executable
  hotfix(log plugins) only log consumer_id and credential id
  docs(changelog) add 0.5.2 changes
  chore: bump Kong to 0.5.2
  support for X-Date header where date header cant be used
  Add support for oauth2 plugin X-Forwarded-Proto HTTPS override
  docs(readme) add Kongfig to tools section
  Merge branch 'sinzone-patch-1' into next
  support for X-Date header where date header cant be used
  docs(readme)
  • Loading branch information
xvaara committed Oct 23, 2015
2 parents dfde9c3 + e0fb503 commit 10fe05a
Show file tree
Hide file tree
Showing 18 changed files with 167 additions and 65 deletions.
14 changes: 13 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
## [Unreleased][unreleased]

## [0.5.2] - 2015/10/21

A few fixes requested by the community!

### Fixed

- Kong properly search the `nginx` in your $PATH variable.
- Plugins:
- OAuth2: can detect that the originating protocol for a request was HTTPS through the `X-Forwarded-Proto` header and work behind another reverse proxy (load balancer). [#650](https://github.com/Mashape/kong/pull/650)
- HMAC signature: support for `X-Date` header to sign the request for usage in browsers (since the `Date` header is protected). [#641](https://github.com/Mashape/kong/issues/641)

## [0.5.1] - 2015/10/13

Fixing a few glitches we let out with 0.5.0!
Expand Down Expand Up @@ -335,7 +346,8 @@ First version running with Cassandra.
- CLI `bin/kong` script.
- Database migrations (using `db.lua`).

[unreleased]: https://github.com/mashape/kong/compare/0.5.1...next
[unreleased]: https://github.com/mashape/kong/compare/0.5.2...next
[0.5.2]: https://github.com/mashape/kong/compare/0.5.1...0.5.2
[0.5.1]: https://github.com/mashape/kong/compare/0.5.0...0.5.1
[0.5.0]: https://github.com/mashape/kong/compare/0.4.2...0.5.0
[0.4.2]: https://github.com/mashape/kong/compare/0.4.1...0.4.2
Expand Down
24 changes: 16 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ Kong [was created](http://stackshare.io/mashape/how-mashape-manages-over-15-000-

[![Gitter Badge][gitter-badge]][gitter-url]


## Summary

- [**Features**](#features)
Expand Down Expand Up @@ -75,22 +74,31 @@ Kong comes in many shapes. While this repository contains its core's source code

Resources:

- [The story behind Kong](http://stackshare.io/mashape/how-mashape-manages-over-15-000-apis-microservices)
- [Kong mentioned for the Empire PaaS](http://engineering.remind.com/introducing-empire/)
- [Kong Getting Started Tutorials in Japanese](http://dev.classmethod.jp/etc/kong-api-aggregator/)
- [Realtime API Management with Pushpin](http://blog.fanout.io/2015/07/14/realtime-api-management-pushpin-kong/)
- [How to Create your own Plugin](http://streamdata.io/blog/developing-an-helloworld-kong-plugin/)
- [Instaclustr Partners with Kong](https://www.instaclustr.com/instaclustr-partners-with-mashape-to-deliver-managed-cassandra-for-kong/)
- [The story behind Kong](http://stackshare.io/mashape/how-mashape-manages-over-15-000-apis-microservices)
- [How to create your own Kong plugin](http://streamdata.io/blog/developing-an-helloworld-kong-plugin/)
- [Instaclustr partners with Kong](https://www.instaclustr.com/instaclustr-partners-with-mashape-to-deliver-managed-cassandra-for-kong/)
- [How to deploy Kong on Azure](https://jeremiedevillard.wordpress.com/2015/10/12/deploy-kong-api-management-using-azure-resource-manager/)
- [Kong intro in Portuguese](https://www.youtube.com/watch?v=0OIWr1yLs_4)
- [Kong tutorial in Japanese 1](http://dev.classmethod.jp/etc/kong-api-aggregator/)
- [Kong tutorial in Japanese 2](http://www.ryuzee.com/contents/blog/7048)

Videos:

- [VIDEO - Kong Demo in Portuguese](https://www.youtube.com/watch?v=0OIWr1yLs_4)
- [VIDEO - OAuth2 with Kong](https://www.youtube.com/watch?v=nzySsFuV72M)
- [VIDEO - Kong with Docker](https://www.youtube.com/watch?v=ME7MI2SwJ-E)

Tools:

- [Kongfig](https://github.com/mybuilder/kongfig)
- [Kong on Tutum](https://github.com/Sillelien/docker-kong)
- [Kong Admin GUI in JS](https://github.com/rsdevigo/jungle)
- [Kong Admin GUI in Py](https://github.com/vikingco/django-kong-admin)
- [Kong GUI in JS](https://github.com/rsdevigo/jungle)
- [Kong GUI in Py](https://github.com/vikingco/django-kong-admin)
- [Kong UI](https://github.com/msaraf/kong-ui)
- [Chef Cookbook for Kong](https://github.com/zuazo/kong-cookbook)
- [Python Client for Kong API](https://pypi.python.org/pypi/python-kong/)
- [Python Client for Kong](https://pypi.python.org/pypi/python-kong/)
- [Kong with Instaclustr](https://www.instaclustr.com/products/kong/)

## Roadmap
Expand Down
6 changes: 3 additions & 3 deletions kong-0.5.1-1.rockspec → kong-0.5.2-1.rockspec
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package = "kong"
version = "0.5.1-1"
version = "0.5.2-1"
supported_platforms = {"linux", "macosx"}
source = {
url = "git://github.com/Mashape/kong",
tag = "0.5.1"
tag = "0.5.2"
}
description = {
summary = "Kong is a scalable and customizable API Management Layer built on top of Nginx.",
Expand Down Expand Up @@ -214,7 +214,7 @@ build = {
["kong.plugins.jwt.api"] = "kong/plugins/jwt/api.lua",
["kong.plugins.jwt.daos"] = "kong/plugins/jwt/daos.lua",
["kong.plugins.jwt.jwt_parser"] = "kong/plugins/jwt/jwt_parser.lua",

["kong.plugins.hmac-auth.migrations.cassandra"] = "kong/plugins/hmac-auth/migrations/cassandra.lua",
["kong.plugins.hmac-auth.handler"] = "kong/plugins/hmac-auth/handler.lua",
["kong.plugins.hmac-auth.access"] = "kong/plugins/hmac-auth/access.lua",
Expand Down
25 changes: 10 additions & 15 deletions kong/cli/utils/signal.lua
Original file line number Diff line number Diff line change
Expand Up @@ -37,33 +37,28 @@ end
-- @param path_to_check Path to the binary
-- @return true or false
local function is_openresty(path_to_check)
if IO.file_exists(path_to_check) then
local cmd = path_to_check.." -v"
local out, code = IO.os_execute(cmd)
if code ~= 0 then
cutils.logger:error_exit(out)
end
return out:match("^nginx version: ngx_openresty/")
or out:match("^nginx version: openresty/")
or out:match("^nginx version: nginx/[%w.%s]+%(nginx%-plus%-extras.+%)")
end
return false
local cmd = path_to_check.." -v"
local out = IO.os_execute(cmd)
return out:match("^nginx version: ngx_openresty/")
or out:match("^nginx version: openresty/")
or out:match("^nginx version: nginx/[%w.%s]+%(nginx%-plus%-extras.+%)")
end

-- Paths where to search for an `nginx` executable in addition to the usual $PATH
-- Preferred paths where to search for an `nginx` executable in priority to the $PATH
local NGINX_BIN = "nginx"
local NGINX_SEARCH_PATHS = {
"/usr/local/openresty/nginx/sbin/",
"/usr/local/opt/openresty/bin/",
"/usr/local/bin/",
"/usr/sbin/"
"/usr/sbin/",
"" -- to check the $PATH
}

-- Try to find an `nginx` executable in defined paths, or in $PATH
-- @return Path to found executable or nil if none was found
local function find_nginx()
for i = 1, #NGINX_SEARCH_PATHS + 1 do
local prefix = NGINX_SEARCH_PATHS[i] and NGINX_SEARCH_PATHS[i] or ""
for i = 1, #NGINX_SEARCH_PATHS do
local prefix = NGINX_SEARCH_PATHS[i]
local to_check = prefix..NGINX_BIN
if is_openresty(to_check) then
return to_check
Expand Down
2 changes: 1 addition & 1 deletion kong/constants.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
local VERSION = "0.5.1"
local VERSION = "0.5.2"

return {
NAME = "kong",
Expand Down
2 changes: 1 addition & 1 deletion kong/kong.lua
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ function _M.exec_plugins_access()
for _, plugin_t in ipairs(plugins) do
if ngx.ctx.api then
ngx.ctx.plugin[plugin_t.name] = load_plugin(ngx.ctx.api.id, nil, plugin_t.name)
local consumer_id = ngx.ctx.authenticated_entity and ngx.ctx.authenticated_entity.consumer_id or nil
local consumer_id = ngx.ctx.authenticated_credential and ngx.ctx.authenticated_credential.consumer_id or nil
if consumer_id then
local app_plugin = load_plugin(ngx.ctx.api.id, consumer_id, plugin_t.name)
if app_plugin then
Expand Down
4 changes: 2 additions & 2 deletions kong/plugins/acl/access.lua
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ local _M = {}

function _M.execute(conf)
local consumer_id
if ngx.ctx.authenticated_entity then
consumer_id = ngx.ctx.authenticated_entity.consumer_id
if ngx.ctx.authenticated_credential then
consumer_id = ngx.ctx.authenticated_credential.consumer_id
else
return responses.send_HTTP_FORBIDDEN("Cannot identify the consumer, add an authentication plugin to use the ACL plugin")
end
Expand Down
2 changes: 1 addition & 1 deletion kong/plugins/basic-auth/access.lua
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ function _M.execute(conf)
ngx.req.set_header(constants.HEADERS.CONSUMER_CUSTOM_ID, consumer.custom_id)
ngx.req.set_header(constants.HEADERS.CONSUMER_USERNAME, consumer.username)
ngx.req.set_header(constants.HEADERS.CREDENTIAL_USERNAME, credential.username)
ngx.ctx.authenticated_entity = credential
ngx.ctx.authenticated_credential = credential
end

return _M
30 changes: 15 additions & 15 deletions kong/plugins/hmac-auth/access.lua
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ local split = stringy.split
local AUTHORIZATION = "authorization"
local PROXY_AUTHORIZATION = "proxy-authorization"
local DATE = "date"
local X_DATE = "x-date"
local SIGNATURE_NOT_VALID = "HMAC signature cannot be verified"

local _M = {}
Expand All @@ -36,7 +37,7 @@ local function retrieve_hmac_fields(request, headers, header_name, conf)
local m, err = iterator()
if err then
ngx_log(ngx.ERR, err)
return
return
end

if m and #m >= 4 then
Expand Down Expand Up @@ -66,7 +67,7 @@ local function create_hash(request, hmac_params, headers)
if not header_value then
if header == "request-line" then
-- request-line in hmac headers list
signing_string = signing_string..split(request.raw_header(), "\r\n")[1]
signing_string = signing_string..split(request.raw_header(), "\r\n")[1]
else
signing_string = signing_string..header..":"
end
Expand All @@ -75,9 +76,8 @@ local function create_hash(request, hmac_params, headers)
end
if i < count then
signing_string = signing_string.."\n"
end
end
end

return ngx_sha1(hmac_params.secret, signing_string)
end

Expand Down Expand Up @@ -109,14 +109,14 @@ local function load_credential(username)
return credential
end

local function validate_clock_skew(headers, allowed_clock_skew)
local date = headers[DATE]
local function validate_clock_skew(headers, date_header_name, allowed_clock_skew)
local date = headers[date_header_name]
if not date then
return false
end

local requestTime, err = ngx_parse_time(date)
if err then
local requestTime = ngx_parse_time(date)
if not requestTime then
return false
end

Expand All @@ -125,7 +125,7 @@ local function validate_clock_skew(headers, allowed_clock_skew)
return false
end
return true
end
end

function _M.execute(conf)
local headers = ngx_set_headers();
Expand All @@ -136,10 +136,10 @@ function _M.execute(conf)
end

-- validate clock skew
if not validate_clock_skew(headers, conf.clock_skew) then
responses.send_HTTP_FORBIDDEN("HMAC signature cannot be verified, a valid date field is required for HMAC Authentication")
if not (validate_clock_skew(headers, X_DATE, conf.clock_skew) or validate_clock_skew(headers, DATE, conf.clock_skew)) then
responses.send_HTTP_FORBIDDEN("HMAC signature cannot be verified, a valid date or x-date header is required for HMAC Authentication")
end

-- retrieve hmac parameter from Proxy-Authorization header
local hmac_params = retrieve_hmac_fields(ngx.req, headers, PROXY_AUTHORIZATION, conf)
-- Try with the authorization header
Expand All @@ -154,7 +154,7 @@ function _M.execute(conf)
local credential = load_credential(hmac_params.username)
if not credential then
responses.send_HTTP_FORBIDDEN(SIGNATURE_NOT_VALID)
end
end
hmac_params.secret = credential.secret
if not validate_signature(ngx.req, hmac_params, headers) then
ngx.ctx.stop_phases = true -- interrupt other phases of this request
Expand All @@ -174,7 +174,7 @@ function _M.execute(conf)
ngx_set_header(constants.HEADERS.CONSUMER_CUSTOM_ID, consumer.custom_id)
ngx_set_header(constants.HEADERS.CONSUMER_USERNAME, consumer.username)
ngx.req.set_header(constants.HEADERS.CREDENTIAL_USERNAME, credential.username)
ngx.ctx.authenticated_entity = secret
ngx.ctx.authenticated_credential = credential
end

return _M
return _M
2 changes: 1 addition & 1 deletion kong/plugins/jwt/access.lua
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ function _M.execute(conf)
ngx.req.set_header(constants.HEADERS.CONSUMER_ID, consumer.id)
ngx.req.set_header(constants.HEADERS.CONSUMER_CUSTOM_ID, consumer.custom_id)
ngx.req.set_header(constants.HEADERS.CONSUMER_USERNAME, consumer.username)
ngx.ctx.authenticated_entity = consumer
ngx.ctx.authenticated_credential = jwt_secret
end

return _M
2 changes: 1 addition & 1 deletion kong/plugins/key-auth/access.lua
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ function _M.execute(conf)
ngx.req.set_header(constants.HEADERS.CONSUMER_ID, consumer.id)
ngx.req.set_header(constants.HEADERS.CONSUMER_CUSTOM_ID, consumer.custom_id)
ngx.req.set_header(constants.HEADERS.CONSUMER_USERNAME, consumer.username)
ngx.ctx.authenticated_entity = credential
ngx.ctx.authenticated_credential = credential
end

return _M
10 changes: 9 additions & 1 deletion kong/plugins/log-serializers/basic.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
local _M = {}

function _M.serialize(ngx)
local authenticated_entity
if ngx.ctx.authenticated_credential ~= nil then
authenticated_entity = {
id = ngx.ctx.authenticated_credential.id,
consumer_id = ngx.ctx.authenticated_credential.consumer_id
}
end

return {
request = {
uri = ngx.var.request_uri,
Expand All @@ -22,7 +30,7 @@ function _M.serialize(ngx)
proxy = ngx.var.upstream_response_time * 1000,
request = ngx.var.request_time * 1000
},
authenticated_entity = ngx.ctx.authenticated_entity,
authenticated_entity = authenticated_entity,
api = ngx.ctx.api,
client_ip = ngx.var.remote_addr,
started_at = ngx.req.start_time() * 1000
Expand Down
8 changes: 5 additions & 3 deletions kong/plugins/oauth2/access.lua
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,9 @@ local function get_redirect_uri(client_id)
end

local function is_https()
return ngx.var.scheme:lower() == "https"
local forwarded_proto_header = ngx.req.get_headers()["x-forwarded-proto"]

return ngx.var.scheme:lower() == "https" or (forwarded_proto_header and forwarded_proto_header:lower() == "https")
end

local function retrieve_parameters()
Expand Down Expand Up @@ -250,7 +252,7 @@ local function issue_token(conf)
end
elseif grant_type == GRANT_CLIENT_CREDENTIALS then
-- Only check the provision_key if the authenticated_userid is being set
if parameters.authenticated_userid and conf.provision_key ~= parameters.provision_key then
if parameters.authenticated_userid and conf.provision_key ~= parameters.provision_key then
response_params = {[ERROR] = "invalid_provision_key", error_description = "Invalid Kong provision_key"}
else
-- Check scopes
Expand Down Expand Up @@ -412,7 +414,7 @@ function _M.execute(conf)
ngx.req.set_header(constants.HEADERS.CONSUMER_USERNAME, consumer.username)
ngx.req.set_header("x-authenticated-scope", token.scope)
ngx.req.set_header("x-authenticated-userid", token.authenticated_userid)
ngx.ctx.authenticated_entity = credential
ngx.ctx.authenticated_credential = credential
end

return _M
8 changes: 4 additions & 4 deletions kong/plugins/rate-limiting/access.lua
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ local _M = {}
local function get_identifier()
local identifier

-- Consumer is identified by ip address or authenticated_entity id
if ngx.ctx.authenticated_entity then
identifier = ngx.ctx.authenticated_entity.id
-- Consumer is identified by ip address or authenticated_credential id
if ngx.ctx.authenticated_credential then
identifier = ngx.ctx.authenticated_credential.id
else
identifier = ngx.var.remote_addr
end
Expand Down Expand Up @@ -56,7 +56,7 @@ end
function _M.execute(conf)
local current_timestamp = timestamp.get_utc()

-- Consumer is identified by ip address or authenticated_entity id
-- Consumer is identified by ip address or authenticated_credential id
local identifier = get_identifier()

local api_id = ngx.ctx.api.id
Expand Down
8 changes: 4 additions & 4 deletions kong/plugins/response-ratelimiting/access.lua
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ local _M = {}
local function get_identifier()
local identifier

-- Consumer is identified by ip address or authenticated_entity id
if ngx.ctx.authenticated_entity then
identifier = ngx.ctx.authenticated_entity.id
-- Consumer is identified by ip address or authenticated_credential id
if ngx.ctx.authenticated_credential then
identifier = ngx.ctx.authenticated_credential.id
else
identifier = ngx.var.remote_addr
end
Expand Down Expand Up @@ -47,7 +47,7 @@ function _M.execute(conf)
end

-- Load info
local current_timestamp = timestamp.get_utc()
local current_timestamp = timestamp.get_utc()
ngx.ctx.current_timestamp = current_timestamp -- For later use
local api_id = ngx.ctx.api.id
local identifier = get_identifier()
Expand Down
2 changes: 1 addition & 1 deletion kong/tools/io.lua
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ function _M.file_size(path)
end

--- Load a yaml configuration file.
-- The return config will get 2 extra fields; `pid_file` of the nginx process
-- The return config will get 2 extra fields; `pid_file` of the nginx process
-- and `dao_config` as a shortcut to the dao configuration
-- @param configuration_path path to configuration file to load
-- @return config Loaded configuration table
Expand Down
Loading

0 comments on commit 10fe05a

Please sign in to comment.