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

use backend http client #456

Merged
merged 14 commits into from
Nov 6, 2017
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
95 changes: 23 additions & 72 deletions apicast/conf.d/apicast.conf
Original file line number Diff line number Diff line change
Expand Up @@ -9,30 +9,35 @@ set_by_lua_block $deployment {
# ssl_session_fetch_by_lua_block { require('module').call() }
# ssl_session_store_by_lua_block { require('module').call() }

location = /threescale_authrep {
location = /___http_call {
internal;

set_by_lua_block $log {
local log = ngx.var.arg_log;
if log then return '&' .. ngx.unescape_uri(log) end
}
set_by_lua_block $backend_endpoint { return ngx.ctx.backend_endpoint }
set $path /transactions/authrep.xml?$backend_authentication_type=$backend_authentication_value&service_id=$service_id&$usage&$credentials$log;
set $url '';

set $endpoint '';

set $host_header '';
set $connection_header 'close';
set $options '';
set $grant_type '';

proxy_pass $endpoint;
proxy_pass_request_headers off;
proxy_pass_request_body on;
proxy_http_version 1.1;
proxy_pass $backend_endpoint$path;
proxy_set_header Host "$backend_host";
proxy_set_header User-Agent "$user_agent";
proxy_set_header X-3scale-User-Agent "$deployment";
proxy_set_header X-3scale-Version "$version";
proxy_set_header Connection "";

# Enable the option to receive the rejection reason in the
# '3scale-rejection-reason' header of the response.
proxy_set_header 3scale-options "rejection_reason_header=1";
proxy_set_header Host $host_header;
proxy_set_header Connection $connection_header;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-3scale-User-Agent $deployment;
proxy_set_header X-3scale-Version $version;
proxy_set_header User-Agent $user_agent;
proxy_set_header X-3scale-OAuth2-Grant-Type $grant_type;
proxy_set_header 3scale-options $options;

rewrite_by_lua_block {
ngx.var.real_url = ngx.var.backend_endpoint .. ngx.var.path
require('resty.http_ng.backend.ngx'):resolver()
}
}

Expand All @@ -42,7 +47,6 @@ location @out_of_band_authrep_action {
proxy_pass_request_headers off;

set_by_lua $original_request_time 'return ngx.var.request_time';
set_by_lua $backend_endpoint 'return ngx.var.post_action_backend_endpoint';

content_by_lua_block { require('module'):post_action() }

Expand All @@ -52,9 +56,6 @@ location @out_of_band_authrep_action {
}
}

set $backend_endpoint 'http://127.0.0.1:8081';


location / {
set $cached_key null;
set $credentials null;
Expand All @@ -72,7 +73,7 @@ location / {
set $post_action_backend_endpoint '';
set $backend_authentication_type null;
set $backend_authentication_value null;
set $version null;
set $version '';
set $real_url null;

set $post_action_impact null;
Expand Down Expand Up @@ -100,56 +101,6 @@ location / {
include ../apicast.d/location.d/*.conf;
}

location = /_threescale/oauth_store_token {
internal;
proxy_pass_request_headers off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host "$backend_host";
proxy_set_header User-Agent "$user_agent";
proxy_set_header X-3scale-User-Agent "$deployment";
proxy_set_header X-3scale-Version "$version";

proxy_pass $backend_endpoint/services/$service_id/oauth_access_tokens.xml?$backend_authentication_type=$backend_authentication_value;
}

location = /_threescale/check_credentials {
internal;

proxy_pass_request_headers off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host "$backend_host";
proxy_set_header User-Agent "$user_agent";
proxy_set_header X-3scale-User-Agent "$deployment";
proxy_set_header X-3scale-Version "$version";

proxy_pass $backend_endpoint/transactions/oauth_authorize.xml?$backend_authentication_type=$backend_authentication_value&service_id=$service_id&$args;
}

location = /threescale_oauth_authrep {
internal;

set_by_lua_block $log {
local log = ngx.var.arg_log;
if log then return '&' .. ngx.unescape_uri(log) end
}
set $path /transactions/oauth_authrep.xml?$backend_authentication_type=$backend_authentication_value&service_id=$service_id&$usage&$credentials$log;
proxy_pass_request_headers off;
proxy_http_version 1.1;
proxy_pass $backend_endpoint$path;
proxy_set_header Host "$backend_host";
proxy_set_header User-Agent "$user_agent";
proxy_set_header X-3scale-User-Agent "$deployment";
proxy_set_header X-3scale-Version "$version";
proxy_set_header Connection "";
proxy_set_header X-3scale-OAuth2-Grant-Type "authorization_code";

rewrite_by_lua_block {
ngx.var.real_url = ngx.var.backend_endpoint .. ngx.var.path
}
}

# This exposes a health check for kubernetes environments
# This is so the healtcheck on our Google HTTP load balancers works
location /_threescale/healthz {
Expand Down
7 changes: 4 additions & 3 deletions apicast/http.d/upstream.conf
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

upstream upstream {
server 0.0.0.1:1;

Expand All @@ -7,10 +6,12 @@ upstream upstream {
keepalive 1024;
}

upstream backend_upstream {
upstream http_client {
server 0.0.0.1:1;

balancer_by_lua_block { require('module'):balancer() }
balancer_by_lua_block {
require('resty.http_ng.backend.ngx'):balancer()
}

keepalive 1024;
}
4 changes: 2 additions & 2 deletions apicast/src/backend/cache_handler.lua
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ function _M.handlers.strict(cache, cached_key, response, ttl)
else
ngx.log(ngx.NOTICE, 'apicast cache delete key: ', cached_key, ' cause status ', response.status)
cache:delete(cached_key)
return false, rejection_reason(response.header)
return false, rejection_reason(response.headers)
end
end

Expand All @@ -69,7 +69,7 @@ function _M.handlers.resilient(cache, cached_key, response, ttl)
cache:set(cached_key, status, ttl or 0)

local authorized = (status == 200)
return authorized, (not authorized and rejection_reason(response.header))
return authorized, (not authorized and rejection_reason(response.headers))
end
end

Expand Down
88 changes: 65 additions & 23 deletions apicast/src/backend_client.lua
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@ local setmetatable = setmetatable
local concat = table.concat
local insert = table.insert
local len = string.len
local format = string.format

local http_ng = require('resty.http_ng')
local user_agent = require('user_agent')
local resty_url = require('resty.url')
local resty_env = require('resty.env')

local _M = {
endpoint = resty_env.get("BACKEND_ENDPOINT_OVERRIDE")
Copy link
Contributor Author

@mikz mikz Oct 23, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be ignoring empty string by using env.value instead.


}

Expand All @@ -29,8 +31,8 @@ local mt = { __index = _M }
-- @tparam Service service object with service definition
-- @tparam http_ng.backend http_client async/test/custom http backend
-- @treturn backend_client
function _M.new(_, service, http_client)
local endpoint = service.backend.endpoint or ngx.var.backend_endpoint
function _M:new(service, http_client)
local endpoint = self.endpoint or service.backend.endpoint or error('missing endpoint')
local service_id = service.id

if not endpoint then
Expand All @@ -39,7 +41,7 @@ function _M.new(_, service, http_client)

local authentication = { service_id = service_id }

if service.backend_authentication.type then
if service.backend_authentication and service.backend_authentication.type then
authentication[service.backend_authentication.type] = service.backend_authentication.value
end

Expand All @@ -54,7 +56,7 @@ function _M.new(_, service, http_client)
options = {
headers = {
user_agent = user_agent(),
host = service.backend.host or backend[4]
host = service.backend and service.backend.host or backend[4],
},
ssl = { verify = resty_env.enabled('OPENSSL_VERIFY') }
}
Expand All @@ -69,40 +71,65 @@ function _M.new(_, service, http_client)
}, mt)
end

local function call_backend_transaction(self, path, ...)
local version = self.version
local http_client = self.http_client
local function build_args(args)
local query = {}

if not version or not http_client then
return nil, 'not initialized'
for i=1, #args do
local arg = ngx.encode_args(args[i])
if len(arg) > 0 then
insert(query, arg)
end
end

return concat(query, '&')
end

local function build_url(self, path, ...)
local endpoint = self.endpoint

if not endpoint then
return nil, 'missing endpoint'
end


local args = { self.authentication, ... }
return resty_url.join(endpoint, '', path .. '?' .. build_args(args))
end

local query = {}
for i=1, #args do
local arg = ngx.encode_args(args[i])
if len(arg) > 0 then
insert(query, arg)
end
end
local function call_backend_transaction(self, path, options, ...)
local http_client = self.http_client

local url = resty_url.join(endpoint, '/transactions', path .. '?' .. concat(query, '&'))
if not http_client then
return nil, 'not initialized'
end

local res = http_client.get(url)
local url = build_url(self, path, ...)
local res = http_client.get(url, options)

ngx.log(ngx.INFO, 'backend client uri: ', url, ' ok: ', res.ok, ' status: ', res.status, ' body: ', res.body)

return res
end

local function authrep_path(using_oauth)
return (using_oauth and '/transactions/oauth_authrep.xml') or
'/transactions/authrep.xml'
end

local function auth_path(using_oauth)
return (using_oauth and '/transactions/oauth_authorize.xml') or
'/transactions/authorize.xml'
end

local function create_token_path(service_id)
return format('/services/%s/oauth_access_tokens.xml', service_id)
end

local authorize_options = {
headers = {
['3scale-options'] = 'rejection_reason_header=1'
}
}

--- Call authrep (oauth_authrep) on backend.
-- @tparam ?{table,...} query list of query parameters
-- @treturn http_ng.response http response
Expand All @@ -111,8 +138,8 @@ function _M:authrep(...)
return nil, 'not initialized'
end

local auth_uri = self.version == 'oauth' and 'oauth_authrep.xml' or 'authrep.xml'
return call_backend_transaction(self, auth_uri, ...)
local auth_uri = authrep_path(self.version == 'oauth')
return call_backend_transaction(self, auth_uri, authorize_options, ...)
end

--- Call authorize (oauth_authorize) on backend.
Expand All @@ -123,8 +150,23 @@ function _M:authorize(...)
return nil, 'not initialized'
end

local auth_uri = self.version == 'oauth' and 'oauth_authorize.xml' or 'authorize.xml'
return call_backend_transaction(self, auth_uri, ...)
local auth_uri = auth_path(self.version == 'oauth')
return call_backend_transaction(self, auth_uri, authorize_options, ...)
end

--- Calls backend to create an oauth token.
-- @tparam ?{table, ...} list of query params (might include the token, ttl,
-- app_id, and user_id)
-- @treturn http_ng.response http response
function _M:store_oauth_token(token_info)
local http_client = self.http_client

if not http_client then
return nil, 'not initialized'
end

local url = build_url(self, create_token_path(self.service_id))
return http_client.post(url, token_info)
end

return _M
18 changes: 7 additions & 11 deletions apicast/src/oauth/apicast_oauth/authorize.lua
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
local random = require 'resty.random'
local ts = require 'threescale_utils'
local backend_client = require('backend_client')
local http_ng_ngx = require('resty.http_ng.backend.ngx')

-- returns a unique string for the client_id. it will be short lived
local function nonce(client_id)
Expand Down Expand Up @@ -81,16 +83,9 @@ end


-- Check valid params ( client_id / secret / redirect_url, whichever are sent) against 3scale
local function check_credentials(params)
local res = ngx.location.capture("/_threescale/check_credentials",
{
args = {
app_id = params.client_id,
redirect_uri = params.redirect_uri
},
copy_all_vars = true,
ctx = ngx.ctx
})
local function check_credentials(service, params)
local backend = assert(backend_client:new(service, http_ng_ngx), 'missing backend')
local res = backend:authorize({ app_id = params.client_id, redirect_uri = params.redirect_uri })

ngx.log(ngx.INFO, "[oauth] Checking client credentials, status: ", res.status, " body: ", res.body)

Expand All @@ -103,7 +98,8 @@ local _M = {

function _M.call()
local params = extract_params()
local is_valid = check_credentials(params)
local service = ngx.ctx.service
local is_valid = check_credentials(service, params)

if is_valid then
ngx.log(ngx.DEBUG, 'oauth params valid')
Expand Down
Loading