From ba64ff28c2137aa32421406a37ebeed18b4f32e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andres=20Mu=C3=B1oz?= Date: Thu, 26 Oct 2017 12:14:38 +0200 Subject: [PATCH 01/27] The configuration file was modified to include two additional fields inside of the gatekeeper configuration for managing token validation with FIWARE Wilma PEP Poxy, this fields allow to define the PEP proxy host and port to establish the connection. The caching option was changed to false because the token validation option doesn't allow caching yet. Also, the error messages defined in the api settings were changed for including token as other validation method. --- config/default.yml | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/config/default.yml b/config/default.yml index a1b7a5352..3964a7ec5 100644 --- a/config/default.yml +++ b/config/default.yml @@ -58,7 +58,9 @@ gatekeeper: - header - getParam - basicAuthUsername - api_key_cache: true + api_key_cache: false + pep_host: 127.0.0.1 # ip or hostname of Pep Proxy host + pep_port: 8090 # listen port of Pep Proxy trafficserver: host: 127.0.0.1 port: 14009 @@ -282,12 +284,12 @@ apiSettings: message: The requested URL was not found on this server. api_key_missing: status_code: 403 - code: API_KEY_MISSING - message: No api_key was supplied. Get one at {{signup_url}} + code: API_KEY_OR_TOKEN_MISSING + message: No api_key or token was supplied. Get one at {{signup_url}} api_key_invalid: status_code: 403 - code: API_KEY_INVALID - message: An invalid api_key was supplied. Get one at {{signup_url}} + code: API_KEY_OR_TOKEN_INVALID + message: An invalid api_key or token was supplied. Get one at {{signup_url}} api_key_disabled: status_code: 403 code: API_KEY_DISABLED @@ -298,8 +300,8 @@ apiSettings: message: The api_key supplied has not been verified yet. Please check your e-mail to verify the API key. Contact us at {{contact_url}} for assistance api_key_unauthorized: status_code: 403 - code: API_KEY_UNAUTHORIZED - message: The api_key supplied is not authorized to access the given service. Contact us at {{contact_url}} for assistance + code: API_KEY_OR_TOKEN_UNAUTHORIZED + message: The api_key or token supplied is not authorized to access the given service. Contact us at {{contact_url}} for assistance over_rate_limit: status_code: 429 code: OVER_RATE_LIMIT @@ -368,4 +370,4 @@ ban: message: "Please contact us for assistance." ember_server: port: 14050 - live_reload_port: 14051 +live_reload_port: 14051 \ No newline at end of file From 6c1280e364e394048442c0d918d102a5dd5fd1bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andres=20Mu=C3=B1oz?= Date: Thu, 26 Oct 2017 12:28:02 +0200 Subject: [PATCH 02/27] In this file, I include two more nginx server variables for checking the word "token" in the url and the header "X-Auth-Token" in the requests made to the platform. With this change is possible to manage and differentiate if the user made a request using an API_Key or OAuth Token --- src/api-umbrella/proxy/hooks/rewrite.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/api-umbrella/proxy/hooks/rewrite.lua b/src/api-umbrella/proxy/hooks/rewrite.lua index af0a2268f..d238ea134 100644 --- a/src/api-umbrella/proxy/hooks/rewrite.lua +++ b/src/api-umbrella/proxy/hooks/rewrite.lua @@ -17,6 +17,7 @@ wait_for_setup() -- ngx.var lookups are apparently somewhat expensive. ngx.ctx.args = ngx_var.args ngx.ctx.arg_api_key = ngx_var.arg_api_key +ngx.ctx.arg_token = ngx_var.arg_token if(config["router"]["match_x_forwarded_host"]) then ngx.ctx.host = ngx_var.http_x_forwarded_host or ngx_var.http_host or ngx_var.host else @@ -24,6 +25,7 @@ else end ngx.ctx.host_normalized = host_normalize(ngx.ctx.host) ngx.ctx.http_x_api_key = ngx_var.http_x_api_key +ngx.ctx.http_x_auth_token = ngx_var.http_x_auth_token ngx.ctx.port = ngx_var.real_port ngx.ctx.protocol = ngx_var.real_scheme ngx.ctx.remote_addr = ngx_var.remote_addr @@ -69,4 +71,4 @@ else else error_handler(api_err) end -end +end \ No newline at end of file From 254988bae12df284d0ce89f3c2feeb6f035a7187 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andres=20Mu=C3=B1oz?= Date: Thu, 26 Oct 2017 12:45:03 +0200 Subject: [PATCH 03/27] This file was modified for including the token validation, the methods allowed to pass the token are by param and header. The variable api_key was changed by a key, value table, this table has two values, fist the key_value that stores the value of the api_key or the token, and the second value called key_type which stores the type of key provided by the user, it can take two values token or api_key All the variables that previously stored the api_key value, was changed to store api_key ["key_value"], that represents exactly the same value using the new api_key table. --- .../proxy/middleware/api_key_validator.lua | 41 +++++++++++++------ 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/src/api-umbrella/proxy/middleware/api_key_validator.lua b/src/api-umbrella/proxy/middleware/api_key_validator.lua index ab1447b32..5c6e691b1 100644 --- a/src/api-umbrella/proxy/middleware/api_key_validator.lua +++ b/src/api-umbrella/proxy/middleware/api_key_validator.lua @@ -6,32 +6,47 @@ local is_empty = types.is_empty local function resolve_api_key() local api_key_methods = config["gatekeeper"]["api_key_methods"] - local api_key + local key = {key_value="", key_type="" } + -- The api_key variable is a dictionary compose by two elements, the key_value which stores + -- the api_key value or the user token value and the key_type field in where is stored + -- the type of key that was provided by the user, it value could be an api_key or a token. + -- The validation process is made for all the api_key_methods (except basicAuthUsername) + -- declared in the configuration file checking if the user sends an api_key or token + -- Only the header and get_param methods are supported by the token validation. for _, method in ipairs(api_key_methods) do - if method == "header" then - api_key = ngx.ctx.http_x_api_key - elseif method == "getParam" then - api_key = ngx.ctx.arg_api_key - elseif method == "basicAuthUsername" then - api_key = ngx.ctx.remote_user + if method == "header" and ngx.ctx.http_x_api_key then + key.key_value = ngx.ctx.http_x_api_key + key.key_type = "api_key" + elseif ngx.ctx.http_x_auth_token then + key.key_value = ngx.ctx.http_x_auth_token + key.key_type = "token" + elseif method == "getParam" and ngx.ctx.arg_api_key then + key.key_value = ngx.ctx.arg_api_key + key.key_type = "api_key" + elseif ngx.ctx.arg_token then + key.key_value = ngx.ctx.arg_token + key.key_type = "token" + elseif method == "basicAuthUsername" and ngx.ctx.remote_user then + key.key_value = ngx.ctx.remote_user + key.key_type = "api_key" end - if not is_empty(api_key) then + if not is_empty(key["key_value"]) then break end end -- Store the api key for logging. - ngx.ctx.api_key = api_key + ngx.ctx.api_key = key["key_value"] - return api_key + return key end return function(settings) -- Find the API key in the header, query string, or HTTP auth. local api_key = resolve_api_key() - if is_empty(api_key) then + if is_empty(api_key["key_value"]) then if settings and settings["disable_api_key"] then return nil else @@ -47,7 +62,7 @@ return function(settings) -- Store the api key on the user object for easier access (the user object -- doesn't contain it directly, to save memory storage in the lookup table). - user["api_key"] = api_key + user["api_key"] = api_key["key_value"] -- Store user details for logging. ngx.ctx.user_id = user["id"] @@ -76,4 +91,4 @@ return function(settings) end return user -end +end \ No newline at end of file From 055407027169912a1a4fa5973b154fc92c0704a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andres=20Mu=C3=B1oz?= Date: Thu, 26 Oct 2017 12:57:42 +0200 Subject: [PATCH 04/27] This function usually is used for inverting the roles table, it was modified to allow and parse a roles tables that have more than one value by rol, for example: if the function receives the roles in this format Roles":[{"name":"rol1","id":"16"}]. With the modification the function checks if the roles value has more than one value and takes only the value for the key "name" ant after that invert the table. --- src/api-umbrella/utils/invert_table.lua | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/api-umbrella/utils/invert_table.lua b/src/api-umbrella/utils/invert_table.lua index 5d0000f22..126b8f38e 100644 --- a/src/api-umbrella/utils/invert_table.lua +++ b/src/api-umbrella/utils/invert_table.lua @@ -1,8 +1,18 @@ return function(table) + local numItems = 0 local inverted = {} for key, value in pairs(table) do - inverted[value] = key + if type(value)=="string" then + inverted[value] = key + else + for k,v in pairs(value) do + numItems = numItems + 1 + end + if numItems > 1 then + value = value["name"] + end + inverted[value] = key + end end - return inverted -end +end \ No newline at end of file From 07e2aa5c66fbfb017931b7e64f7798fe75bec517 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andres=20Mu=C3=B1oz?= Date: Thu, 26 Oct 2017 13:04:18 +0200 Subject: [PATCH 05/27] This function allows to connect with the Pep Proxy service for checking if the token is valid and retrieve the user information. The function takes the PEP Proxy host and port as parameters and sends a request with the header X-Auth-Token and the value of the token provided by the user. If the token is valid, PEP proxy sends a response with the user information asociated to the token, otherwise, it sends a message indicating the result of the validation process with his status, 404 , 402, etc. --- src/api-umbrella/utils/pep.lua | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 src/api-umbrella/utils/pep.lua diff --git a/src/api-umbrella/utils/pep.lua b/src/api-umbrella/utils/pep.lua new file mode 100644 index 000000000..33e7119d1 --- /dev/null +++ b/src/api-umbrella/utils/pep.lua @@ -0,0 +1,27 @@ +local http = require "resty.http" +local cjson = require "cjson" +local _M = {} +-- Function to connect with the Pep Proxy service for checking if the token is valid and retrieve +-- the user properties. The function takes the PEP Proxy host and port as parameters +-- and sends a request with the header X-Auth-Token with the value of the token provided +-- by the user. If the token is valid, PEP proxy sends a response with the user information +-- asociated to the token, otherwise, it sends a message indicating the result of the +-- validation process with his status, 404 , 402, etc. +function _M.first(host, port, token) + local result + local httpc = http.new() + httpc:set_timeout(45000) + httpc:connect(host,port) + local res, err = httpc:request({headers = {["X-Auth-Token"] = token}}) + if res and res.status == 200 then + local body, body_err = res:read_body() + if not body then + return nil, body_err + end + result = cjson.decode(body) + end + + return result, err +end + +return _M \ No newline at end of file From bbf9f0b05fdba3729dbe787a84ded63b05f359ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andres=20Mu=C3=B1oz?= Date: Thu, 26 Oct 2017 14:54:18 +0200 Subject: [PATCH 06/27] The user_store function was modified for including the token validation, for achieving this, an extra validation through the key_type value of the api_key variable was used. If the key_value is equal to "api_key", the key_value is checked in the Mongo database. In case of the value of key_values is equal to "token", the token is sent to the PEP Proxy for validation, if the token is valid, the user information is returned. If the user information is retrieved from the database this information is stored in the variables of the platform as usually did. In case that the user information was retrieved using token validation, the variables the Nick_name is assigned to the user_id and the Roles is assigned to the roles of the platform. Moreover, if the user information coming from of the token validation with PEP Proxy doesn't have the value of "email", this field is stored in the platform using the Nick_name value, this value is needed for displaying, the user associated with each request in the Analytics option of the web app . The rest of the changes are related to the reassignment of the api_key variable using api_key ["key_value"] --- src/api-umbrella/proxy/user_store.lua | 56 ++++++++++++++++++++------- 1 file changed, 43 insertions(+), 13 deletions(-) diff --git a/src/api-umbrella/proxy/user_store.lua b/src/api-umbrella/proxy/user_store.lua index 6ca87e4e2..6b943af71 100644 --- a/src/api-umbrella/proxy/user_store.lua +++ b/src/api-umbrella/proxy/user_store.lua @@ -8,19 +8,33 @@ local mongo = require "api-umbrella.utils.mongo" local shcache = require "shcache" local types = require "pl.types" local utils = require "api-umbrella.proxy.utils" +local pep = require "api-umbrella.utils.pep" local cache_computed_settings = utils.cache_computed_settings local is_empty = types.is_empty local function lookup_user(api_key) - local raw_user, err = mongo.first("api_users", { - query = { - api_key = api_key, - }, - }) - - if err then - ngx.log(ngx.ERR, "failed to fetch user from mongodb: ", err) + local raw_user + local db_err + local pep_err + + -- Checking the field of api_key ["key_type"], if the key_type is api_key + -- the api_key value is checked in the database and retrieve the user information + -- else if the key_type is token, the token is checked using PEP Proxy and + -- the user information is retrieved + if not api_key["key_type"] or api_key["key_type"] == "api_key" then + raw_user, db_err = mongo.first("api_users", { + query = { + api_key = api_key["key_value"], + }, + }) + elseif api_key["key_type"] == "token" then + raw_user, pep_err = pep.first(config["gatekeeper"]["pep_host"],config["gatekeeper"]["pep_port"],api_key["key_value"]) + end + if pep_err then + ngx.log(ngx.ERR, "failed to autenticate , status code:", pep_err) + elseif db_err then + ngx.log(ngx.ERR, "failed to fetch user from mongodb", db_err) elseif raw_user then local user = utils.pick_where_present(raw_user, { "created_at", @@ -36,15 +50,31 @@ local function lookup_user(api_key) -- Ensure IDs get stored as strings, even if Mongo ObjectIds are in use. if raw_user["_id"] and raw_user["_id"]["$oid"] then user["id"] = raw_user["_id"]["$oid"] + elseif raw_user.Nick_Name then + user["id"] = raw_user.Nick_Name + if not raw_user.Email then + user["email"] = raw_user.Nick_Name + else + user["email"] = raw_user.Email + end else - user["id"] = raw_user["_id"] + user["id"] = raw_user["_id"] + end + -- If the validation was made using a token, the Nick_Name associate to the token + -- is assigned to the id attribute of the user + if raw_user.Nick_Name then + user["id"] = raw_user.Nick_Name end -- Invert the array of roles into a hashy table for more optimized -- lookups (so we can just check if the key exists, rather than -- looping over each value). + -- Moreover, in case that the user information have been retrieved using a token validation, + -- the roles associated with the token are stored in user ["roles"] if user["roles"] then user["roles"] = invert_table(user["roles"]) + elseif raw_user.Roles then + user["roles"] = invert_table(raw_user.Roles) end if user["created_at"] and user["created_at"]["$date"] then @@ -103,14 +133,14 @@ function _M.get(api_key) return nil end - user = shared_cache:load(api_key) + user = shared_cache:load(api_key["key_value"]) if user then - local_cache:set(api_key, user, 2) + local_cache:set(api_key["key_value"], user, 2) else - local_cache:set(api_key, EMPTY_DATA, 2) + local_cache:set(api_key["key_value"], EMPTY_DATA, 2) end return user end -return _M +return _M \ No newline at end of file From 0e86c300e1e9796df1e962382e55393e147c5397 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andres=20Mu=C3=B1oz?= Date: Tue, 7 Nov 2017 16:26:17 +0100 Subject: [PATCH 07/27] Revert "New feature for OAuth2 Token Validation using Fiware Wilma PEP-Proxy" --- config/default.yml | 18 +++--- src/api-umbrella/proxy/hooks/rewrite.lua | 4 +- .../proxy/middleware/api_key_validator.lua | 41 +++++--------- src/api-umbrella/proxy/user_store.lua | 56 +++++-------------- src/api-umbrella/utils/invert_table.lua | 16 +----- src/api-umbrella/utils/pep.lua | 27 --------- 6 files changed, 38 insertions(+), 124 deletions(-) delete mode 100644 src/api-umbrella/utils/pep.lua diff --git a/config/default.yml b/config/default.yml index 3964a7ec5..a1b7a5352 100644 --- a/config/default.yml +++ b/config/default.yml @@ -58,9 +58,7 @@ gatekeeper: - header - getParam - basicAuthUsername - api_key_cache: false - pep_host: 127.0.0.1 # ip or hostname of Pep Proxy host - pep_port: 8090 # listen port of Pep Proxy + api_key_cache: true trafficserver: host: 127.0.0.1 port: 14009 @@ -284,12 +282,12 @@ apiSettings: message: The requested URL was not found on this server. api_key_missing: status_code: 403 - code: API_KEY_OR_TOKEN_MISSING - message: No api_key or token was supplied. Get one at {{signup_url}} + code: API_KEY_MISSING + message: No api_key was supplied. Get one at {{signup_url}} api_key_invalid: status_code: 403 - code: API_KEY_OR_TOKEN_INVALID - message: An invalid api_key or token was supplied. Get one at {{signup_url}} + code: API_KEY_INVALID + message: An invalid api_key was supplied. Get one at {{signup_url}} api_key_disabled: status_code: 403 code: API_KEY_DISABLED @@ -300,8 +298,8 @@ apiSettings: message: The api_key supplied has not been verified yet. Please check your e-mail to verify the API key. Contact us at {{contact_url}} for assistance api_key_unauthorized: status_code: 403 - code: API_KEY_OR_TOKEN_UNAUTHORIZED - message: The api_key or token supplied is not authorized to access the given service. Contact us at {{contact_url}} for assistance + code: API_KEY_UNAUTHORIZED + message: The api_key supplied is not authorized to access the given service. Contact us at {{contact_url}} for assistance over_rate_limit: status_code: 429 code: OVER_RATE_LIMIT @@ -370,4 +368,4 @@ ban: message: "Please contact us for assistance." ember_server: port: 14050 -live_reload_port: 14051 \ No newline at end of file + live_reload_port: 14051 diff --git a/src/api-umbrella/proxy/hooks/rewrite.lua b/src/api-umbrella/proxy/hooks/rewrite.lua index d238ea134..af0a2268f 100644 --- a/src/api-umbrella/proxy/hooks/rewrite.lua +++ b/src/api-umbrella/proxy/hooks/rewrite.lua @@ -17,7 +17,6 @@ wait_for_setup() -- ngx.var lookups are apparently somewhat expensive. ngx.ctx.args = ngx_var.args ngx.ctx.arg_api_key = ngx_var.arg_api_key -ngx.ctx.arg_token = ngx_var.arg_token if(config["router"]["match_x_forwarded_host"]) then ngx.ctx.host = ngx_var.http_x_forwarded_host or ngx_var.http_host or ngx_var.host else @@ -25,7 +24,6 @@ else end ngx.ctx.host_normalized = host_normalize(ngx.ctx.host) ngx.ctx.http_x_api_key = ngx_var.http_x_api_key -ngx.ctx.http_x_auth_token = ngx_var.http_x_auth_token ngx.ctx.port = ngx_var.real_port ngx.ctx.protocol = ngx_var.real_scheme ngx.ctx.remote_addr = ngx_var.remote_addr @@ -71,4 +69,4 @@ else else error_handler(api_err) end -end \ No newline at end of file +end diff --git a/src/api-umbrella/proxy/middleware/api_key_validator.lua b/src/api-umbrella/proxy/middleware/api_key_validator.lua index 5c6e691b1..ab1447b32 100644 --- a/src/api-umbrella/proxy/middleware/api_key_validator.lua +++ b/src/api-umbrella/proxy/middleware/api_key_validator.lua @@ -6,47 +6,32 @@ local is_empty = types.is_empty local function resolve_api_key() local api_key_methods = config["gatekeeper"]["api_key_methods"] - local key = {key_value="", key_type="" } + local api_key - -- The api_key variable is a dictionary compose by two elements, the key_value which stores - -- the api_key value or the user token value and the key_type field in where is stored - -- the type of key that was provided by the user, it value could be an api_key or a token. - -- The validation process is made for all the api_key_methods (except basicAuthUsername) - -- declared in the configuration file checking if the user sends an api_key or token - -- Only the header and get_param methods are supported by the token validation. for _, method in ipairs(api_key_methods) do - if method == "header" and ngx.ctx.http_x_api_key then - key.key_value = ngx.ctx.http_x_api_key - key.key_type = "api_key" - elseif ngx.ctx.http_x_auth_token then - key.key_value = ngx.ctx.http_x_auth_token - key.key_type = "token" - elseif method == "getParam" and ngx.ctx.arg_api_key then - key.key_value = ngx.ctx.arg_api_key - key.key_type = "api_key" - elseif ngx.ctx.arg_token then - key.key_value = ngx.ctx.arg_token - key.key_type = "token" - elseif method == "basicAuthUsername" and ngx.ctx.remote_user then - key.key_value = ngx.ctx.remote_user - key.key_type = "api_key" + if method == "header" then + api_key = ngx.ctx.http_x_api_key + elseif method == "getParam" then + api_key = ngx.ctx.arg_api_key + elseif method == "basicAuthUsername" then + api_key = ngx.ctx.remote_user end - if not is_empty(key["key_value"]) then + if not is_empty(api_key) then break end end -- Store the api key for logging. - ngx.ctx.api_key = key["key_value"] + ngx.ctx.api_key = api_key - return key + return api_key end return function(settings) -- Find the API key in the header, query string, or HTTP auth. local api_key = resolve_api_key() - if is_empty(api_key["key_value"]) then + if is_empty(api_key) then if settings and settings["disable_api_key"] then return nil else @@ -62,7 +47,7 @@ return function(settings) -- Store the api key on the user object for easier access (the user object -- doesn't contain it directly, to save memory storage in the lookup table). - user["api_key"] = api_key["key_value"] + user["api_key"] = api_key -- Store user details for logging. ngx.ctx.user_id = user["id"] @@ -91,4 +76,4 @@ return function(settings) end return user -end \ No newline at end of file +end diff --git a/src/api-umbrella/proxy/user_store.lua b/src/api-umbrella/proxy/user_store.lua index 6b943af71..6ca87e4e2 100644 --- a/src/api-umbrella/proxy/user_store.lua +++ b/src/api-umbrella/proxy/user_store.lua @@ -8,33 +8,19 @@ local mongo = require "api-umbrella.utils.mongo" local shcache = require "shcache" local types = require "pl.types" local utils = require "api-umbrella.proxy.utils" -local pep = require "api-umbrella.utils.pep" local cache_computed_settings = utils.cache_computed_settings local is_empty = types.is_empty local function lookup_user(api_key) - local raw_user - local db_err - local pep_err - - -- Checking the field of api_key ["key_type"], if the key_type is api_key - -- the api_key value is checked in the database and retrieve the user information - -- else if the key_type is token, the token is checked using PEP Proxy and - -- the user information is retrieved - if not api_key["key_type"] or api_key["key_type"] == "api_key" then - raw_user, db_err = mongo.first("api_users", { - query = { - api_key = api_key["key_value"], - }, - }) - elseif api_key["key_type"] == "token" then - raw_user, pep_err = pep.first(config["gatekeeper"]["pep_host"],config["gatekeeper"]["pep_port"],api_key["key_value"]) - end - if pep_err then - ngx.log(ngx.ERR, "failed to autenticate , status code:", pep_err) - elseif db_err then - ngx.log(ngx.ERR, "failed to fetch user from mongodb", db_err) + local raw_user, err = mongo.first("api_users", { + query = { + api_key = api_key, + }, + }) + + if err then + ngx.log(ngx.ERR, "failed to fetch user from mongodb: ", err) elseif raw_user then local user = utils.pick_where_present(raw_user, { "created_at", @@ -50,31 +36,15 @@ local function lookup_user(api_key) -- Ensure IDs get stored as strings, even if Mongo ObjectIds are in use. if raw_user["_id"] and raw_user["_id"]["$oid"] then user["id"] = raw_user["_id"]["$oid"] - elseif raw_user.Nick_Name then - user["id"] = raw_user.Nick_Name - if not raw_user.Email then - user["email"] = raw_user.Nick_Name - else - user["email"] = raw_user.Email - end else - user["id"] = raw_user["_id"] - end - -- If the validation was made using a token, the Nick_Name associate to the token - -- is assigned to the id attribute of the user - if raw_user.Nick_Name then - user["id"] = raw_user.Nick_Name + user["id"] = raw_user["_id"] end -- Invert the array of roles into a hashy table for more optimized -- lookups (so we can just check if the key exists, rather than -- looping over each value). - -- Moreover, in case that the user information have been retrieved using a token validation, - -- the roles associated with the token are stored in user ["roles"] if user["roles"] then user["roles"] = invert_table(user["roles"]) - elseif raw_user.Roles then - user["roles"] = invert_table(raw_user.Roles) end if user["created_at"] and user["created_at"]["$date"] then @@ -133,14 +103,14 @@ function _M.get(api_key) return nil end - user = shared_cache:load(api_key["key_value"]) + user = shared_cache:load(api_key) if user then - local_cache:set(api_key["key_value"], user, 2) + local_cache:set(api_key, user, 2) else - local_cache:set(api_key["key_value"], EMPTY_DATA, 2) + local_cache:set(api_key, EMPTY_DATA, 2) end return user end -return _M \ No newline at end of file +return _M diff --git a/src/api-umbrella/utils/invert_table.lua b/src/api-umbrella/utils/invert_table.lua index 126b8f38e..5d0000f22 100644 --- a/src/api-umbrella/utils/invert_table.lua +++ b/src/api-umbrella/utils/invert_table.lua @@ -1,18 +1,8 @@ return function(table) - local numItems = 0 local inverted = {} for key, value in pairs(table) do - if type(value)=="string" then - inverted[value] = key - else - for k,v in pairs(value) do - numItems = numItems + 1 - end - if numItems > 1 then - value = value["name"] - end - inverted[value] = key - end + inverted[value] = key end + return inverted -end \ No newline at end of file +end diff --git a/src/api-umbrella/utils/pep.lua b/src/api-umbrella/utils/pep.lua deleted file mode 100644 index 33e7119d1..000000000 --- a/src/api-umbrella/utils/pep.lua +++ /dev/null @@ -1,27 +0,0 @@ -local http = require "resty.http" -local cjson = require "cjson" -local _M = {} --- Function to connect with the Pep Proxy service for checking if the token is valid and retrieve --- the user properties. The function takes the PEP Proxy host and port as parameters --- and sends a request with the header X-Auth-Token with the value of the token provided --- by the user. If the token is valid, PEP proxy sends a response with the user information --- asociated to the token, otherwise, it sends a message indicating the result of the --- validation process with his status, 404 , 402, etc. -function _M.first(host, port, token) - local result - local httpc = http.new() - httpc:set_timeout(45000) - httpc:connect(host,port) - local res, err = httpc:request({headers = {["X-Auth-Token"] = token}}) - if res and res.status == 200 then - local body, body_err = res:read_body() - if not body then - return nil, body_err - end - result = cjson.decode(body) - end - - return result, err -end - -return _M \ No newline at end of file From a0166f4b74bc527875a12de10f994f06c04f16fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andres=20Mu=C3=B1oz?= Date: Mon, 13 Nov 2017 15:18:03 +0100 Subject: [PATCH 08/27] The configuration file was modified to include one additional field inside of the gatekeeper configuration for managing token validation with externals Identity Providers (Fiware, Google, Github, Facebook). The caching option was changed to false because the token validation option doesn't allow caching yet. Also, the error messages defined in the api settings were changed for including token as other validation method. --- config/default.yml | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/config/default.yml b/config/default.yml index a1b7a5352..1f4a7f2ce 100644 --- a/config/default.yml +++ b/config/default.yml @@ -58,7 +58,12 @@ gatekeeper: - header - getParam - basicAuthUsername - api_key_cache: true + api_key_cache: false + idp_providers: + - fiware-oauth2 + - github-oauth2 + - facebook-oauth2 + - google-oauth2 trafficserver: host: 127.0.0.1 port: 14009 @@ -282,12 +287,12 @@ apiSettings: message: The requested URL was not found on this server. api_key_missing: status_code: 403 - code: API_KEY_MISSING - message: No api_key was supplied. Get one at {{signup_url}} + code: API_KEY_OR_TOKEN_MISSING + message: No api_key or token was supplied. Get one at {{signup_url}} api_key_invalid: status_code: 403 - code: API_KEY_INVALID - message: An invalid api_key was supplied. Get one at {{signup_url}} + code: API_KEY_OR_TOKEN_INVALID + message: An invalid api_key or token was supplied. Get one at {{signup_url}} api_key_disabled: status_code: 403 code: API_KEY_DISABLED @@ -298,8 +303,8 @@ apiSettings: message: The api_key supplied has not been verified yet. Please check your e-mail to verify the API key. Contact us at {{contact_url}} for assistance api_key_unauthorized: status_code: 403 - code: API_KEY_UNAUTHORIZED - message: The api_key supplied is not authorized to access the given service. Contact us at {{contact_url}} for assistance + code: API_KEY_OR_TOKEN_UNAUTHORIZED + message: The api_key or token supplied is not authorized to access the given service. Contact us at {{contact_url}} for assistance over_rate_limit: status_code: 429 code: OVER_RATE_LIMIT From 99fb1b0c919d2b0e2cd6762f4da5f1b5edc5ff6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andres=20Mu=C3=B1oz?= Date: Mon, 13 Nov 2017 15:22:34 +0100 Subject: [PATCH 09/27] In this file, I include two more nginx server variables for checking the word "token" in the url and the header "X-Auth-Token" in the requests made to the platform. With this change is possible to manage and differentiate if the user made a request using an API_Key or OAuth2 Token --- .idea/vcs.xml | 6 ++++++ src/api-umbrella/proxy/hooks/rewrite.lua | 4 +++- 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 .idea/vcs.xml diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 000000000..35eb1ddfb --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/api-umbrella/proxy/hooks/rewrite.lua b/src/api-umbrella/proxy/hooks/rewrite.lua index af0a2268f..d238ea134 100644 --- a/src/api-umbrella/proxy/hooks/rewrite.lua +++ b/src/api-umbrella/proxy/hooks/rewrite.lua @@ -17,6 +17,7 @@ wait_for_setup() -- ngx.var lookups are apparently somewhat expensive. ngx.ctx.args = ngx_var.args ngx.ctx.arg_api_key = ngx_var.arg_api_key +ngx.ctx.arg_token = ngx_var.arg_token if(config["router"]["match_x_forwarded_host"]) then ngx.ctx.host = ngx_var.http_x_forwarded_host or ngx_var.http_host or ngx_var.host else @@ -24,6 +25,7 @@ else end ngx.ctx.host_normalized = host_normalize(ngx.ctx.host) ngx.ctx.http_x_api_key = ngx_var.http_x_api_key +ngx.ctx.http_x_auth_token = ngx_var.http_x_auth_token ngx.ctx.port = ngx_var.real_port ngx.ctx.protocol = ngx_var.real_scheme ngx.ctx.remote_addr = ngx_var.remote_addr @@ -69,4 +71,4 @@ else else error_handler(api_err) end -end +end \ No newline at end of file From 1ead4075699f06ea15db273409b34f27987d36b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andres=20Mu=C3=B1oz?= Date: Mon, 13 Nov 2017 15:26:09 +0100 Subject: [PATCH 10/27] This function usually is used for inverting the roles table, it was modified to allow and parse a roles tables that have more than one value by rol, for example: if the function receives the roles in this format Roles":[{"name":"rol1","id":"16"}]. With the modification the function checks if the roles value has more than one value and takes only the value for the key "name" and after that, the function inverts the table. --- src/api-umbrella/utils/invert_table.lua | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/api-umbrella/utils/invert_table.lua b/src/api-umbrella/utils/invert_table.lua index 5d0000f22..4b5a1b8f9 100644 --- a/src/api-umbrella/utils/invert_table.lua +++ b/src/api-umbrella/utils/invert_table.lua @@ -1,8 +1,18 @@ return function(table) + local numItems = 0 local inverted = {} for key, value in pairs(table) do - inverted[value] = key + if type(value)=="string" then + inverted[value] = key + else + for k,v in pairs(value) do + numItems = numItems + 1 + end + if numItems > 1 then + value = value["name"] + end + inverted[value] = key + end end - return inverted end From ae7143b033fcf97bb0455407c664519ffa410f35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andres=20Mu=C3=B1oz?= Date: Mon, 13 Nov 2017 15:29:04 +0100 Subject: [PATCH 11/27] This function allows to connect with an IdP service (Google, Facebook, Fiware, Github) for checking if a token is valid and retrieve the user properties. The function takes the token provided by the user and the IdP provider registered in the api-backend for checking if the token is valid making a validation request to the corresponding IdP. If the token is valid, the user information stored in the IdP is retrieved. --- src/api-umbrella/utils/idp.lua | 55 ++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 src/api-umbrella/utils/idp.lua diff --git a/src/api-umbrella/utils/idp.lua b/src/api-umbrella/utils/idp.lua new file mode 100644 index 000000000..764c95eb1 --- /dev/null +++ b/src/api-umbrella/utils/idp.lua @@ -0,0 +1,55 @@ +local http = require "resty.http" +local cjson = require "cjson" +local _M = {} + +-- Function to connect with an IdP service (Google, Facebook, Fiware, Github) for checking +-- if a token is valid and retrieve the user properties. The function takes +-- the token provided by the user and the IdP provider registered in the api-backend +-- for checking if the token is valid making a validation request to the corresponding IdP. +-- If the token is valid, the user information stored in the IdP is retrieved. + +function _M.first(dict) + local idp_back_name = dict["idp"]["backend_name"] + local token = dict["key_value"] + local idp_host, result, res, err, rpath + local ssl=false + local httpc = http.new() + httpc:set_timeout(45000) + + if config["nginx"]["lua_ssl_trusted_certificate"] then + ssl=true + end + local rquery = "access_token="..token + if idp_back_name == "google-oauth2" then + rpath = "/oauth2/v3/userinfo" + idp_host="https://www.googleapis.com" + elseif idp_back_name == "fiware-oauth2" then + rpath = "/user" + idp_host="https://130.206.84.14" + elseif idp_back_name == "facebook-oauth2" then + rpath = "/me" + idp_host="https://graph.facebook.com" + rquery = "fields=id,name,email&access_token="..token + elseif idp_back_name == "github-oauth2" then + rpath = "/user" + idp_host="https://api.github.com" + end + + res, err = httpc:request_uri(idp_host..rpath,{ + method = "GET", + query = rquery, + ssl_verify = ssl, + }) + + if res and res.status == 200 then + local body= res.body + if not body then + return nil + end + result = cjson.decode(body) + end + + return result, err +end + +return _M \ No newline at end of file From 0eacb118c3037320a514cac975974cc2b85bea90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andres=20Mu=C3=B1oz?= Date: Mon, 13 Nov 2017 15:35:35 +0100 Subject: [PATCH 12/27] This file was modified for including the token validation, the methods allowed to pass the token are by param and header. The variable api_key was changed by a key, value table, this table has three elements, first the key_value that stores the value of the api_key or the token, the second value called key_type which stores the type of key provided by the user, it can take two values token or api_key and, Finally, the las element named "idp" has a value that indicates if and which external IdP has the associated the requested api-backend. All the variables that previously stored the api_key value, was changed to store api_key ["key_value"], that represents exactly the same value using the new api_key table. --- .../proxy/middleware/api_key_validator.lua | 46 +++++++++++++------ 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/src/api-umbrella/proxy/middleware/api_key_validator.lua b/src/api-umbrella/proxy/middleware/api_key_validator.lua index ab1447b32..e27dfe67a 100644 --- a/src/api-umbrella/proxy/middleware/api_key_validator.lua +++ b/src/api-umbrella/proxy/middleware/api_key_validator.lua @@ -6,32 +6,52 @@ local is_empty = types.is_empty local function resolve_api_key() local api_key_methods = config["gatekeeper"]["api_key_methods"] - local api_key + local key = {key_value="", key_type="", idp=nil } + -- The api_key variable is a dictionary compose by three elements, the key_value which stores + -- the api_key value or the user token value, the key_type field in where is stored + -- the type of key that was provided by the user, it value could be an api_key or a token, Finally + -- the idp field indicates, if the api-backend have an IdP registred for the token validation + -- The validation process is made for all the api_key_methods (except basicAuthUsername) + -- declared in the configuration file, checking if the user sends an api_key or token + -- Only the header and get_param methods are supported by the token validation. for _, method in ipairs(api_key_methods) do - if method == "header" then - api_key = ngx.ctx.http_x_api_key - elseif method == "getParam" then - api_key = ngx.ctx.arg_api_key - elseif method == "basicAuthUsername" then - api_key = ngx.ctx.remote_user + if method == "header" and ngx.ctx.http_x_api_key then + key.key_value = ngx.ctx.http_x_api_key + key.key_type = "api_key" + elseif ngx.ctx.http_x_auth_token then + key.key_value = ngx.ctx.http_x_auth_token + key.key_type = "token" + elseif method == "getParam" and ngx.ctx.arg_api_key then + key.key_value = ngx.ctx.arg_api_key + key.key_type = "api_key" + elseif ngx.ctx.arg_token then + key.key_value = ngx.ctx.arg_token + key.key_type = "token" + elseif method == "basicAuthUsername" and ngx.ctx.remote_user then + key.key_value = ngx.ctx.remote_user + key.key_type = "api_key" end - if not is_empty(api_key) then + if not is_empty(key["key_value"]) then break end end -- Store the api key for logging. - ngx.ctx.api_key = api_key + ngx.ctx.api_key = key["key_value"] - return api_key + return key end return function(settings) -- Find the API key in the header, query string, or HTTP auth. local api_key = resolve_api_key() - if is_empty(api_key) then + -- Find if and IdP was set + if settings["require_idp"] then + api_key.idp=settings["require_idp"][1] + end + if is_empty(api_key["key_value"]) then if settings and settings["disable_api_key"] then return nil else @@ -47,7 +67,7 @@ return function(settings) -- Store the api key on the user object for easier access (the user object -- doesn't contain it directly, to save memory storage in the lookup table). - user["api_key"] = api_key + user["api_key"] = api_key["key_value"] -- Store user details for logging. ngx.ctx.user_id = user["id"] @@ -76,4 +96,4 @@ return function(settings) end return user -end +end \ No newline at end of file From ac81453191ce8942e3beb3f5b8a597e1ae6f757d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andres=20Mu=C3=B1oz?= Date: Mon, 13 Nov 2017 15:43:23 +0100 Subject: [PATCH 13/27] The user_store function was modified for including the token validation, for achieving this, an extra validation through the key_type value of the api_key variable was used. If the key_value is equal to "api_key", the key_value is checked in the Mongo database. In case of the value of key_values is equal to "token", the token is sent to the IdP validation with the corresponding api_key["idp"] value for sending a validation request directly to the IdP associated to the api-backend, if the token is valid, the user information is returned. If the user information is retrieved from the database this information is stored in the variables of the platform as usually did. In case that the user information was retrieved using token validation and the IdP was Fiware, the variables the id is assigned to the user_id and the Roles is assigned to the roles of the platform. In case of the other externals IdP, the name and the email of the user are retrieved only. The rest of the changes are related to the reassignment of the api_key variable using api_key ["key_value"] --- src/api-umbrella/proxy/user_store.lua | 55 +++++++++++++++++++-------- 1 file changed, 40 insertions(+), 15 deletions(-) diff --git a/src/api-umbrella/proxy/user_store.lua b/src/api-umbrella/proxy/user_store.lua index 6ca87e4e2..358202b55 100644 --- a/src/api-umbrella/proxy/user_store.lua +++ b/src/api-umbrella/proxy/user_store.lua @@ -8,19 +8,34 @@ local mongo = require "api-umbrella.utils.mongo" local shcache = require "shcache" local types = require "pl.types" local utils = require "api-umbrella.proxy.utils" +local idp = require "api-umbrella.utils.idp" local cache_computed_settings = utils.cache_computed_settings local is_empty = types.is_empty local function lookup_user(api_key) - local raw_user, err = mongo.first("api_users", { - query = { - api_key = api_key, - }, - }) - - if err then - ngx.log(ngx.ERR, "failed to fetch user from mongodb: ", err) + local raw_user + local db_err + local idp_err + + -- Checking the field of api_key ["key_type"], if the key_type is api_key + -- the api_key value is checked in the database and retrieve the user information + -- else if the key_type is token, the token is checked using the corresponding IdP + -- registred in the api-backend and the user information is retrieved + + if not api_key["key_type"] or api_key["key_type"] == "api_key" then + raw_user, db_err = mongo.first("api_users", { + query = { + api_key = api_key["key_value"], + }, + }) + elseif api_key["key_type"] == "token" and api_key["idp"]then + raw_user, idp_err = idp.first(api_key) + end + if idp_err then + ngx.log(ngx.ERR, "failed to autenticate , status code:", idp_err) + elseif db_err then + ngx.log(ngx.ERR, "failed to fetch user from mongodb", db_err) elseif raw_user then local user = utils.pick_where_present(raw_user, { "created_at", @@ -32,19 +47,29 @@ local function lookup_user(api_key) "settings", "throttle_by_ip", }) - -- Ensure IDs get stored as strings, even if Mongo ObjectIds are in use. - if raw_user["_id"] and raw_user["_id"]["$oid"] then - user["id"] = raw_user["_id"]["$oid"] + if not api_key["idp"]and raw_user["_id"] and raw_user["_id"]["$oid"] then + user["id"] = raw_user["_id"]["$oid"] else user["id"] = raw_user["_id"] end + if api_key["idp"] and api_key["idp"]["backend_name"]== "fiware-oauth2" then + user["id"] = raw_user.id + user["email"] = raw_user.email + elseif api_key["idp"] and api_key["idp"]["backend_name"]~= "fiware-oauth2" then + user["id"] = raw_user.name + user["email"] = raw_user.email + end -- Invert the array of roles into a hashy table for more optimized -- lookups (so we can just check if the key exists, rather than -- looping over each value). + -- Moreover, in case that the user information have been retrieved using a token validation, + -- the roles associated with the token are stored in user ["roles"] if user["roles"] then user["roles"] = invert_table(user["roles"]) + elseif api_key["idp"] and api_key["idp"]["backend_name"]== "fiware-oauth2" and raw_user.Roles then + user["roles"] = invert_table(raw_user.Roles) end if user["created_at"] and user["created_at"]["$date"] then @@ -103,14 +128,14 @@ function _M.get(api_key) return nil end - user = shared_cache:load(api_key) + user = shared_cache:load(api_key["key_value"]) if user then - local_cache:set(api_key, user, 2) + local_cache:set(api_key["key_value"], user, 2) else - local_cache:set(api_key, EMPTY_DATA, 2) + local_cache:set(api_key["key_value"], EMPTY_DATA, 2) end return user end -return _M +return _M \ No newline at end of file From 739c99ec71619e25dbba33e17f4d125af7e84229 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andres=20Mu=C3=B1oz?= Date: Tue, 14 Nov 2017 15:16:21 +0100 Subject: [PATCH 14/27] Correcting validation mistake for allowing access to the api backend using api_key or token even when an IdP has been associated to that API backend --- src/api-umbrella/proxy/user_store.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/api-umbrella/proxy/user_store.lua b/src/api-umbrella/proxy/user_store.lua index 358202b55..65d89db11 100644 --- a/src/api-umbrella/proxy/user_store.lua +++ b/src/api-umbrella/proxy/user_store.lua @@ -48,15 +48,15 @@ local function lookup_user(api_key) "throttle_by_ip", }) -- Ensure IDs get stored as strings, even if Mongo ObjectIds are in use. - if not api_key["idp"]and raw_user["_id"] and raw_user["_id"]["$oid"] then + if api_key["key_type"]=="api_key" and raw_user["_id"] and raw_user["_id"]["$oid"] then user["id"] = raw_user["_id"]["$oid"] else user["id"] = raw_user["_id"] end - if api_key["idp"] and api_key["idp"]["backend_name"]== "fiware-oauth2" then + if api_key["idp"] and api_key["key_type"]=="token" and api_key["idp"]["backend_name"]== "fiware-oauth2" then user["id"] = raw_user.id user["email"] = raw_user.email - elseif api_key["idp"] and api_key["idp"]["backend_name"]~= "fiware-oauth2" then + elseif api_key["idp"] and api_key["key_type"]=="token" and api_key["idp"]["backend_name"]~= "fiware-oauth2" then user["id"] = raw_user.name user["email"] = raw_user.email end @@ -68,7 +68,7 @@ local function lookup_user(api_key) -- the roles associated with the token are stored in user ["roles"] if user["roles"] then user["roles"] = invert_table(user["roles"]) - elseif api_key["idp"] and api_key["idp"]["backend_name"]== "fiware-oauth2" and raw_user.Roles then + elseif api_key["idp"] and api_key["key_type"]=="token" and api_key["idp"]["backend_name"]== "fiware-oauth2" and raw_user.Roles then user["roles"] = invert_table(raw_user.Roles) end From 80bb4fb362be25abd5e362930dcccc0d19a29aa5 Mon Sep 17 00:00:00 2001 From: agordillo Date: Tue, 13 Feb 2018 12:50:02 +0100 Subject: [PATCH 15/27] Fix on Vagrantfile for synchronizing files in admin-ui --- Vagrantfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Vagrantfile b/Vagrantfile index 783b5ec27..78660dd69 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -62,6 +62,7 @@ Vagrant.configure("2") do |config| end config.vm.synced_folder "src/api-umbrella/admin-ui", "/vagrant-admin-ui", + :nfs => options[:nfs], :type => "rsync", :rsync__verbose => true, :rsync__exclude => [ From 58cc570ad5cdbea0db0f220b327cadea1366e906 Mon Sep 17 00:00:00 2001 From: agordillo Date: Tue, 13 Feb 2018 15:04:44 +0100 Subject: [PATCH 16/27] Add external idps field to apis form --- .../app/components/apis/settings/common-fields.js | 9 +++++++++ src/api-umbrella/admin-ui/app/models/api/settings.js | 1 + src/api-umbrella/admin-ui/app/routes/apis/form.js | 1 + .../templates/components/apis/settings/common-fields.hbs | 1 + src/api-umbrella/web-app/config/locales/en.yml | 4 ++++ 5 files changed, 16 insertions(+) diff --git a/src/api-umbrella/admin-ui/app/components/apis/settings/common-fields.js b/src/api-umbrella/admin-ui/app/components/apis/settings/common-fields.js index fa862a8f8..fd76f5151 100644 --- a/src/api-umbrella/admin-ui/app/components/apis/settings/common-fields.js +++ b/src/api-umbrella/admin-ui/app/components/apis/settings/common-fields.js @@ -22,6 +22,15 @@ export default Ember.Component.extend({ { id: 'required_email', name: I18n.t('admin.api.settings.api_key_verification_level_options.required_email') }, ], + externalIdpOptions: [ + { id: null, name: I18n.t('admin.api.settings.external_idp_options.inherit') }, + { id: 'none', name: I18n.t('admin.api.settings.external_idp_options.none') }, + { id: 'fiware-oauth2', name: "FIWARE" }, + { id: 'github-oauth2', name: "GitHub" }, + { id: 'facebook-oauth2', name: "Facebook" }, + { id: 'google-oauth2', name: "Google" }, + ], + passApiKeyOptions: [ { id: 'header', name: I18n.t('admin.api.settings.pass_api_key_header') }, { id: 'param', name: I18n.t('admin.api.settings.pass_api_key_param') }, diff --git a/src/api-umbrella/admin-ui/app/models/api/settings.js b/src/api-umbrella/admin-ui/app/models/api/settings.js index c0ac58f19..029ce3f7e 100644 --- a/src/api-umbrella/admin-ui/app/models/api/settings.js +++ b/src/api-umbrella/admin-ui/app/models/api/settings.js @@ -8,6 +8,7 @@ export default DS.Model.extend({ requireHttps: DS.attr(), disableApiKey: DS.attr(), apiKeyVerificationLevel: DS.attr(), + externalIdp: DS.attr(), requiredRoles: DS.attr(), requiredRolesOverride: DS.attr(), allowedIps: DS.attr(), diff --git a/src/api-umbrella/admin-ui/app/routes/apis/form.js b/src/api-umbrella/admin-ui/app/routes/apis/form.js index 0467142b9..74407e331 100644 --- a/src/api-umbrella/admin-ui/app/routes/apis/form.js +++ b/src/api-umbrella/admin-ui/app/routes/apis/form.js @@ -6,6 +6,7 @@ import UncachedModel from 'api-umbrella-admin-ui/mixins/uncached-model'; export default Base.extend(Confirmation, UncachedModel, { // Return a promise for loading multiple models all together. fetchModels(record) { + //TODO: add external IDPs config here return Ember.RSVP.hash({ record: record, roleOptions: this.get('store').findAll('api-user-role', { reload: true }), diff --git a/src/api-umbrella/admin-ui/app/templates/components/apis/settings/common-fields.hbs b/src/api-umbrella/admin-ui/app/templates/components/apis/settings/common-fields.hbs index a03e3faec..8fefe2f50 100644 --- a/src/api-umbrella/admin-ui/app/templates/components/apis/settings/common-fields.hbs +++ b/src/api-umbrella/admin-ui/app/templates/components/apis/settings/common-fields.hbs @@ -2,6 +2,7 @@ {{f.select-field "requireHttps" label=(t "admin.api.settings.require_https") tooltip=(t "admin.api.settings.require_https_tooltip_markdown") options=requireHttpsOptions}} {{f.select-field "disableApiKey" label=(t "admin.api.settings.disable_api_key") options=disableApiKeyOptions}} {{f.select-field "apiKeyVerificationLevel" label=(t "admin.api.settings.api_key_verification_level") options=apiKeyVerificationLevelOptions}} + {{f.select-field "externalIdp" label=(t "admin.api.settings.external_idp") options=externalIdpOptions}} {{f.selectize-field "requiredRolesString" label=(t "admin.api.settings.required_roles") tooltip=(t "admin.api.settings.required_roles_tooltip_markdown") options=roleOptions}} {{#if isSubSettings}} {{f.checkbox-field "requiredRolesOverride" label=(t "admin.api.settings.required_roles_override") tooltip=(t "admin.api.settings.required_roles_override_tooltip_markdown")}} diff --git a/src/api-umbrella/web-app/config/locales/en.yml b/src/api-umbrella/web-app/config/locales/en.yml index 4efe2faa2..6145a91ff 100644 --- a/src/api-umbrella/web-app/config/locales/en.yml +++ b/src/api-umbrella/web-app/config/locales/en.yml @@ -139,6 +139,10 @@ en: none: None - API keys can be used without any verification transition_email: E-mail verification transition - Existing API keys will continue to work, new API keys will only work if verified required_email: E-mail verification required - Existing API keys will break, only new API keys will work if verified + external_idp: External Identity Provider + external_idp_options: + inherit: Inherit (default - none) + none: None required_roles: Required Roles required_roles_tooltip_markdown: |- Define roles that API keys must have in order to access this API. If multiple roles are set, then the API key must have all of the roles. From 79c4a43bcdecc2743da88664e159f38a1e1f3545 Mon Sep 17 00:00:00 2001 From: agordillo Date: Tue, 13 Feb 2018 15:47:02 +0100 Subject: [PATCH 17/27] Add require_idp field to apis (client and server sides) --- .../admin-ui/app/components/apis/settings/common-fields.js | 6 +++--- src/api-umbrella/admin-ui/app/models/api/settings.js | 2 +- .../templates/components/apis/settings/common-fields.hbs | 2 +- .../web-app/app/controllers/api/v1/apis_controller.rb | 1 + src/api-umbrella/web-app/app/models/api/settings.rb | 1 + src/api-umbrella/web-app/config/locales/en.yml | 4 ++-- 6 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/api-umbrella/admin-ui/app/components/apis/settings/common-fields.js b/src/api-umbrella/admin-ui/app/components/apis/settings/common-fields.js index fd76f5151..85d9cf414 100644 --- a/src/api-umbrella/admin-ui/app/components/apis/settings/common-fields.js +++ b/src/api-umbrella/admin-ui/app/components/apis/settings/common-fields.js @@ -22,9 +22,9 @@ export default Ember.Component.extend({ { id: 'required_email', name: I18n.t('admin.api.settings.api_key_verification_level_options.required_email') }, ], - externalIdpOptions: [ - { id: null, name: I18n.t('admin.api.settings.external_idp_options.inherit') }, - { id: 'none', name: I18n.t('admin.api.settings.external_idp_options.none') }, + requireIdpOptions: [ + { id: null, name: I18n.t('admin.api.settings.require_idp_options.inherit') }, + { id: 'none', name: I18n.t('admin.api.settings.require_idp_options.none') }, { id: 'fiware-oauth2', name: "FIWARE" }, { id: 'github-oauth2', name: "GitHub" }, { id: 'facebook-oauth2', name: "Facebook" }, diff --git a/src/api-umbrella/admin-ui/app/models/api/settings.js b/src/api-umbrella/admin-ui/app/models/api/settings.js index 029ce3f7e..ffc811e19 100644 --- a/src/api-umbrella/admin-ui/app/models/api/settings.js +++ b/src/api-umbrella/admin-ui/app/models/api/settings.js @@ -8,7 +8,7 @@ export default DS.Model.extend({ requireHttps: DS.attr(), disableApiKey: DS.attr(), apiKeyVerificationLevel: DS.attr(), - externalIdp: DS.attr(), + requireIdp: DS.attr(), requiredRoles: DS.attr(), requiredRolesOverride: DS.attr(), allowedIps: DS.attr(), diff --git a/src/api-umbrella/admin-ui/app/templates/components/apis/settings/common-fields.hbs b/src/api-umbrella/admin-ui/app/templates/components/apis/settings/common-fields.hbs index 8fefe2f50..ec5978edd 100644 --- a/src/api-umbrella/admin-ui/app/templates/components/apis/settings/common-fields.hbs +++ b/src/api-umbrella/admin-ui/app/templates/components/apis/settings/common-fields.hbs @@ -2,7 +2,7 @@ {{f.select-field "requireHttps" label=(t "admin.api.settings.require_https") tooltip=(t "admin.api.settings.require_https_tooltip_markdown") options=requireHttpsOptions}} {{f.select-field "disableApiKey" label=(t "admin.api.settings.disable_api_key") options=disableApiKeyOptions}} {{f.select-field "apiKeyVerificationLevel" label=(t "admin.api.settings.api_key_verification_level") options=apiKeyVerificationLevelOptions}} - {{f.select-field "externalIdp" label=(t "admin.api.settings.external_idp") options=externalIdpOptions}} + {{f.select-field "requireIdp" label=(t "admin.api.settings.require_idp") options=requireIdpOptions}} {{f.selectize-field "requiredRolesString" label=(t "admin.api.settings.required_roles") tooltip=(t "admin.api.settings.required_roles_tooltip_markdown") options=roleOptions}} {{#if isSubSettings}} {{f.checkbox-field "requiredRolesOverride" label=(t "admin.api.settings.required_roles_override") tooltip=(t "admin.api.settings.required_roles_override_tooltip_markdown")}} diff --git a/src/api-umbrella/web-app/app/controllers/api/v1/apis_controller.rb b/src/api-umbrella/web-app/app/controllers/api/v1/apis_controller.rb index 38550bc96..462a7c50e 100644 --- a/src/api-umbrella/web-app/app/controllers/api/v1/apis_controller.rb +++ b/src/api-umbrella/web-app/app/controllers/api/v1/apis_controller.rb @@ -94,6 +94,7 @@ def api_params :disable_api_key, :api_key_verification_level, :api_key_verification_transition_start_at, + :require_idp, :rate_limit_mode, :anonymous_rate_limit_behavior, :authenticated_rate_limit_behavior, diff --git a/src/api-umbrella/web-app/app/models/api/settings.rb b/src/api-umbrella/web-app/app/models/api/settings.rb index 3d8e11aa0..3fcda9bad 100644 --- a/src/api-umbrella/web-app/app/models/api/settings.rb +++ b/src/api-umbrella/web-app/app/models/api/settings.rb @@ -10,6 +10,7 @@ class Api::Settings field :disable_api_key, :type => Boolean field :api_key_verification_level, :type => String field :api_key_verification_transition_start_at, :type => Time + field :require_idp, :type => String field :required_roles, :type => Array field :required_roles_override, :type => Boolean field :allowed_ips, :type => Array diff --git a/src/api-umbrella/web-app/config/locales/en.yml b/src/api-umbrella/web-app/config/locales/en.yml index 6145a91ff..177b700f2 100644 --- a/src/api-umbrella/web-app/config/locales/en.yml +++ b/src/api-umbrella/web-app/config/locales/en.yml @@ -139,8 +139,8 @@ en: none: None - API keys can be used without any verification transition_email: E-mail verification transition - Existing API keys will continue to work, new API keys will only work if verified required_email: E-mail verification required - Existing API keys will break, only new API keys will work if verified - external_idp: External Identity Provider - external_idp_options: + require_idp: External Identity Provider + require_idp_options: inherit: Inherit (default - none) none: None required_roles: Required Roles From cecb00dba88c6166465bea0f1cd99def875435ae Mon Sep 17 00:00:00 2001 From: anmunoz Date: Tue, 13 Feb 2018 16:50:17 +0100 Subject: [PATCH 18/27] Adding the web interface fields for external idp validation for api backends by @agordillo --- .../app/components/apis/settings/common-fields.js | 9 +++++++++ src/api-umbrella/admin-ui/app/models/api/settings.js | 1 + .../templates/components/apis/settings/common-fields.hbs | 1 + .../web-app/app/controllers/api/v1/apis_controller.rb | 1 + src/api-umbrella/web-app/app/models/api/settings.rb | 1 + src/api-umbrella/web-app/config/locales/en.yml | 4 ++++ 6 files changed, 17 insertions(+) diff --git a/src/api-umbrella/admin-ui/app/components/apis/settings/common-fields.js b/src/api-umbrella/admin-ui/app/components/apis/settings/common-fields.js index fa862a8f8..85d9cf414 100644 --- a/src/api-umbrella/admin-ui/app/components/apis/settings/common-fields.js +++ b/src/api-umbrella/admin-ui/app/components/apis/settings/common-fields.js @@ -22,6 +22,15 @@ export default Ember.Component.extend({ { id: 'required_email', name: I18n.t('admin.api.settings.api_key_verification_level_options.required_email') }, ], + requireIdpOptions: [ + { id: null, name: I18n.t('admin.api.settings.require_idp_options.inherit') }, + { id: 'none', name: I18n.t('admin.api.settings.require_idp_options.none') }, + { id: 'fiware-oauth2', name: "FIWARE" }, + { id: 'github-oauth2', name: "GitHub" }, + { id: 'facebook-oauth2', name: "Facebook" }, + { id: 'google-oauth2', name: "Google" }, + ], + passApiKeyOptions: [ { id: 'header', name: I18n.t('admin.api.settings.pass_api_key_header') }, { id: 'param', name: I18n.t('admin.api.settings.pass_api_key_param') }, diff --git a/src/api-umbrella/admin-ui/app/models/api/settings.js b/src/api-umbrella/admin-ui/app/models/api/settings.js index c0ac58f19..ffc811e19 100644 --- a/src/api-umbrella/admin-ui/app/models/api/settings.js +++ b/src/api-umbrella/admin-ui/app/models/api/settings.js @@ -8,6 +8,7 @@ export default DS.Model.extend({ requireHttps: DS.attr(), disableApiKey: DS.attr(), apiKeyVerificationLevel: DS.attr(), + requireIdp: DS.attr(), requiredRoles: DS.attr(), requiredRolesOverride: DS.attr(), allowedIps: DS.attr(), diff --git a/src/api-umbrella/admin-ui/app/templates/components/apis/settings/common-fields.hbs b/src/api-umbrella/admin-ui/app/templates/components/apis/settings/common-fields.hbs index a03e3faec..ec5978edd 100644 --- a/src/api-umbrella/admin-ui/app/templates/components/apis/settings/common-fields.hbs +++ b/src/api-umbrella/admin-ui/app/templates/components/apis/settings/common-fields.hbs @@ -2,6 +2,7 @@ {{f.select-field "requireHttps" label=(t "admin.api.settings.require_https") tooltip=(t "admin.api.settings.require_https_tooltip_markdown") options=requireHttpsOptions}} {{f.select-field "disableApiKey" label=(t "admin.api.settings.disable_api_key") options=disableApiKeyOptions}} {{f.select-field "apiKeyVerificationLevel" label=(t "admin.api.settings.api_key_verification_level") options=apiKeyVerificationLevelOptions}} + {{f.select-field "requireIdp" label=(t "admin.api.settings.require_idp") options=requireIdpOptions}} {{f.selectize-field "requiredRolesString" label=(t "admin.api.settings.required_roles") tooltip=(t "admin.api.settings.required_roles_tooltip_markdown") options=roleOptions}} {{#if isSubSettings}} {{f.checkbox-field "requiredRolesOverride" label=(t "admin.api.settings.required_roles_override") tooltip=(t "admin.api.settings.required_roles_override_tooltip_markdown")}} diff --git a/src/api-umbrella/web-app/app/controllers/api/v1/apis_controller.rb b/src/api-umbrella/web-app/app/controllers/api/v1/apis_controller.rb index 38550bc96..462a7c50e 100644 --- a/src/api-umbrella/web-app/app/controllers/api/v1/apis_controller.rb +++ b/src/api-umbrella/web-app/app/controllers/api/v1/apis_controller.rb @@ -94,6 +94,7 @@ def api_params :disable_api_key, :api_key_verification_level, :api_key_verification_transition_start_at, + :require_idp, :rate_limit_mode, :anonymous_rate_limit_behavior, :authenticated_rate_limit_behavior, diff --git a/src/api-umbrella/web-app/app/models/api/settings.rb b/src/api-umbrella/web-app/app/models/api/settings.rb index 3d8e11aa0..3fcda9bad 100644 --- a/src/api-umbrella/web-app/app/models/api/settings.rb +++ b/src/api-umbrella/web-app/app/models/api/settings.rb @@ -10,6 +10,7 @@ class Api::Settings field :disable_api_key, :type => Boolean field :api_key_verification_level, :type => String field :api_key_verification_transition_start_at, :type => Time + field :require_idp, :type => String field :required_roles, :type => Array field :required_roles_override, :type => Boolean field :allowed_ips, :type => Array diff --git a/src/api-umbrella/web-app/config/locales/en.yml b/src/api-umbrella/web-app/config/locales/en.yml index 4efe2faa2..177b700f2 100644 --- a/src/api-umbrella/web-app/config/locales/en.yml +++ b/src/api-umbrella/web-app/config/locales/en.yml @@ -139,6 +139,10 @@ en: none: None - API keys can be used without any verification transition_email: E-mail verification transition - Existing API keys will continue to work, new API keys will only work if verified required_email: E-mail verification required - Existing API keys will break, only new API keys will work if verified + require_idp: External Identity Provider + require_idp_options: + inherit: Inherit (default - none) + none: None required_roles: Required Roles required_roles_tooltip_markdown: |- Define roles that API keys must have in order to access this API. If multiple roles are set, then the API key must have all of the roles. From 1e561c73a1be5b95ef3ed0057b847a60e3594522 Mon Sep 17 00:00:00 2001 From: anmunoz Date: Wed, 14 Feb 2018 12:37:16 +0100 Subject: [PATCH 19/27] Fixing some code for integrating the external IdP validation with the web interface --- config/default.yml | 5 ----- src/api-umbrella/proxy/middleware/api_key_validator.lua | 2 +- src/api-umbrella/proxy/user_store.lua | 8 ++++---- src/api-umbrella/utils/idp.lua | 2 +- 4 files changed, 6 insertions(+), 11 deletions(-) diff --git a/config/default.yml b/config/default.yml index 1f4a7f2ce..543d95183 100644 --- a/config/default.yml +++ b/config/default.yml @@ -59,11 +59,6 @@ gatekeeper: - getParam - basicAuthUsername api_key_cache: false - idp_providers: - - fiware-oauth2 - - github-oauth2 - - facebook-oauth2 - - google-oauth2 trafficserver: host: 127.0.0.1 port: 14009 diff --git a/src/api-umbrella/proxy/middleware/api_key_validator.lua b/src/api-umbrella/proxy/middleware/api_key_validator.lua index e27dfe67a..0a507ef1d 100644 --- a/src/api-umbrella/proxy/middleware/api_key_validator.lua +++ b/src/api-umbrella/proxy/middleware/api_key_validator.lua @@ -49,7 +49,7 @@ return function(settings) local api_key = resolve_api_key() -- Find if and IdP was set if settings["require_idp"] then - api_key.idp=settings["require_idp"][1] + api_key.idp=settings["require_idp"] end if is_empty(api_key["key_value"]) then if settings and settings["disable_api_key"] then diff --git a/src/api-umbrella/proxy/user_store.lua b/src/api-umbrella/proxy/user_store.lua index 65d89db11..56fa46ce6 100644 --- a/src/api-umbrella/proxy/user_store.lua +++ b/src/api-umbrella/proxy/user_store.lua @@ -49,14 +49,14 @@ local function lookup_user(api_key) }) -- Ensure IDs get stored as strings, even if Mongo ObjectIds are in use. if api_key["key_type"]=="api_key" and raw_user["_id"] and raw_user["_id"]["$oid"] then - user["id"] = raw_user["_id"]["$oid"] + user["id"] = raw_user["_id"]["$oid"] else user["id"] = raw_user["_id"] end - if api_key["idp"] and api_key["key_type"]=="token" and api_key["idp"]["backend_name"]== "fiware-oauth2" then + if api_key["idp"] and api_key["key_type"]=="token" and api_key["idp"]== "fiware-oauth2" then user["id"] = raw_user.id user["email"] = raw_user.email - elseif api_key["idp"] and api_key["key_type"]=="token" and api_key["idp"]["backend_name"]~= "fiware-oauth2" then + elseif api_key["idp"] and api_key["key_type"]=="token" and api_key["idp"]~= "fiware-oauth2" then user["id"] = raw_user.name user["email"] = raw_user.email end @@ -68,7 +68,7 @@ local function lookup_user(api_key) -- the roles associated with the token are stored in user ["roles"] if user["roles"] then user["roles"] = invert_table(user["roles"]) - elseif api_key["idp"] and api_key["key_type"]=="token" and api_key["idp"]["backend_name"]== "fiware-oauth2" and raw_user.Roles then + elseif api_key["idp"] and api_key["key_type"]=="token" and api_key["idp"]== "fiware-oauth2" and raw_user.Roles then user["roles"] = invert_table(raw_user.Roles) end diff --git a/src/api-umbrella/utils/idp.lua b/src/api-umbrella/utils/idp.lua index 764c95eb1..ad0496a1b 100644 --- a/src/api-umbrella/utils/idp.lua +++ b/src/api-umbrella/utils/idp.lua @@ -9,7 +9,7 @@ local _M = {} -- If the token is valid, the user information stored in the IdP is retrieved. function _M.first(dict) - local idp_back_name = dict["idp"]["backend_name"] + local idp_back_name = dict["idp"] local token = dict["key_value"] local idp_host, result, res, err, rpath local ssl=false From 0574328b6bba7a1b1175a0fbc690df3c1502488a Mon Sep 17 00:00:00 2001 From: anmunoz Date: Wed, 14 Feb 2018 13:03:36 +0100 Subject: [PATCH 20/27] Pre-merge --- README.md | 4 ++++ bin/api-umbrella | 0 bin/api-umbrella-cli | 0 bin/api-umbrella-exec | 0 bin/api-umbrella-geoip-auto-updater | 0 bin/api-umbrella-nginx-reloader | 0 bin/docker-compose/make | 0 bin/docker-compose/rake | 0 build/package/build_package | 0 build/package/docker_run | 0 build/package/docker_script | 0 build/package/files/etc/init.d/api-umbrella | 0 build/package/parse_version | 0 build/package/publish | 0 build/package/scripts/after-install | 0 build/package/scripts/after-remove | 0 build/package/scripts/before-remove | 0 build/package/verify/docker_run | 0 build/package/verify/docker_script | 0 build/package/verify/download_previous_packages | 0 build/scripts/distclean | 0 build/scripts/download_cmake | 0 build/scripts/install_build_dependencies | 0 configure | 0 docker/dev/docker-start | 0 scripts/fix-log-geoip/fix | 0 scripts/generate_user_agent_data | 0 scripts/import_access_logs/import | 0 scripts/replay_logs | 0 src/api-umbrella/web-app/bin/bundle | 0 src/api-umbrella/web-app/bin/delayed_job | 0 src/api-umbrella/web-app/bin/rails | 0 src/api-umbrella/web-app/bin/rake | 0 src/api-umbrella/web-app/bin/setup | 0 src/api-umbrella/web-app/bin/spring | 0 src/api-umbrella/web-app/script/migrate_logs | 0 src/api-umbrella/web-app/script/migrate_users | 0 templates/etc/perp/.boot/rc.log | 0 templates/etc/perp/.boot/rc.perp.mustache | 0 templates/etc/perp/dev-env-ember-server/rc.log | 0 templates/etc/perp/dev-env-ember-server/rc.main.mustache | 0 templates/etc/perp/elasticsearch/rc.log | 0 templates/etc/perp/elasticsearch/rc.main.mustache | 0 templates/etc/perp/flume/rc.log | 0 templates/etc/perp/flume/rc.main.mustache | 0 templates/etc/perp/geoip-auto-updater/rc.log | 0 templates/etc/perp/geoip-auto-updater/rc.main.mustache | 0 templates/etc/perp/kylin/rc.log | 0 templates/etc/perp/kylin/rc.main.mustache | 0 templates/etc/perp/kylin/rc.run.mustache | 0 templates/etc/perp/mongod/rc.log | 0 templates/etc/perp/mongod/rc.main.mustache | 0 templates/etc/perp/mora/rc.log | 0 templates/etc/perp/mora/rc.main.mustache | 0 templates/etc/perp/nginx-reloader/rc.log | 0 templates/etc/perp/nginx-reloader/rc.main.mustache | 0 templates/etc/perp/nginx/rc.log | 0 templates/etc/perp/nginx/rc.main.mustache | 0 templates/etc/perp/presto/rc.log | 0 templates/etc/perp/presto/rc.main.mustache | 0 templates/etc/perp/rc.log.mustache | 0 templates/etc/perp/rsyslog/rc.log | 0 templates/etc/perp/rsyslog/rc.main.mustache | 0 templates/etc/perp/test-env-mailhog/rc.log | 0 templates/etc/perp/test-env-mailhog/rc.main.mustache | 0 templates/etc/perp/test-env-mongo-orchestration/rc.log | 0 .../etc/perp/test-env-mongo-orchestration/rc.main.mustache | 0 templates/etc/perp/test-env-nginx/rc.log | 0 templates/etc/perp/test-env-nginx/rc.main.mustache | 0 templates/etc/perp/test-env-openldap/rc.log | 0 templates/etc/perp/test-env-openldap/rc.main.mustache | 0 templates/etc/perp/test-env-unbound/rc.log | 0 templates/etc/perp/test-env-unbound/rc.main.mustache | 0 templates/etc/perp/trafficserver/rc.log | 0 templates/etc/perp/trafficserver/rc.main.mustache | 0 templates/etc/perp/web-delayed-job/rc.log | 0 templates/etc/perp/web-delayed-job/rc.main.mustache | 0 templates/etc/perp/web-puma/rc.log | 0 templates/etc/perp/web-puma/rc.main.mustache | 0 test/scripts/circle-ci | 0 80 files changed, 4 insertions(+) mode change 100755 => 100644 bin/api-umbrella mode change 100755 => 100644 bin/api-umbrella-cli mode change 100755 => 100644 bin/api-umbrella-exec mode change 100755 => 100644 bin/api-umbrella-geoip-auto-updater mode change 100755 => 100644 bin/api-umbrella-nginx-reloader mode change 100755 => 100644 bin/docker-compose/make mode change 100755 => 100644 bin/docker-compose/rake mode change 100755 => 100644 build/package/build_package mode change 100755 => 100644 build/package/docker_run mode change 100755 => 100644 build/package/docker_script mode change 100755 => 100644 build/package/files/etc/init.d/api-umbrella mode change 100755 => 100644 build/package/parse_version mode change 100755 => 100644 build/package/publish mode change 100755 => 100644 build/package/scripts/after-install mode change 100755 => 100644 build/package/scripts/after-remove mode change 100755 => 100644 build/package/scripts/before-remove mode change 100755 => 100644 build/package/verify/docker_run mode change 100755 => 100644 build/package/verify/docker_script mode change 100755 => 100644 build/package/verify/download_previous_packages mode change 100755 => 100644 build/scripts/distclean mode change 100755 => 100644 build/scripts/download_cmake mode change 100755 => 100644 build/scripts/install_build_dependencies mode change 100755 => 100644 configure mode change 100755 => 100644 docker/dev/docker-start mode change 100755 => 100644 scripts/fix-log-geoip/fix mode change 100755 => 100644 scripts/generate_user_agent_data mode change 100755 => 100644 scripts/import_access_logs/import mode change 100755 => 100644 scripts/replay_logs mode change 100755 => 100644 src/api-umbrella/web-app/bin/bundle mode change 100755 => 100644 src/api-umbrella/web-app/bin/delayed_job mode change 100755 => 100644 src/api-umbrella/web-app/bin/rails mode change 100755 => 100644 src/api-umbrella/web-app/bin/rake mode change 100755 => 100644 src/api-umbrella/web-app/bin/setup mode change 100755 => 100644 src/api-umbrella/web-app/bin/spring mode change 100755 => 100644 src/api-umbrella/web-app/script/migrate_logs mode change 100755 => 100644 src/api-umbrella/web-app/script/migrate_users mode change 100755 => 100644 templates/etc/perp/.boot/rc.log mode change 100755 => 100644 templates/etc/perp/.boot/rc.perp.mustache mode change 100755 => 100644 templates/etc/perp/dev-env-ember-server/rc.log mode change 100755 => 100644 templates/etc/perp/dev-env-ember-server/rc.main.mustache mode change 100755 => 100644 templates/etc/perp/elasticsearch/rc.log mode change 100755 => 100644 templates/etc/perp/elasticsearch/rc.main.mustache mode change 100755 => 100644 templates/etc/perp/flume/rc.log mode change 100755 => 100644 templates/etc/perp/flume/rc.main.mustache mode change 100755 => 100644 templates/etc/perp/geoip-auto-updater/rc.log mode change 100755 => 100644 templates/etc/perp/geoip-auto-updater/rc.main.mustache mode change 100755 => 100644 templates/etc/perp/kylin/rc.log mode change 100755 => 100644 templates/etc/perp/kylin/rc.main.mustache mode change 100755 => 100644 templates/etc/perp/kylin/rc.run.mustache mode change 100755 => 100644 templates/etc/perp/mongod/rc.log mode change 100755 => 100644 templates/etc/perp/mongod/rc.main.mustache mode change 100755 => 100644 templates/etc/perp/mora/rc.log mode change 100755 => 100644 templates/etc/perp/mora/rc.main.mustache mode change 100755 => 100644 templates/etc/perp/nginx-reloader/rc.log mode change 100755 => 100644 templates/etc/perp/nginx-reloader/rc.main.mustache mode change 100755 => 100644 templates/etc/perp/nginx/rc.log mode change 100755 => 100644 templates/etc/perp/nginx/rc.main.mustache mode change 100755 => 100644 templates/etc/perp/presto/rc.log mode change 100755 => 100644 templates/etc/perp/presto/rc.main.mustache mode change 100755 => 100644 templates/etc/perp/rc.log.mustache mode change 100755 => 100644 templates/etc/perp/rsyslog/rc.log mode change 100755 => 100644 templates/etc/perp/rsyslog/rc.main.mustache mode change 100755 => 100644 templates/etc/perp/test-env-mailhog/rc.log mode change 100755 => 100644 templates/etc/perp/test-env-mailhog/rc.main.mustache mode change 100755 => 100644 templates/etc/perp/test-env-mongo-orchestration/rc.log mode change 100755 => 100644 templates/etc/perp/test-env-mongo-orchestration/rc.main.mustache mode change 100755 => 100644 templates/etc/perp/test-env-nginx/rc.log mode change 100755 => 100644 templates/etc/perp/test-env-nginx/rc.main.mustache mode change 100755 => 100644 templates/etc/perp/test-env-openldap/rc.log mode change 100755 => 100644 templates/etc/perp/test-env-openldap/rc.main.mustache mode change 100755 => 100644 templates/etc/perp/test-env-unbound/rc.log mode change 100755 => 100644 templates/etc/perp/test-env-unbound/rc.main.mustache mode change 100755 => 100644 templates/etc/perp/trafficserver/rc.log mode change 100755 => 100644 templates/etc/perp/trafficserver/rc.main.mustache mode change 100755 => 100644 templates/etc/perp/web-delayed-job/rc.log mode change 100755 => 100644 templates/etc/perp/web-delayed-job/rc.main.mustache mode change 100755 => 100644 templates/etc/perp/web-puma/rc.log mode change 100755 => 100644 templates/etc/perp/web-puma/rc.main.mustache mode change 100755 => 100644 test/scripts/circle-ci diff --git a/README.md b/README.md index b929c9d36..9bef2d69e 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,10 @@ API Umbrella is an open source API management platform for exposing web service Binary packages are available for [download](https://apiumbrella.io/install/). Follow the quick setup instructions on the download page to begin running API Umbrella. +## Additional Features + +In this repo is hosted an addittional feature of API-Umbrella f + ## Getting Started Once you have API Umbrella up and running, there are a variety of things you can do to start using the platform. For a quick tutorial, see [getting started](https://api-umbrella.readthedocs.org/en/latest/getting-started.html). diff --git a/bin/api-umbrella b/bin/api-umbrella old mode 100755 new mode 100644 diff --git a/bin/api-umbrella-cli b/bin/api-umbrella-cli old mode 100755 new mode 100644 diff --git a/bin/api-umbrella-exec b/bin/api-umbrella-exec old mode 100755 new mode 100644 diff --git a/bin/api-umbrella-geoip-auto-updater b/bin/api-umbrella-geoip-auto-updater old mode 100755 new mode 100644 diff --git a/bin/api-umbrella-nginx-reloader b/bin/api-umbrella-nginx-reloader old mode 100755 new mode 100644 diff --git a/bin/docker-compose/make b/bin/docker-compose/make old mode 100755 new mode 100644 diff --git a/bin/docker-compose/rake b/bin/docker-compose/rake old mode 100755 new mode 100644 diff --git a/build/package/build_package b/build/package/build_package old mode 100755 new mode 100644 diff --git a/build/package/docker_run b/build/package/docker_run old mode 100755 new mode 100644 diff --git a/build/package/docker_script b/build/package/docker_script old mode 100755 new mode 100644 diff --git a/build/package/files/etc/init.d/api-umbrella b/build/package/files/etc/init.d/api-umbrella old mode 100755 new mode 100644 diff --git a/build/package/parse_version b/build/package/parse_version old mode 100755 new mode 100644 diff --git a/build/package/publish b/build/package/publish old mode 100755 new mode 100644 diff --git a/build/package/scripts/after-install b/build/package/scripts/after-install old mode 100755 new mode 100644 diff --git a/build/package/scripts/after-remove b/build/package/scripts/after-remove old mode 100755 new mode 100644 diff --git a/build/package/scripts/before-remove b/build/package/scripts/before-remove old mode 100755 new mode 100644 diff --git a/build/package/verify/docker_run b/build/package/verify/docker_run old mode 100755 new mode 100644 diff --git a/build/package/verify/docker_script b/build/package/verify/docker_script old mode 100755 new mode 100644 diff --git a/build/package/verify/download_previous_packages b/build/package/verify/download_previous_packages old mode 100755 new mode 100644 diff --git a/build/scripts/distclean b/build/scripts/distclean old mode 100755 new mode 100644 diff --git a/build/scripts/download_cmake b/build/scripts/download_cmake old mode 100755 new mode 100644 diff --git a/build/scripts/install_build_dependencies b/build/scripts/install_build_dependencies old mode 100755 new mode 100644 diff --git a/configure b/configure old mode 100755 new mode 100644 diff --git a/docker/dev/docker-start b/docker/dev/docker-start old mode 100755 new mode 100644 diff --git a/scripts/fix-log-geoip/fix b/scripts/fix-log-geoip/fix old mode 100755 new mode 100644 diff --git a/scripts/generate_user_agent_data b/scripts/generate_user_agent_data old mode 100755 new mode 100644 diff --git a/scripts/import_access_logs/import b/scripts/import_access_logs/import old mode 100755 new mode 100644 diff --git a/scripts/replay_logs b/scripts/replay_logs old mode 100755 new mode 100644 diff --git a/src/api-umbrella/web-app/bin/bundle b/src/api-umbrella/web-app/bin/bundle old mode 100755 new mode 100644 diff --git a/src/api-umbrella/web-app/bin/delayed_job b/src/api-umbrella/web-app/bin/delayed_job old mode 100755 new mode 100644 diff --git a/src/api-umbrella/web-app/bin/rails b/src/api-umbrella/web-app/bin/rails old mode 100755 new mode 100644 diff --git a/src/api-umbrella/web-app/bin/rake b/src/api-umbrella/web-app/bin/rake old mode 100755 new mode 100644 diff --git a/src/api-umbrella/web-app/bin/setup b/src/api-umbrella/web-app/bin/setup old mode 100755 new mode 100644 diff --git a/src/api-umbrella/web-app/bin/spring b/src/api-umbrella/web-app/bin/spring old mode 100755 new mode 100644 diff --git a/src/api-umbrella/web-app/script/migrate_logs b/src/api-umbrella/web-app/script/migrate_logs old mode 100755 new mode 100644 diff --git a/src/api-umbrella/web-app/script/migrate_users b/src/api-umbrella/web-app/script/migrate_users old mode 100755 new mode 100644 diff --git a/templates/etc/perp/.boot/rc.log b/templates/etc/perp/.boot/rc.log old mode 100755 new mode 100644 diff --git a/templates/etc/perp/.boot/rc.perp.mustache b/templates/etc/perp/.boot/rc.perp.mustache old mode 100755 new mode 100644 diff --git a/templates/etc/perp/dev-env-ember-server/rc.log b/templates/etc/perp/dev-env-ember-server/rc.log old mode 100755 new mode 100644 diff --git a/templates/etc/perp/dev-env-ember-server/rc.main.mustache b/templates/etc/perp/dev-env-ember-server/rc.main.mustache old mode 100755 new mode 100644 diff --git a/templates/etc/perp/elasticsearch/rc.log b/templates/etc/perp/elasticsearch/rc.log old mode 100755 new mode 100644 diff --git a/templates/etc/perp/elasticsearch/rc.main.mustache b/templates/etc/perp/elasticsearch/rc.main.mustache old mode 100755 new mode 100644 diff --git a/templates/etc/perp/flume/rc.log b/templates/etc/perp/flume/rc.log old mode 100755 new mode 100644 diff --git a/templates/etc/perp/flume/rc.main.mustache b/templates/etc/perp/flume/rc.main.mustache old mode 100755 new mode 100644 diff --git a/templates/etc/perp/geoip-auto-updater/rc.log b/templates/etc/perp/geoip-auto-updater/rc.log old mode 100755 new mode 100644 diff --git a/templates/etc/perp/geoip-auto-updater/rc.main.mustache b/templates/etc/perp/geoip-auto-updater/rc.main.mustache old mode 100755 new mode 100644 diff --git a/templates/etc/perp/kylin/rc.log b/templates/etc/perp/kylin/rc.log old mode 100755 new mode 100644 diff --git a/templates/etc/perp/kylin/rc.main.mustache b/templates/etc/perp/kylin/rc.main.mustache old mode 100755 new mode 100644 diff --git a/templates/etc/perp/kylin/rc.run.mustache b/templates/etc/perp/kylin/rc.run.mustache old mode 100755 new mode 100644 diff --git a/templates/etc/perp/mongod/rc.log b/templates/etc/perp/mongod/rc.log old mode 100755 new mode 100644 diff --git a/templates/etc/perp/mongod/rc.main.mustache b/templates/etc/perp/mongod/rc.main.mustache old mode 100755 new mode 100644 diff --git a/templates/etc/perp/mora/rc.log b/templates/etc/perp/mora/rc.log old mode 100755 new mode 100644 diff --git a/templates/etc/perp/mora/rc.main.mustache b/templates/etc/perp/mora/rc.main.mustache old mode 100755 new mode 100644 diff --git a/templates/etc/perp/nginx-reloader/rc.log b/templates/etc/perp/nginx-reloader/rc.log old mode 100755 new mode 100644 diff --git a/templates/etc/perp/nginx-reloader/rc.main.mustache b/templates/etc/perp/nginx-reloader/rc.main.mustache old mode 100755 new mode 100644 diff --git a/templates/etc/perp/nginx/rc.log b/templates/etc/perp/nginx/rc.log old mode 100755 new mode 100644 diff --git a/templates/etc/perp/nginx/rc.main.mustache b/templates/etc/perp/nginx/rc.main.mustache old mode 100755 new mode 100644 diff --git a/templates/etc/perp/presto/rc.log b/templates/etc/perp/presto/rc.log old mode 100755 new mode 100644 diff --git a/templates/etc/perp/presto/rc.main.mustache b/templates/etc/perp/presto/rc.main.mustache old mode 100755 new mode 100644 diff --git a/templates/etc/perp/rc.log.mustache b/templates/etc/perp/rc.log.mustache old mode 100755 new mode 100644 diff --git a/templates/etc/perp/rsyslog/rc.log b/templates/etc/perp/rsyslog/rc.log old mode 100755 new mode 100644 diff --git a/templates/etc/perp/rsyslog/rc.main.mustache b/templates/etc/perp/rsyslog/rc.main.mustache old mode 100755 new mode 100644 diff --git a/templates/etc/perp/test-env-mailhog/rc.log b/templates/etc/perp/test-env-mailhog/rc.log old mode 100755 new mode 100644 diff --git a/templates/etc/perp/test-env-mailhog/rc.main.mustache b/templates/etc/perp/test-env-mailhog/rc.main.mustache old mode 100755 new mode 100644 diff --git a/templates/etc/perp/test-env-mongo-orchestration/rc.log b/templates/etc/perp/test-env-mongo-orchestration/rc.log old mode 100755 new mode 100644 diff --git a/templates/etc/perp/test-env-mongo-orchestration/rc.main.mustache b/templates/etc/perp/test-env-mongo-orchestration/rc.main.mustache old mode 100755 new mode 100644 diff --git a/templates/etc/perp/test-env-nginx/rc.log b/templates/etc/perp/test-env-nginx/rc.log old mode 100755 new mode 100644 diff --git a/templates/etc/perp/test-env-nginx/rc.main.mustache b/templates/etc/perp/test-env-nginx/rc.main.mustache old mode 100755 new mode 100644 diff --git a/templates/etc/perp/test-env-openldap/rc.log b/templates/etc/perp/test-env-openldap/rc.log old mode 100755 new mode 100644 diff --git a/templates/etc/perp/test-env-openldap/rc.main.mustache b/templates/etc/perp/test-env-openldap/rc.main.mustache old mode 100755 new mode 100644 diff --git a/templates/etc/perp/test-env-unbound/rc.log b/templates/etc/perp/test-env-unbound/rc.log old mode 100755 new mode 100644 diff --git a/templates/etc/perp/test-env-unbound/rc.main.mustache b/templates/etc/perp/test-env-unbound/rc.main.mustache old mode 100755 new mode 100644 diff --git a/templates/etc/perp/trafficserver/rc.log b/templates/etc/perp/trafficserver/rc.log old mode 100755 new mode 100644 diff --git a/templates/etc/perp/trafficserver/rc.main.mustache b/templates/etc/perp/trafficserver/rc.main.mustache old mode 100755 new mode 100644 diff --git a/templates/etc/perp/web-delayed-job/rc.log b/templates/etc/perp/web-delayed-job/rc.log old mode 100755 new mode 100644 diff --git a/templates/etc/perp/web-delayed-job/rc.main.mustache b/templates/etc/perp/web-delayed-job/rc.main.mustache old mode 100755 new mode 100644 diff --git a/templates/etc/perp/web-puma/rc.log b/templates/etc/perp/web-puma/rc.log old mode 100755 new mode 100644 diff --git a/templates/etc/perp/web-puma/rc.main.mustache b/templates/etc/perp/web-puma/rc.main.mustache old mode 100755 new mode 100644 diff --git a/test/scripts/circle-ci b/test/scripts/circle-ci old mode 100755 new mode 100644 From 0ee3b3dcbb12c7c195f843182c1e2f11f27eed43 Mon Sep 17 00:00:00 2001 From: anmunoz Date: Wed, 14 Feb 2018 16:57:45 +0100 Subject: [PATCH 21/27] Adding documentation for using external IdP validation --- README.md | 3 +- docker-ging/Dockerfile | 23 ++++ docs/idp-doc.md | 168 ++++++++++++++++++++++++++++++ docs/images/create-backend-ex.png | Bin 0 -> 80121 bytes docs/images/create-backend.png | Bin 0 -> 66742 bytes docs/images/idp-arch.png | Bin 0 -> 84215 bytes 6 files changed, 193 insertions(+), 1 deletion(-) create mode 100644 docker-ging/Dockerfile create mode 100644 docs/idp-doc.md create mode 100644 docs/images/create-backend-ex.png create mode 100644 docs/images/create-backend.png create mode 100644 docs/images/idp-arch.png diff --git a/README.md b/README.md index 9bef2d69e..05900ed62 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,8 @@ Binary packages are available for [download](https://apiumbrella.io/install/). F ## Additional Features -In this repo is hosted an addittional feature of API-Umbrella f +In this repo is hosted one additional feature of API-Umbrella for providing validation using external IdP's. +The documentation about how to use is available here: [Documentation](./docs/idp-doc.md) ## Getting Started diff --git a/docker-ging/Dockerfile b/docker-ging/Dockerfile new file mode 100644 index 000000000..27a0ccaf8 --- /dev/null +++ b/docker-ging/Dockerfile @@ -0,0 +1,23 @@ +FROM centos:centos6 + +ENV API_UMBRELLA_VERSION 0.14.4-1~centos + +# Install API Umbrella +RUN yum -y update; yum clean all +RUN yum -y install git +RUN groupadd -r api-umbrella && \ +useradd -r -g api-umbrella -s /sbin/nologin -d /opt/api-umbrella -c "API Umbrella user" api-umbrella +RUN git clone https://github.com/ging/api-umbrella.git +RUN chmod 775 -R ./api-umbrella +RUN cd ./api-umbrella && ./build/scripts/install_build_dependencies && ./configure && make && make install + + +# Define mountable directories +VOLUME ["/etc/api-umbrella", "/opt/api-umbrella/var/db", "/opt/api-umbrella/var/log"] + +# Expose HTTP and HTTPS ports +EXPOSE 80 443 + +# Run the API Umbrella service +CMD ["api-umbrella", "run"] + diff --git a/docs/idp-doc.md b/docs/idp-doc.md new file mode 100644 index 000000000..0ef443613 --- /dev/null +++ b/docs/idp-doc.md @@ -0,0 +1,168 @@ +##External IdP Validation + +This new feature allows to the API-umbrella users +the possibility of make request to a registered API + backend, using an API key or an OAuth2 token. + If the user uses a token in the request, this token is verified using an external IdP, once the token is validated the user information is retrieved and redirect to the API backend following the usual workflow. + The list of IdP's + included in this development are: + +* Fiware +* Google +* Facebook +* GitHub + +Hence, after the inclusion of this feature, +the gatekeeper architecture is modified +as is showed in the next figure: + +![API-Umbrella architecture](./images/idp-arch.png) + +##Getting Started + +###Installation +For using API-Umbrella with External IdP validation, you have to clone +this repo and install API-Umbrella from source code. The instructions fordoing this are: + +Note: This installation was tested with centos 6 and 7 with other Linux +distribution should work too but, is recommended to use centos + +First, clone the repo and install: + +``` +$ git clone https://github.com/ging/api-umbrella.git +$ chmod 775 -R ./api-umbrella +$ cd api-umbrella +$ sudo ./build/scripts/install_build_dependencies +$ ./configure +$ make +$ sudo make install +``` +This process could take some minutes while it download and install the dependencies. + +Second, start API-Umbrella + +``` +sudo /etc/init.d/api-umbrella start +``` +###Docker API-Umbrella + +Also, you have the option of use a docker container instead of install +API-Umbrella. The instructions for creating and running the docker +container with this version of API umbrella are: + +Build the API-Umbrella container: + +``` +$ git clone https://github.com/ging/api-umbrella.git +$ cd api-umbrella/docker-ging +$ docker build -t umbrella:0.14.4 . +``` + +Once you have your api-umbrella image, you can run the container and use it + +``` +$ docker run -d --name=api-umbrella -p 80:80 -p 443:443 umbrella:0.14.4 +``` + +### Admin and User guide + +At this point, you can perform the same operations described in +[getting started](https://api-umbrella.readthedocs.org/en/latest/getting-started.html). but Also +in this section is included the guide of how to create API backends for processing +the requests using Oauth2 token and external IdP's + +####Registering and API-Backend +The next figures show the Web UI for creating an API backend. You need to + fill the fields for registering you API but, for choosing +the external IdP in order to validate the user's token you have to go to +the **Global request setting** dropdown, in that part of the page, you have to choose +between the available IdP's in the option **External Identity Provider** +. Once you were selected the IdP, you need to save the backend and publish it + +![API-backend creation](./images/create-backend.png) +![API-backend creation](./images/create-backend-ex.png) + +#### Making requests to your API's + +For making requests to your API's with the external IdP validation +you need to send the Oauth2 user token by param or header. + +Sending the token by param: +``` +curl -k "https:///?token=" + +``` +An example of using the google maps API backend registered in API-Umbrella: + +``` +curl -k "https://127.0.0.1/distance1/maps/api/distancematrix/json?units=imperial&origins=Washington,DC&destinations=New+York+City,NY&token=XXXXXXXXXX" +``` +Output: +``` +{ + "destination_addresses" : [ "New York, NY, USA" ], + "origin_addresses" : [ "Washington, DC, USA" ], + "rows" : [ + { + "elements" : [ + { + "distance" : { + "text" : "225 mi", + "value" : 361940 + }, + "duration" : { + "text" : "3 hours 51 mins", + "value" : 13839 + }, + "status" : "OK" + } + ] + } + ], + "status" : "OK" +} + +``` + +For sending the token via header: + +``` +curl -k -H "X-Auth-Token:" "https:///" +``` + +An example using the same API backend of google maps. + +``` +curl -k -H "X-Auth-Token:XXXXXX" "https://127.0.0.1/distance/maps/api/distancematrix/json?units=imperial&origins=Washington,DC&destinations=New+York+City,NY" +``` +Output: +``` +{ + "destination_addresses" : [ "New York, NY, USA" ], + "origin_addresses" : [ "Washington, DC, USA" ], + "rows" : [ + { + "elements" : [ + { + "distance" : { + "text" : "225 mi", + "value" : 361940 + }, + "duration" : { + "text" : "3 hours 51 mins", + "value" : 13839 + }, + "status" : "OK" + } + ] + } + ], + "status" : "OK" +} + +``` +For any additional questions or support please send an email to: + +* + diff --git a/docs/images/create-backend-ex.png b/docs/images/create-backend-ex.png new file mode 100644 index 0000000000000000000000000000000000000000..9e9144ec5e3cbfbd84f08adee59f06611e8adceb GIT binary patch literal 80121 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 L1-nn^bo}g}fjfDa literal 0 HcmV?d00001 diff --git a/docs/images/create-backend.png b/docs/images/create-backend.png new file mode 100644 index 0000000000000000000000000000000000000000..95b7bd570706fc4956f22bce74a44a51d35430d3 GIT binary patch literal 66742 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

!l4mQuZaHK%Wo_cFA|FG3R)(s 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 DNrNHo literal 0 HcmV?d00001 From fb48514a9a4515dadd771fc287380eac87e0ff8f Mon Sep 17 00:00:00 2001 From: anmunoz Date: Wed, 14 Feb 2018 17:01:17 +0100 Subject: [PATCH 22/27] Correcting the documentation --- docs/idp-doc.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/idp-doc.md b/docs/idp-doc.md index 0ef443613..ba5a639f6 100644 --- a/docs/idp-doc.md +++ b/docs/idp-doc.md @@ -1,4 +1,4 @@ -##External IdP Validation +## External IdP Validation This new feature allows to the API-umbrella users the possibility of make request to a registered API @@ -18,9 +18,9 @@ as is showed in the next figure: ![API-Umbrella architecture](./images/idp-arch.png) -##Getting Started +## Getting Started -###Installation +### Installation For using API-Umbrella with External IdP validation, you have to clone this repo and install API-Umbrella from source code. The instructions fordoing this are: @@ -45,7 +45,7 @@ Second, start API-Umbrella ``` sudo /etc/init.d/api-umbrella start ``` -###Docker API-Umbrella +### Docker API-Umbrella Also, you have the option of use a docker container instead of install API-Umbrella. The instructions for creating and running the docker @@ -72,7 +72,7 @@ At this point, you can perform the same operations described in in this section is included the guide of how to create API backends for processing the requests using Oauth2 token and external IdP's -####Registering and API-Backend +#### Registering and API-Backend The next figures show the Web UI for creating an API backend. You need to fill the fields for registering you API but, for choosing the external IdP in order to validate the user's token you have to go to From a1d583c2c2d54ccdbfd012be52f376b928a64986 Mon Sep 17 00:00:00 2001 From: anmunoz Date: Mon, 26 Feb 2018 16:02:45 +0100 Subject: [PATCH 23/27] documentation update --- docs/idp-doc.md | 55 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/docs/idp-doc.md b/docs/idp-doc.md index ba5a639f6..1c681f780 100644 --- a/docs/idp-doc.md +++ b/docs/idp-doc.md @@ -51,7 +51,13 @@ Also, you have the option of use a docker container instead of install API-Umbrella. The instructions for creating and running the docker container with this version of API umbrella are: -Build the API-Umbrella container: +You can run directly the container pulling the image from the docker hub: + +``` +$ docker run -d --name=api-umbrella -p 80:80 -p 443:443 martel/api-umbrella +``` + +Or build the API-Umbrella image and run the container: ``` $ git clone https://github.com/ging/api-umbrella.git @@ -72,6 +78,53 @@ At this point, you can perform the same operations described in in this section is included the guide of how to create API backends for processing the requests using Oauth2 token and external IdP's +#### Registering and API-Backend uding API REST + +The procedure of how you can create a request using an REST call is available in the official documentation but, +for using the external validation feature you need to include in you JSON body request the field ** require_idp: ** where IdP value could be one of this: fiware-oauth2, google-oauth2, facebook-oauth2, github-oauth2. + +An request example for registring a API-backend with a generic parameters is: + +``` +curl -k -X POST "https:///api-umbrella/v1/apis" -H "X-Api-Key: " -H "X-Admin-Auth-Token: " -H "Accept: application/json" -H "Content-Type: application/json" -d @- < Date: Mon, 19 Mar 2018 16:41:25 +0100 Subject: [PATCH 24/27] Pre-merge for validating trusted applications --- config/default.yml | 4 ++++ docs/idp-doc.md | 2 +- .../proxy/middleware/api_key_validator.lua | 7 ++++++- src/api-umbrella/proxy/user_store.lua | 3 +++ .../utils/trusted_app_validation.lua | 17 +++++++++++++++++ 5 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 src/api-umbrella/utils/trusted_app_validation.lua diff --git a/config/default.yml b/config/default.yml index 543d95183..090c215cd 100644 --- a/config/default.yml +++ b/config/default.yml @@ -300,6 +300,10 @@ apiSettings: status_code: 403 code: API_KEY_OR_TOKEN_UNAUTHORIZED message: The api_key or token supplied is not authorized to access the given service. Contact us at {{contact_url}} for assistance + not_trusted_app: + status_code: 403 + code: NOT_TRUSTED_APPLICATION + message: The application trying to access the API_BACKEND is not trusted over_rate_limit: status_code: 429 code: OVER_RATE_LIMIT diff --git a/docs/idp-doc.md b/docs/idp-doc.md index 1c681f780..7cec0db15 100644 --- a/docs/idp-doc.md +++ b/docs/idp-doc.md @@ -110,7 +110,7 @@ curl -k -X POST "https:///api-umbrella/v1/apis" -H "settings": { "require_https":"required_return_error", "require_idp": "fiware-oauth2", - "disable_api_key":"true", + "disable_api_key":"false", "api_key_verification_level":"none", "rate_limit_mode":"unlimited", "error_templates": {}, diff --git a/src/api-umbrella/proxy/middleware/api_key_validator.lua b/src/api-umbrella/proxy/middleware/api_key_validator.lua index 0a507ef1d..b00b57c4c 100644 --- a/src/api-umbrella/proxy/middleware/api_key_validator.lua +++ b/src/api-umbrella/proxy/middleware/api_key_validator.lua @@ -6,7 +6,7 @@ local is_empty = types.is_empty local function resolve_api_key() local api_key_methods = config["gatekeeper"]["api_key_methods"] - local key = {key_value="", key_type="", idp=nil } + local key = {key_value="", key_type="", idp=nil, trusted_apps=nil} -- The api_key variable is a dictionary compose by three elements, the key_value which stores -- the api_key value or the user token value, the key_type field in where is stored @@ -50,6 +50,7 @@ return function(settings) -- Find if and IdP was set if settings["require_idp"] then api_key.idp=settings["require_idp"] + api_key.trusted_apps = settings["trusted_apps"] end if is_empty(api_key["key_value"]) then if settings and settings["disable_api_key"] then @@ -64,6 +65,10 @@ return function(settings) if not user then return nil, "api_key_invalid" end + -- Verify if the app that makes the request is in the trusted app list of the API Backend + if api_key["key_type"]== "token" and user["trusted_app"]== "not_trusted" then + return nil, "not_trusted_app" + end -- Store the api key on the user object for easier access (the user object -- doesn't contain it directly, to save memory storage in the lookup table). diff --git a/src/api-umbrella/proxy/user_store.lua b/src/api-umbrella/proxy/user_store.lua index 56fa46ce6..5413c0102 100644 --- a/src/api-umbrella/proxy/user_store.lua +++ b/src/api-umbrella/proxy/user_store.lua @@ -9,6 +9,7 @@ local shcache = require "shcache" local types = require "pl.types" local utils = require "api-umbrella.proxy.utils" local idp = require "api-umbrella.utils.idp" +local trusted_app = require "api-umbrella.utils.trusted_app_validation" local cache_computed_settings = utils.cache_computed_settings local is_empty = types.is_empty @@ -53,9 +54,11 @@ local function lookup_user(api_key) else user["id"] = raw_user["_id"] end + if api_key["idp"] and api_key["key_type"]=="token" and api_key["idp"]== "fiware-oauth2" then user["id"] = raw_user.id user["email"] = raw_user.email + user["trusted_app"]= trusted_app.trusted_app_validation(raw_user.app_id,api_key["trusted_apps"]) elseif api_key["idp"] and api_key["key_type"]=="token" and api_key["idp"]~= "fiware-oauth2" then user["id"] = raw_user.name user["email"] = raw_user.email diff --git a/src/api-umbrella/utils/trusted_app_validation.lua b/src/api-umbrella/utils/trusted_app_validation.lua new file mode 100644 index 000000000..1b3058dcd --- /dev/null +++ b/src/api-umbrella/utils/trusted_app_validation.lua @@ -0,0 +1,17 @@ +-- +-- Created by: anmunoz +-- Date: 3/16/18 +-- Time: 2:03 PM +-- +local _output_value = {} +function _output_value.trusted_app_validation(app_id_scope,trusted_app_list) + for _, trusted_app_id in ipairs(trusted_app_list) do + if app_id_scope == trusted_app_id.id then + _output_value="trusted" + return _output_value + end + end + _output_value="not_trusted" + return _output_value +end +return _output_value \ No newline at end of file From cf690084b92c3c8c4e9ffd052f9fe96806216071 Mon Sep 17 00:00:00 2001 From: anmunoz Date: Mon, 8 Oct 2018 10:43:31 +0200 Subject: [PATCH 25/27] adding new type of requests for FIWARE IDP, now is possible to work in mode authentication and authorization, for these reasons the request to the IDM are different. For authentication the url needs to include the token and the app-ID and for authorization is needed to include, token, action, resource and app-ID --- .../proxy/middleware/api_key_validator.lua | 2 ++ src/api-umbrella/utils/idp.lua | 13 +++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/api-umbrella/proxy/middleware/api_key_validator.lua b/src/api-umbrella/proxy/middleware/api_key_validator.lua index b00b57c4c..34ce1b78b 100644 --- a/src/api-umbrella/proxy/middleware/api_key_validator.lua +++ b/src/api-umbrella/proxy/middleware/api_key_validator.lua @@ -51,6 +51,8 @@ return function(settings) if settings["require_idp"] then api_key.idp=settings["require_idp"] api_key.trusted_apps = settings["trusted_apps"] + api_key.app_id = settings["idp_app_id"] + api_key.mode = settings["idp_mode"] end if is_empty(api_key["key_value"]) then if settings and settings["disable_api_key"] then diff --git a/src/api-umbrella/utils/idp.lua b/src/api-umbrella/utils/idp.lua index ad0496a1b..8909ac95d 100644 --- a/src/api-umbrella/utils/idp.lua +++ b/src/api-umbrella/utils/idp.lua @@ -11,8 +11,10 @@ local _M = {} function _M.first(dict) local idp_back_name = dict["idp"] local token = dict["key_value"] - local idp_host, result, res, err, rpath + local idp_host, result, res, err, rpath,resource, method local ssl=false + local app_id = dict["app_id"] + local mode = dict["mode"] local httpc = http.new() httpc:set_timeout(45000) @@ -23,9 +25,16 @@ function _M.first(dict) if idp_back_name == "google-oauth2" then rpath = "/oauth2/v3/userinfo" idp_host="https://www.googleapis.com" - elseif idp_back_name == "fiware-oauth2" then + elseif idp_back_name == "fiware-oauth2" and mode == "authorization" then rpath = "/user" idp_host="https://130.206.84.14" + resource = ngx.ctx.uri + method = ngx.ctx.request_method + rquery = "access_token="..token.."&app_id="..app_id.."&resource="..resource.."&action="..method + elseif idp_back_name == "fiware-oauth2" and mode == "authentication" then + rpath = "/user" + idp_host="https://130.206.84.14" + rquery = "access_token="..token.."&app_id="..app_id elseif idp_back_name == "facebook-oauth2" then rpath = "/me" idp_host="https://graph.facebook.com" From ee9b3b8807441d486e5b0bb1720b9f583034e2e9 Mon Sep 17 00:00:00 2001 From: anmunoz Date: Mon, 8 Oct 2018 12:11:13 +0200 Subject: [PATCH 26/27] working with default IDP declared in he config.yml --- config/default.yml | 11 +++++++++++ .../proxy/middleware/api_key_validator.lua | 1 + src/api-umbrella/utils/idp.lua | 4 ++-- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/config/default.yml b/config/default.yml index 6791050a2..e59b25fd7 100644 --- a/config/default.yml +++ b/config/default.yml @@ -59,6 +59,17 @@ gatekeeper: - getParam - basicAuthUsername api_key_cache: false + api_key_cache: true + positive_ttl: 120 + negative_ttl: 60 + idp_providers: + - fiware-oauth2 + - github-oauth2 + - facebook-oauth2 + - google-oauth2 + default_idp: + backend_name: fiware-oauth2 + host: http://138.4.7.8:8000 trafficserver: host: 127.0.0.1 port: 14009 diff --git a/src/api-umbrella/proxy/middleware/api_key_validator.lua b/src/api-umbrella/proxy/middleware/api_key_validator.lua index 34ce1b78b..128c93c05 100644 --- a/src/api-umbrella/proxy/middleware/api_key_validator.lua +++ b/src/api-umbrella/proxy/middleware/api_key_validator.lua @@ -49,6 +49,7 @@ return function(settings) local api_key = resolve_api_key() -- Find if and IdP was set if settings["require_idp"] then + api_key.idp=config["gatekeeper"]["default_idp"] api_key.idp=settings["require_idp"] api_key.trusted_apps = settings["trusted_apps"] api_key.app_id = settings["idp_app_id"] diff --git a/src/api-umbrella/utils/idp.lua b/src/api-umbrella/utils/idp.lua index 8909ac95d..b992269bf 100644 --- a/src/api-umbrella/utils/idp.lua +++ b/src/api-umbrella/utils/idp.lua @@ -27,13 +27,13 @@ function _M.first(dict) idp_host="https://www.googleapis.com" elseif idp_back_name == "fiware-oauth2" and mode == "authorization" then rpath = "/user" - idp_host="https://130.206.84.14" + idp_host=dict["idp"]["host"] resource = ngx.ctx.uri method = ngx.ctx.request_method rquery = "access_token="..token.."&app_id="..app_id.."&resource="..resource.."&action="..method elseif idp_back_name == "fiware-oauth2" and mode == "authentication" then rpath = "/user" - idp_host="https://130.206.84.14" + idp_host=dict["idp"]["host"] rquery = "access_token="..token.."&app_id="..app_id elseif idp_back_name == "facebook-oauth2" then rpath = "/me" From b58c352b54de3d438a819fd8e31a81f42bf3858f Mon Sep 17 00:00:00 2001 From: anmunoz Date: Mon, 8 Oct 2018 13:06:01 +0200 Subject: [PATCH 27/27] correction config.yml --- config/default.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/config/default.yml b/config/default.yml index e59b25fd7..34e5fe1fb 100644 --- a/config/default.yml +++ b/config/default.yml @@ -59,7 +59,6 @@ gatekeeper: - getParam - basicAuthUsername api_key_cache: false - api_key_cache: true positive_ttl: 120 negative_ttl: 60 idp_providers: @@ -69,7 +68,7 @@ gatekeeper: - google-oauth2 default_idp: backend_name: fiware-oauth2 - host: http://138.4.7.8:8000 + host: http://138.4.7.8:8000 trafficserver: host: 127.0.0.1 port: 14009