fix(core): upstream openresty fixes; lua global scope pollution
diff --git a/.dockerignore b/.dockerignore
index 1b5d582..b6643df 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -5,3 +5,4 @@
 Dockerfile
 Makefile
 README.md
+tools/
diff --git a/Dockerfile b/Dockerfile
index 30a35ce..ce8d088 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -17,7 +17,7 @@
 
 # apigateway
 #
-# VERSION               1.15.8.3
+# VERSION               1.17.8.2
 #
 # From https://hub.docker.com/_/alpine/
 #
@@ -37,7 +37,7 @@
     && rm -rf /var/cache/apk/*
 
 # openresty build
-ENV OPENRESTY_VERSION=1.15.8.3 \
+ENV OPENRESTY_VERSION=1.17.8.2 \
     PCRE_VERSION=8.37 \
     TEST_NGINX_VERSION=0.24 \
     OPM_VERSION=0.0.5 \
diff --git a/scripts/lua/lib/dataStore.lua b/scripts/lua/lib/dataStore.lua
index 57a86cc..453576a 100644
--- a/scripts/lua/lib/dataStore.lua
+++ b/scripts/lua/lib/dataStore.lua
@@ -34,7 +34,7 @@
 
 function DataStore:setSnapshotId(tenant)
   self.snapshotId = self.impl.getSnapshotId(self.ds, tenant)
-  self:lockSnapshot(snapshotId)
+  self:lockSnapshot(self.snapshotId)
   if self.snapshotId == ngx.null then
     self.snapshotId = nil
   end
@@ -159,7 +159,7 @@
 
 function DataStore:getSubscriptions(artifactId, tenantId)
   self:singleInit()
-  return self.impl.deleteSubscription(self.ds, key, self.snapshotId)
+  return self.impl.getSubscriptions(self.ds, artifactId, tenantId, self.snapshotId)
 end
 
 function DataStore:healthCheck()
diff --git a/scripts/lua/lib/redis.lua b/scripts/lua/lib/redis.lua
index bd6701f..5c4da83 100644
--- a/scripts/lua/lib/redis.lua
+++ b/scripts/lua/lib/redis.lua
@@ -102,6 +102,169 @@
   end
 end
 
+-- LRU Caching methods
+
+--- Call function with retry logic
+-- @param func function to call
+-- @param args arguments to pass in to function
+local function call(func, args)
+  local res, err = func(unpack(args))
+  local retryCount = REDIS_RETRY_COUNT
+  while not res and retryCount > 0 do
+    res, err = func(unpack(args))
+    retryCount = retryCount - 1
+  end
+  return res, err
+end
+
+local function exists(red, key, snapshotId)
+  if snapshotId ~= nil then
+    key = utils.concatStrings({'snapshots:', snapshotId, ':', key})
+  end
+  if CACHING_ENABLED then
+    local cached = c:get(key)
+    if cached ~= nil then
+      return 1
+    end
+  -- if it isn't in the cache, try and load it in there
+    if red == nil then
+      red = _M.init()
+    end
+    local result = red:get(key)
+    if result ~= ngx.null then
+      c:set(key, result, CACHE_TTL)
+      return 1, red
+    end
+    return 0
+  else
+    if red == nil then
+      red = _M.init()
+    end
+    return call(red.exists, {red, key}), red
+  end
+end
+
+local function get(red, key)
+  if CACHING_ENABLED then
+    local cached, stale = c:get(key)
+    if cached ~= nil then
+      return cached
+    else
+      if red == nil then
+        red = _M.init()
+      end
+      local result = red:get(key)
+      c:set(key, result, CACHE_TTL)
+      return result, red
+    end
+  else
+    if red == nil then
+      red = _M.init()
+    end
+    return call(red.get, {red, key})
+  end
+end
+
+local function hget(red, key, id)
+  if CACHING_ENABLED then
+    local cachedmap, stale = c:get(key)
+    if cachedmap ~= nil then
+      local cached = cachedmap:get(id)
+      if cached ~= nil then
+         return cached
+      else
+        if red == nil then
+          red = _M.init()
+        end
+        local result = red:hget(key, id)
+        cachedmap:set(id, result, CACHE_TTL)
+        c:set(key, cachedmap, CACHE_TTL)
+        return result, red
+      end
+    else
+      if red == nil then
+        red = _M.init()
+      end
+      local result = red:hget(key, id)
+      local newcache = lrucache.new(CACHE_SIZE)
+      newcache:set(id, result, CACHE_TTL)
+      c:set(key, newcache, CACHE_TTL)
+      return result, red
+    end
+  else
+    if red == nil then
+      red = _M.init()
+    end
+    return call(red.hget, {red, key, id}), red
+  end
+end
+
+local function hgetall(red, key)
+  return call(red.hgetall, {red, key})
+end
+
+local function hset(red, key, id, value)
+  if CACHING_ENABLED then
+    local cachedmap = c:get(key)
+    if cachedmap ~= nil then
+      cachedmap:set(id, value, CACHE_TTL)
+      c:set(key, cachedmap, CACHE_TTL)
+      return red:hset(key, id, value)
+    else
+      local val = lrucache.new(CACHE_SIZE)
+      val:set(id, value, CACHE_TTL)
+      c:set(key, val, CACHE_TTL)
+    end
+  end
+  return call(red.hset, {red, key, id, value})
+end
+
+local function expire(red, key, ttl)
+  if CACHING_ENABLED then
+    local cached = c:get(key)
+    local value = ''
+    if cached ~= nil then -- just put it back in the cache with a ttl
+      value = cached
+    end
+    c:set(key, value, ttl)
+  end
+  return call(red.expire, {red, ttl})
+end
+
+local function del(red, key)
+  if CACHING_ENABLED then
+    c:delete(key)
+  end
+  return call(red.del, {red, key})
+end
+
+local function hdel(red, key, id)
+  if CACHING_ENABLED then
+    local cachecontents = c:get(key)
+    if cachecontents ~= nil then
+      cachecontents:del(id)
+      c:set(key, cachecontents, CACHE_TTL)
+    end
+  end
+  return call(red.hdel, {red, key, id})
+end
+
+local function set(red, key, value)
+  return call(red.set, {red, key, value})
+end
+
+local function smembers(red, key)
+  return call(red.smembers, {red, key})
+end
+
+local function srem(red, key, id)
+  return call(red.srem, {red, key, id})
+end
+
+local function sadd(red, key, id)
+  return call(red.sadd, {red, key, id})
+end
+
 ---------------------------
 ----------- APIs ----------
 ---------------------------
@@ -597,8 +760,8 @@
   if get(red, startingString) == nil then
     set(red, startingString, '')
   end
-  path = {}
-  key = {}
+  local path = {}
+  local key = {}
   for p in string.gmatch(pathStr, '[^/]*') do
     if p ~= '' then
       table.insert(path, p)
@@ -632,169 +795,6 @@
   red:expire(utils.concatStrings({'lock:snapshots:', snapshotId}), 60)
 end
 
--- LRU Caching methods
-
-function exists(red, key, snapshotId)
-  if snapshotId ~= nil then
-    key = utils.concatStrings({'snapshots:', snapshotId, ':', key})
-  end
-  if CACHING_ENABLED then
-    local cached = c:get(key)
-    if cached ~= nil then
-      return 1
-    end
-  -- if it isn't in the cache, try and load it in there
-    if red == nil then
-      red = _M.init()
-    end
-    local result = red:get(key)
-    if result ~= ngx.null then
-      c:set(key, result, CACHE_TTL)
-      return 1, red
-    end
-    return 0
-  else
-    if red == nil then
-      red = _M.init()
-    end
-    return call(red.exists, {red, key}), red
-  end
-end
-
-function get(red, key)
-  if CACHING_ENABLED then
-    local cached, stale = c:get(key)
-    if cached ~= nil then
-      return cached
-    else
-      if red == nil then
-        red = _M.init()
-      end
-      local result = red:get(key)
-      c:set(key, result, CACHE_TTL)
-      return result, red
-    end
-  else
-    if red == nil then
-      red = _M.init()
-    end
-    return call(red.get, {red, key})
-  end
-end
-
-function hget(red, key, id)
-  if CACHING_ENABLED then
-    local cachedmap, stale = c:get(key)
-    if cachedmap ~= nil then
-      local cached = cachedmap:get(id)
-      if cached ~= nil then
-         return cached
-      else
-        if red == nil then
-          red = _M.init()
-        end
-        local result = red:hget(key, id)
-        cachedmap:set(id, result, CACHE_TTL)
-        c:set(key, cachedmap, CACHE_TTL)
-        return result, red
-      end
-    else
-      if red == nil then
-        red = _M.init()
-      end
-      local result = red:hget(key, id)
-      local newcache = lrucache.new(CACHE_SIZE)
-      newcache:set(id, result, CACHE_TTL)
-      c:set(key, newcache, CACHE_TTL)
-      return result, red
-    end
-  else
-    if red == nil then
-      red = _M.init()
-    end
-    return call(red.hget, {red, key, id}), red
-  end
-end
-
-function hgetall(red, key)
-  return call(red.hgetall, {red, key})
-end
-
-function hset(red, key, id, value)
-  if CACHING_ENABLED then
-    local cachedmap = c:get(key)
-    if cachedmap ~= nil then
-      cachedmap:set(id, value, CACHE_TTL)
-      c:set(key, cachedmap, CACHE_TTL)
-      return red:hset(key, id, value)
-    else
-      local val = lrucache.new(CACHE_SIZE)
-      val:set(id, value, CACHE_TTL)
-      c:set(key, val, CACHE_TTL)
-    end
-  end
-  return call(red.hset, {red, key, id, value})
-end
-
-function expire(red, key, ttl)
-  if CACHING_ENABLED then
-    local cached = c:get(key)
-    local value = ''
-    if cached ~= nil then -- just put it back in the cache with a ttl
-      value = cached
-    end
-    c:set(key, value, ttl)
-  end
-  return call(red.expire, {red, ttl})
-end
-
-function del(red, key)
-  if CACHING_ENABLED then
-    c:delete(key)
-  end
-  return call(red.del, {red, key})
-end
-
-function hdel(red, key, id)
-  if CACHING_ENABLED then
-    local cachecontents = c:get(key)
-    if cachecontents ~= nil then
-      cachecontents:del(id)
-      c:set(key, cachecontents, CACHE_TTL)
-    end
-  end
-  return call(red.hdel, {red, key, id})
-end
-
-function set(red, key, value)
-  return call(red.set, {red, key, value})
-end
-
-function smembers(red, key)
-  return call(red.smembers, {red, key})
-end
-
-function srem(red, key, id)
-  return call(red.srem, {red, key, id})
-end
-
-function sadd(red, key, id)
-  return call(red.sadd, {red, key, id})
-end
-
---- Call function with retry logic
--- @param func function to call
--- @param args arguments to pass in to function
-function call(func, args)
-  local res, err = func(unpack(args))
-  local retryCount = REDIS_RETRY_COUNT
-  while not res and retryCount > 0 do
-    res, err = func(unpack(args))
-    retryCount = retryCount - 1
-  end
-  return res, err
-end
-
 _M.get = get
 _M.set = set
 _M.exists = exists
diff --git a/scripts/lua/lib/request.lua b/scripts/lua/lib/request.lua
index faa2caa..38f6eab 100644
--- a/scripts/lua/lib/request.lua
+++ b/scripts/lua/lib/request.lua
@@ -27,7 +27,7 @@
 --- Error function to call when request is malformed
 -- @param code error code
 -- @param msg error message
-function err(code, msg)
+local function err(code, msg)
   ngx.header.content_type = "application/json; charset=utf-8"
   ngx.status = code
   local errObj = cjson.encode({
@@ -41,7 +41,7 @@
 --- Function to call when request is successful
 -- @param code status code
 -- @param obj JSON encoded object to return
-function success(code, obj)
+local function success(code, obj)
   ngx.status = code
   if obj ~= nil then
     ngx.say(obj)
diff --git a/scripts/lua/lib/utils.lua b/scripts/lua/lib/utils.lua
index e9c2977..4c58f83 100644
--- a/scripts/lua/lib/utils.lua
+++ b/scripts/lua/lib/utils.lua
@@ -67,7 +67,7 @@
 -- @return concatenated string of (?<path_pathParam>(\\w+))
 function _Utils.convertTemplatedPathParam(m)
   local x = m:gsub("{", ""):gsub("}", "")
-  return concatStrings({"(?<path_" , x , ">([a-zA-Z0-9\\-\\s\\_\\%]*))"})
+  return _Utils.concatStrings({"(?<path_" , x , ">([a-zA-Z0-9\\-\\s\\_\\%]*))"})
 end
 
 --- Generate random uuid
diff --git a/scripts/lua/management/lib/apis.lua b/scripts/lua/management/lib/apis.lua
index 04161f2..b2efbd3 100644
--- a/scripts/lua/management/lib/apis.lua
+++ b/scripts/lua/management/lib/apis.lua
@@ -32,6 +32,33 @@
 
 local _M = {}
 
+--- Filter APIs based on query parameters
+-- @param apis list of apis
+-- @param queryParams query parameters to filter tenants
+local function filterAPIs(apis, queryParams)
+  local basePath = queryParams['filter[where][basePath]']
+  basePath = basePath == nil and queryParams['basePath'] or basePath
+  local name = queryParams['filter[where][name]']
+  name = name == nil and queryParams['title'] or name
+  -- missing or invalid query parameters
+  if (basePath == nil and name == nil) then
+    return nil
+  end
+  -- filter tenants
+  local apiList = {}
+  for k, v in pairs(apis) do
+    if k%2 == 0 then
+      local api = cjson.decode(v)
+      if (basePath ~= nil and name == nil and api.basePath == basePath) or
+          (name ~= nil and basePath == nil and api.name == name) or
+          (basePath ~= nil and name ~= nil and api.basePath == basePath and api.name == name) then
+        apiList[#apiList+1] = api
+      end
+    end
+  end
+  return apiList
+end
+
 --- Get all APIs in redis
 -- @param ds dataStore.client
 -- @param queryParams object containing optional query parameters
@@ -137,31 +164,4 @@
   return {}
 end
 
---- Filter APIs based on query parameters
--- @param apis list of apis
--- @param queryParams query parameters to filter tenants
-function filterAPIs(apis, queryParams)
-  local basePath = queryParams['filter[where][basePath]']
-  basePath = basePath == nil and queryParams['basePath'] or basePath
-  local name = queryParams['filter[where][name]']
-  name = name == nil and queryParams['title'] or name
-  -- missing or invalid query parameters
-  if (basePath == nil and name == nil) then
-    return nil
-  end
-  -- filter tenants
-  local apiList = {}
-  for k, v in pairs(apis) do
-    if k%2 == 0 then
-      local api = cjson.decode(v)
-      if (basePath ~= nil and name == nil and api.basePath == basePath) or
-          (name ~= nil and basePath == nil and api.name == name) or
-          (basePath ~= nil and name ~= nil and api.basePath == basePath and api.name == name) then
-        apiList[#apiList+1] = api
-      end
-    end
-  end
-  return apiList
-end
-
 return _M
diff --git a/scripts/lua/management/lib/swagger.lua b/scripts/lua/management/lib/swagger.lua
index d70c08c..b02397e 100644
--- a/scripts/lua/management/lib/swagger.lua
+++ b/scripts/lua/management/lib/swagger.lua
@@ -18,14 +18,201 @@
 --- @module swagger
 -- Module for parsing swagger file
 
-local _M = {}
 local utils = require "lib/utils"
 
+local _M = {}
+
+--- Parse request mapping
+local function parseRequestMapping(configObj)
+  local valueList = {}
+  if configObj ~= nil then
+    for _, obj in pairs(configObj.execute) do
+      for policy, v in pairs(obj) do
+        if policy == "set-variable" then
+          for _, actionObj in pairs(v.actions) do
+            local fromValue = actionObj.value
+            local toParsedArray = {string.match(actionObj.set, "([^.]+).([^.]+).([^.]+)") }
+            local toName = toParsedArray[3]
+            local toLocation = toParsedArray[2]
+            toLocation = toLocation == "headers" and "header" or toLocation
+            valueList[#valueList+1] = {
+              action = "insert",
+              from = {
+                value = fromValue
+              },
+              to = {
+                name = toName,
+                location = toLocation
+              }
+            }
+          end
+        end
+      end
+    end
+  end
+  if next(valueList) ~= nil then
+    return {
+      type = "reqMapping",
+      value = valueList
+    }
+  else
+    return nil
+  end
+end
+
+--- Parse backendUrl and backendMethod
+-- @param swagger swagger file to parse
+local function parseBackends(swagger)
+  local configObj = swagger["x-gateway-configuration"]
+  configObj = (configObj == nil) and swagger["x-ibm-configuration"] or configObj
+  if configObj ~= nil then
+    for _, obj in pairs(configObj.assembly.execute) do
+      for policy, v in pairs(obj) do
+        local res = {}
+        if policy == "operation-switch" then
+          local caseObj = v.case
+          for _, case in pairs(caseObj) do
+            for _, op in pairs(case.operations) do
+              res[op] = {}
+              for _, opPolicy in pairs(case.execute) do
+                if opPolicy.invoke ~= nil then
+                  res[op].backendUrl = opPolicy.invoke["target-url"]
+                  res[op].backendMethod = opPolicy.invoke.verb
+                elseif opPolicy["set-variable"] ~= nil then
+                  local reqMappingPolicy = parseRequestMapping(case)
+                  if reqMappingPolicy ~= nil then
+                    res[op].policy = reqMappingPolicy
+                  end
+                end
+              end
+            end
+          end
+          return res
+        end
+        if policy == "invoke" then
+          res["all"] = {
+            backendUrl = v["target-url"],
+            backendMethod = v.verb
+          }
+          return res
+        end
+      end
+    end
+  end
+end
+
+--- Parse rate limit
+local function parseRateLimit(rlObj)
+  if rlObj ~= nil and rlObj[1] ~= nil then
+    local unit
+    rlObj = rlObj[1]
+    if rlObj.unit == "second" then
+      unit = 1
+    elseif rlObj.unit == "minute" then
+      unit = 60
+    elseif rlObj.unit == "hour" then
+      unit = 3600
+    elseif rlObj.unit == "day" then
+      unit = 86400
+    else
+      unit = 60   -- default to minute
+    end
+    return {
+      type = "rateLimit",
+      value = {
+        interval = unit * rlObj.units,
+        rate = rlObj.rate,
+        scope = "api",
+        subscription = true
+      }
+    }
+  end
+  return nil
+end
+
+--- Parse policies in swagger
+-- @param swagger swagger file to parse
+local function parsePolicies(swagger)
+  local policies = {}
+  -- parse rate limit
+  local rlObj = swagger["x-gateway-rate-limit"]
+  rlObj = (rlObj == nil) and swagger["x-ibm-rate-limit"] or rlObj
+  local rateLimitPolicy = parseRateLimit(rlObj)
+  if rateLimitPolicy ~= nil then
+    policies[#policies+1] = rateLimitPolicy
+  end
+  -- parse set-variable
+  local configObj = swagger["x-gateway-configuration"]
+  configObj = (configObj == nil) and swagger["x-ibm-configuration"] or configObj
+  if configObj ~= nil then
+    local reqMappingPolicy = parseRequestMapping(configObj.assembly)
+    if reqMappingPolicy ~= nil then
+      policies[#policies+1] = reqMappingPolicy
+    end
+  end
+  return policies
+end
+
+--- Parse security in swagger
+-- @param swagger swagger file to parse
+local function parseSecurity(swagger)
+  local security = {}
+  if swagger["securityDefinitions"] ~= nil then
+    local secObject = swagger["securityDefinitions"]
+    if utils.tableLength(secObject) == 2 then
+      local secObj = {
+        type = 'clientSecret',
+        scope = 'api'
+      }
+      for key, sec in pairs(secObject) do
+        if key == 'client_id' then
+          secObj.idFieldName = sec.name
+        elseif key == 'client_secret' then
+          secObj.secretFieldName = sec.name
+        end
+      end
+      security[#security+1] = secObj
+    else
+      for key, sec in pairs(secObject) do
+        if sec.type == 'apiKey' then
+          security[#security+1] = {
+            type = sec.type,
+            scope = "api",
+            header = sec.name
+          }
+        elseif sec.type == 'oauth2' then
+          security[#security+1] = {
+            type = sec.type,
+            scope = "api",
+            provider = key
+          }
+        end
+      end
+    end
+  end
+  return security
+end
+
+local function parseCors(swagger)
+  local cors = { origin = nil, methods = nil }
+  local configObj = swagger["x-gateway-configuration"]
+  configObj = (configObj == nil) and swagger["x-ibm-configuration"] or configObj
+  if configObj.cors ~= nil then
+    if configObj.cors.enabled == true then
+      cors.origin = "true"
+    elseif configObj.cors.enabled == false then
+      cors.origin = "false"
+    end
+    return cors
+  end
+  return nil
+end
+
 -- Convert passed-in swagger body to valid lua table
 -- @param swagger swagger file to parse
 function _M.parseSwagger(swagger)
   local backends = parseBackends(swagger)
-  local policies = parseSwaggerPolicies(swagger)
+  local policies = parsePolicies(swagger)
   local security = parseSecurity(swagger)
   local corsObj = parseCors(swagger)
   local decoded = {
@@ -72,189 +259,4 @@
   return decoded
 end
 
---- Parse backendUrl and backendMethod
--- @param swagger swagger file to parse
-function parseBackends(swagger)
-  local configObj = swagger["x-gateway-configuration"]
-  configObj = (configObj == nil) and swagger["x-ibm-configuration"] or configObj
-  if configObj ~= nil then
-    for _, obj in pairs(configObj.assembly.execute) do
-      for policy, v in pairs(obj) do
-        local res = {}
-        if policy == "operation-switch" then
-          local caseObj = v.case
-          for _, case in pairs(caseObj) do
-            for _, op in pairs(case.operations) do
-              res[op] = {}
-              for _, opPolicy in pairs(case.execute) do
-                if opPolicy.invoke ~= nil then
-                  res[op].backendUrl = opPolicy.invoke["target-url"]
-                  res[op].backendMethod = opPolicy.invoke.verb
-                elseif opPolicy["set-variable"] ~= nil then
-                  local reqMappingPolicy = parseRequestMapping(case)
-                  if reqMappingPolicy ~= nil then
-                    res[op].policy = reqMappingPolicy
-                  end
-                end
-              end
-            end
-          end
-          return res
-        end
-        if policy == "invoke" then
-          res["all"] = {
-            backendUrl = v["target-url"],
-            backendMethod = v.verb
-          }
-          return res
-        end
-      end
-    end
-  end
-end
-
---- Parse policies in swagger
--- @param swagger swagger file to parse
-function parseSwaggerPolicies(swagger)
-  local policies = {}
-  -- parse rate limit
-  local rlObj = swagger["x-gateway-rate-limit"]
-  rlObj = (rlObj == nil) and swagger["x-ibm-rate-limit"] or rlObj
-  local rateLimitPolicy = parseRateLimit(rlObj)
-  if rateLimitPolicy ~= nil then
-    policies[#policies+1] = rateLimitPolicy
-  end
-  -- parse set-variable
-  local configObj = swagger["x-gateway-configuration"]
-  configObj = (configObj == nil) and swagger["x-ibm-configuration"] or configObj
-  if configObj ~= nil then
-    local reqMappingPolicy = parseRequestMapping(configObj.assembly)
-    if reqMappingPolicy ~= nil then
-      policies[#policies+1] = reqMappingPolicy
-    end
-  end
-  return policies
-end
-
---- Parse rate limit
-function parseRateLimit(rlObj)
-  if rlObj ~= nil and rlObj[1] ~= nil then
-    rlObj = rlObj[1]
-    if rlObj.unit == "second" then
-      unit = 1
-    elseif rlObj.unit == "minute" then
-      unit = 60
-    elseif rlObj.unit == "hour" then
-      unit = 3600
-    elseif rlObj.unit == "day" then
-      unit = 86400
-    else
-      unit = 60   -- default to minute
-    end
-    return {
-      type = "rateLimit",
-      value = {
-        interval = unit * rlObj.units,
-        rate = rlObj.rate,
-        scope = "api",
-        subscription = true
-      }
-    }
-  end
-  return nil
-end
-
---- Parse request mapping
-function parseRequestMapping(configObj)
-  local valueList = {}
-  if configObj ~= nil then
-    for _, obj in pairs(configObj.execute) do
-      for policy, v in pairs(obj) do
-        if policy == "set-variable" then
-          for _, actionObj in pairs(v.actions) do
-            local fromValue = actionObj.value
-            local toParsedArray = {string.match(actionObj.set, "([^.]+).([^.]+).([^.]+)") }
-            local toName = toParsedArray[3]
-            local toLocation = toParsedArray[2]
-            toLocation = toLocation == "headers" and "header" or toLocation
-            valueList[#valueList+1] = {
-              action = "insert",
-              from = {
-                value = fromValue
-              },
-              to = {
-                name = toName,
-                location = toLocation
-              }
-            }
-          end
-        end
-      end
-    end
-  end
-  if next(valueList) ~= nil then
-    return {
-      type = "reqMapping",
-      value = valueList
-    }
-  else
-    return nil
-  end
-end
-
---- Parse security in swagger
--- @param swagger swagger file to parse
-function parseSecurity(swagger)
-  local security = {}
-  if swagger["securityDefinitions"] ~= nil then
-    local secObject = swagger["securityDefinitions"]
-    if utils.tableLength(secObject) == 2 then
-      secObj = {
-        type = 'clientSecret',
-        scope = 'api'
-      }
-      for key, sec in pairs(secObject) do
-        if key == 'client_id' then
-          secObj.idFieldName = sec.name
-        elseif key == 'client_secret' then
-          secObj.secretFieldName = sec.name
-        end
-      end
-      security[#security+1] = secObj
-    else
-      for key, sec in pairs(secObject) do
-        if sec.type == 'apiKey' then
-          security[#security+1] = {
-            type = sec.type,
-            scope = "api",
-            header = sec.name
-          }
-        elseif sec.type == 'oauth2' then
-          security[#security+1] = {
-            type = sec.type,
-            scope = "api",
-            provider = key
-          }
-        end
-      end
-    end
-  end
-  return security
-end
-
-function parseCors(swagger)
-  local cors = { origin = nil, methods = nil }
-  local configObj = swagger["x-gateway-configuration"]
-  configObj = (configObj == nil) and swagger["x-ibm-configuration"] or configObj
-  if configObj.cors ~= nil then
-    if configObj.cors.enabled == true then
-      cors.origin = "true"
-    elseif configObj.cors.enabled == false then
-      cors.origin = "false"
-    end
-    return cors
-  end
-  return nil
-end
-
 return _M
diff --git a/scripts/lua/management/lib/tenants.lua b/scripts/lua/management/lib/tenants.lua
index a83c773..4fb7a8a 100644
--- a/scripts/lua/management/lib/tenants.lua
+++ b/scripts/lua/management/lib/tenants.lua
@@ -19,7 +19,6 @@
 -- Management interface for tenants for the gateway
 
 local cjson = require "cjson"
-local redis = require "lib/redis"
 local utils = require "lib/utils"
 local request = require "lib/request"
 local apis = require "management/lib/apis"
@@ -38,6 +37,30 @@
   return cjson.decode(tenantObj)
 end
 
+--- Filter tenants based on query parameters
+-- @param tenants list of tenants
+-- @param queryParams query parameters to filter tenants
+local function filterTenants(tenants, queryParams)
+  local namespace = queryParams['filter[where][namespace]']
+  local instance = queryParams['filter[where][instance]']
+  -- missing or invalid query parameters
+  if (namespace == nil and instance == nil) or (instance ~= nil and namespace == nil) then
+    return nil
+  end
+  -- filter tenants
+  local tenantList = {}
+  for k, v in pairs(tenants) do
+    if k%2 == 0 then
+      local tenant = cjson.decode(v)
+      if (namespace ~= nil and instance == nil and tenant.namespace == namespace) or
+          (namespace ~= nil and instance ~= nil and tenant.namespace == namespace and tenant.instance == instance) then
+        tenantList[#tenantList+1] = tenant
+      end
+    end
+  end
+  return tenantList
+end
+
 --- Get all tenants in redis
 -- @param ds redis client
 -- @param queryParams object containing optional query parameters
@@ -58,30 +81,6 @@
   return tenantList
 end
 
---- Filter tenants based on query parameters
--- @param tenants list of tenants
--- @param queryParams query parameters to filter tenants
-function filterTenants(tenants, queryParams)
-  local namespace = queryParams['filter[where][namespace]']
-  local instance = queryParams['filter[where][instance]']
-  -- missing or invalid query parameters
-  if (namespace == nil and instance == nil) or (instance ~= nil and namespace == nil) then
-    return nil
-  end
-  -- filter tenants
-  local tenantList = {}
-  for k, v in pairs(tenants) do
-    if k%2 == 0 then
-      local tenant = cjson.decode(v)
-      if (namespace ~= nil and instance == nil and tenant.namespace == namespace) or
-          (namespace ~= nil and instance ~= nil and tenant.namespace == namespace and tenant.instance == instance) then
-        tenantList[#tenantList+1] = tenant
-      end
-    end
-  end
-  return tenantList
-end
-
 --- Get tenant by its id
 -- @param ds redis client
 -- @param id tenant id
@@ -93,38 +92,10 @@
   return tenant
 end
 
---- Get APIs associated with tenant
--- @param ds redis client
--- @param id tenant id
--- @param queryParams object containing optional query parameters
-function _M.getTenantAPIs(dataStore, id, queryParams)
-  local apis = dataStore:getAllAPIs()
-  local apiList
-  if next(queryParams) ~= nil then
-    apiList = filterTenantAPIs(id, apis, queryParams);
-  end
-  if apiList == nil then
-    apiList = {}
-    for k, v in pairs(apis) do
-      if k%2 == 0 then
-        local decoded = cjson.decode(v)
-        if decoded.tenantId == id then
-          apiList[#apiList+1] = decoded
-        end
-      end
-    end
-  end
-  if (((queryParams['skip'] == nil or queryParams['skip'] == 'undefined') and (queryParams['limit'] == nil or queryParams['limit'] == 'undefined')) or table.getn(apiList) == 0) then
-    return apiList
-  else
-    return applyPagingToAPIs(apiList, queryParams)
-  end
-end
-
 -- Apply paging on apis
 -- @param apis the list of apis
 -- @param queryparams object containing optional query parameters
-function applyPagingToAPIs(apiList, queryParams)
+local function applyPagingToAPIs(apiList, queryParams)
   local skip  = queryParams['skip']  == nil and 1 or queryParams['skip']
   local limit = queryParams['limit'] == nil and table.getn(apiList) or queryParams['limit']
 
@@ -155,7 +126,7 @@
 
 --- Filter apis based on query paramters
 -- @param queryParams query parameters to filter apis
-function filterTenantAPIs(id, apis, queryParams)
+local function filterTenantAPIs(id, apis, queryParams)
   local basePath = queryParams['filter[where][basePath]']
   basePath = basePath == nil and queryParams['basePath'] or basePath
   local name = queryParams['filter[where][name]']
@@ -180,6 +151,34 @@
   return apiList
 end
 
+--- Get APIs associated with tenant
+-- @param ds redis client
+-- @param id tenant id
+-- @param queryParams object containing optional query parameters
+function _M.getTenantAPIs(dataStore, id, queryParams)
+  local apis = dataStore:getAllAPIs()
+  local apiList
+  if next(queryParams) ~= nil then
+    apiList = filterTenantAPIs(id, apis, queryParams);
+  end
+  if apiList == nil then
+    apiList = {}
+    for k, v in pairs(apis) do
+      if k%2 == 0 then
+        local decoded = cjson.decode(v)
+        if decoded.tenantId == id then
+          apiList[#apiList+1] = decoded
+        end
+      end
+    end
+  end
+  if (((queryParams['skip'] == nil or queryParams['skip'] == 'undefined') and (queryParams['limit'] == nil or queryParams['limit'] == 'undefined')) or table.getn(apiList) == 0) then
+    return apiList
+  else
+    return applyPagingToAPIs(apiList, queryParams)
+  end
+end
+
 --- Delete tenant from gateway
 -- @param ds redis client
 -- @param id id of tenant to delete
diff --git a/scripts/lua/management/lib/validation.lua b/scripts/lua/management/lib/validation.lua
index 4c8ed58..8eef460 100644
--- a/scripts/lua/management/lib/validation.lua
+++ b/scripts/lua/management/lib/validation.lua
@@ -23,76 +23,35 @@
 
 local _M = {}
 
-function _M.validate(dataStore, decoded)
-  local fields = {"name", "basePath", "tenantId", "resources"}
-  for _, v in pairs(fields) do
-    local res, err = isValid(dataStore, v, decoded[v])
-    if res == false then
-      return err
+--- Error checking for policies and security
+-- @param policies policies object
+-- @param security security object
+local function checkOptionalPolicies(policies, security)
+  if policies then
+    for _, v in pairs(policies) do
+      local validTypes = {"reqMapping", "rateLimit", "backendRouting"}
+      if (v.type == nil or v.value == nil) then
+        return false, { statusCode = 400, message = "Missing field in policy object. Need \"type\" and \"value\"." }
+      elseif utils.tableContains(validTypes, v.type) == false then
+        return false, { statusCode = 400, message = "Invalid type in policy object. Valid: " .. cjson.encode(validTypes) }
+      end
     end
   end
-  return nil
-end
-
---- Check JSON body fields for errors
--- @param ds edis client instance
--- @param field name of field
--- @param object field object
-function isValid(dataStore, field, object)
-  -- Check that field exists in body
-  if not object then
-    return false, { statusCode = 400, message = utils.concatStrings({"Missing field '", field, "' in request body."}) }
-  end
-  -- Additional check for basePath
-  if field == "basePath" then
-    local basePath = object
-    if string.match(basePath, "'") then
-      return false, { statusCode = 400, message = "basePath contains illegal character \"'\"." }
-    end
-  end
-  -- Additional check for tenantId
-  if field == "tenantId" then
-    local tenant = dataStore:getTenant(object)
-    if tenant == nil then
-      return false, { statusCode = 404, message = utils.concatStrings({"Unknown tenant id ", object }) }
-    end
-  end
-  if field == "resources" then
-    local res, err = checkResources(object)
-    if res ~= nil and res == false then
-      return res, err
-    end
-  end
-  -- All error checks passed
-  return true
-end
-
---- Error checking for resources
--- @param resources resources object
-function checkResources(resources)
-  if next(resources) == nil then
-    return false, { statusCode = 400, message = "Empty resources object." }
-  end
-  for path, resource in pairs(resources) do
-    -- Check resource path for illegal characters
-    if string.match(path, "'") then
-      return false, { statusCode = 400, message = "resource path contains illegal character \"'\"." }
-    end
-    -- Check that resource path begins with slash
-    if path:sub(1,1) ~= '/' then
-      return false, { statusCode = 400, message = "Resource path must begin with '/'." }
-    end
-    -- Check operations object
-    local res, err = checkOperations(resource.operations)
-    if res ~= nil and res == false then
-      return res, err
+  if security then
+    for _, sec in ipairs(security) do
+      local validScopes = {"tenant", "api", "resource"}
+      if (sec.type == nil or sec.scope == nil) then
+        return false, { statusCode = 400, message = "Missing field in security object. Need \"type\" and \"scope\"." }
+      elseif utils.tableContains(validScopes, sec.scope) == false then
+        return false, { statusCode = 400, message = "Invalid scope in security object. Valid: " .. cjson.encode(validScopes) }
+      end
     end
   end
 end
 
 --- Error checking for operations
 -- @param operations operations object
-function checkOperations(operations)
+local function checkOperations(operations)
   if not operations or next(operations) == nil then
     return false, { statusCode = 400, message = "Missing or empty field 'operations' or in resource path object." }
   end
@@ -122,30 +81,71 @@
   end
 end
 
---- Error checking for policies and security
--- @param policies policies object
--- @param security security object
-function checkOptionalPolicies(policies, security)
-  if policies then
-    for _, v in pairs(policies) do
-      local validTypes = {"reqMapping", "rateLimit", "backendRouting"}
-      if (v.type == nil or v.value == nil) then
-        return false, { statusCode = 400, message = "Missing field in policy object. Need \"type\" and \"value\"." }
-      elseif utils.tableContains(validTypes, v.type) == false then
-        return false, { statusCode = 400, message = "Invalid type in policy object. Valid: " .. cjson.encode(validTypes) }
-      end
+--- Error checking for resources
+-- @param resources resources object
+local function checkResources(resources)
+  if next(resources) == nil then
+    return false, { statusCode = 400, message = "Empty resources object." }
+  end
+  for path, resource in pairs(resources) do
+    -- Check resource path for illegal characters
+    if string.match(path, "'") then
+      return false, { statusCode = 400, message = "resource path contains illegal character \"'\"." }
+    end
+    -- Check that resource path begins with slash
+    if path:sub(1,1) ~= '/' then
+      return false, { statusCode = 400, message = "Resource path must begin with '/'." }
+    end
+    -- Check operations object
+    local res, err = checkOperations(resource.operations)
+    if res ~= nil and res == false then
+      return res, err
     end
   end
-  if security then
-    for _, sec in ipairs(security) do
-      local validScopes = {"tenant", "api", "resource"}
-      if (sec.type == nil or sec.scope == nil) then
-        return false, { statusCode = 400, message = "Missing field in security object. Need \"type\" and \"scope\"." }
-      elseif utils.tableContains(validScopes, sec.scope) == false then
-        return false, { statusCode = 400, message = "Invalid scope in security object. Valid: " .. cjson.encode(validScopes) }
-      end
+end
+
+--- Check JSON body fields for errors
+-- @param ds edis client instance
+-- @param field name of field
+-- @param object field object
+local function isValid(dataStore, field, object)
+  -- Check that field exists in body
+  if not object then
+    return false, { statusCode = 400, message = utils.concatStrings({"Missing field '", field, "' in request body."}) }
+  end
+  -- Additional check for basePath
+  if field == "basePath" then
+    local basePath = object
+    if string.match(basePath, "'") then
+      return false, { statusCode = 400, message = "basePath contains illegal character \"'\"." }
     end
   end
+  -- Additional check for tenantId
+  if field == "tenantId" then
+    local tenant = dataStore:getTenant(object)
+    if tenant == nil then
+      return false, { statusCode = 404, message = utils.concatStrings({"Unknown tenant id ", object }) }
+    end
+  end
+  if field == "resources" then
+    local res, err = checkResources(object)
+    if res ~= nil and res == false then
+      return res, err
+    end
+  end
+  -- All error checks passed
+  return true
+end
+
+function _M.validate(dataStore, decoded)
+  local fields = {"name", "basePath", "tenantId", "resources"}
+  for _, v in pairs(fields) do
+    local res, err = isValid(dataStore, v, decoded[v])
+    if res == false then
+      return err
+    end
+  end
+  return nil
 end
 
 return _M
diff --git a/scripts/lua/management/routes/apis.lua b/scripts/lua/management/routes/apis.lua
index 73b0904..45086c1 100644
--- a/scripts/lua/management/routes/apis.lua
+++ b/scripts/lua/management/routes/apis.lua
@@ -33,22 +33,22 @@
 
 local _M = {}
 
---- Request handler for routing API calls appropriately
-function _M.requestHandler(dataStore)
-  local requestMethod = ngx.req.get_method()
-  ngx.header.content_type = "application/json; charset=utf-8"
-  if requestMethod == "GET" then
-    getAPIs(dataStore)
-  elseif requestMethod == 'POST' or requestMethod == 'PUT' then
-    addAPI(dataStore)
-  elseif requestMethod == "DELETE" then
-    deleteAPI(dataStore)
-  else
-    request.err(400, "Invalid verb.")
+--- Check for api id from uri and use existing API if it already exists in redis
+-- @param red Redis client instance
+-- @param id API id to check
+local function checkForExistingAPI(dataStore, id)
+  local existing
+  if id ~= nil and id ~= '' then
+    existing = dataStore:getAPI(id)
+    if existing == nil then
+      dataStore:close()
+      request.err(404, utils.concatStrings({"Unknown API id ", id}))
+    end
   end
+  return existing
 end
 
-function getAPIs(dataStore)
+local function getAPIs(dataStore)
   local queryParams = ngx.req.get_uri_args()
   local id = ngx.var.api_id
   local version = ngx.var.version
@@ -103,7 +103,7 @@
   end
 end
 
-function addAPI(dataStore)
+local function addAPI(dataStore)
   local id = ngx.var.api_id
   local existingAPI = checkForExistingAPI(dataStore, id)
   ngx.req.read_body()
@@ -159,7 +159,7 @@
   end
 end
 
-function deleteAPI(dataStore)
+local function deleteAPI(dataStore)
   local id = ngx.var.api_id
   if id == nil or id == '' then
     dataStore:close()
@@ -177,19 +177,19 @@
   end
 end
 
---- Check for api id from uri and use existing API if it already exists in redis
--- @param red Redis client instance
--- @param id API id to check
-function checkForExistingAPI(dataStore, id)
-  local existing
-  if id ~= nil and id ~= '' then
-    existing = dataStore:getAPI(id)
-    if existing == nil then
-      dataStore:close()
-      request.err(404, utils.concatStrings({"Unknown API id ", id}))
-    end
+--- Request handler for routing API calls appropriately
+function _M.requestHandler(dataStore)
+  local requestMethod = ngx.req.get_method()
+  ngx.header.content_type = "application/json; charset=utf-8"
+  if requestMethod == "GET" then
+    getAPIs(dataStore)
+  elseif requestMethod == 'POST' or requestMethod == 'PUT' then
+    addAPI(dataStore)
+  elseif requestMethod == "DELETE" then
+    deleteAPI(dataStore)
+  else
+    request.err(400, "Invalid verb.")
   end
-  return existing
 end
 
 return _M;
diff --git a/scripts/lua/management/routes/subscriptions.lua b/scripts/lua/management/routes/subscriptions.lua
index 6993f56..6d9406a 100644
--- a/scripts/lua/management/routes/subscriptions.lua
+++ b/scripts/lua/management/routes/subscriptions.lua
@@ -30,119 +30,7 @@
 
 local _M = {}
 
-function _M.requestHandler(dataStore)
-  local version = ngx.var.version
-  if version == "v2" then
-    v2(dataStore)
-  elseif version == "v1" then
-    v1(dataStore)
-  else
-    request.err(404, "404 Not found")
-  end
-end
-
-
--- v2 --
-
-function v2(dataStore)
-  local requestMethod = ngx.req.get_method()
-  if requestMethod == "POST" or requestMethod == "PUT" then
-    v2AddSubscription(dataStore)
-  elseif requestMethod == "GET" then
-    v2GetSubscriptions(dataStore)
-  elseif requestMethod == "DELETE" then
-    v2DeleteSubscription(dataStore)
-  else
-    dataStore:close()
-    request.err(400, "Invalid verb")
-  end
-end
-
-function v2AddSubscription(dataStore)
-  ngx.req.read_body()
-  local args = ngx.req.get_body_data()
-  if not args then
-    dataStore:close()
-    request.err(400, "Missing request body.")
-  end
-  local decoded = cjson.decode(args)
-  local res, err = utils.tableContainsAll(decoded, {"client_id", "artifact_id"})
-  if res == false then
-    request.err(err.statusCode, err.message)
-  end
-  local artifactId = decoded.artifact_id
-  local tenantId = ngx.var.tenant_id
-  local clientId = decoded.client_id
-  local clientSecret = decoded.client_secret
-  subscriptions.addSubscription(dataStore, artifactId, tenantId, clientId, clientSecret, utils.hash)
-  dataStore:close()
-  local result = {
-    message = utils.concatStrings({"Subscription '", clientId, "' created for API '", artifactId, "'"})
-  }
-  ngx.header.content_type = "application/json; charset=utf-8"
-  request.success(200, cjson.encode(result))
-end
-
-function v2GetSubscriptions(dataStore)
-  local tenantId = ngx.var.tenant_id
-  local artifactId = ngx.req.get_uri_args()["artifact_id"]
-  if artifactId == nil or artifactId == "" then
-    request.err(400, "Missing artifact_id")
-  end
-  local subscriptionList = subscriptions.getSubscriptions(dataStore, artifactId, tenantId)
-  redis.close(red)
-  ngx.header.content_type = "application/json; charset=utf-8"
-  request.success(200, cjson.encode(subscriptionList))
-end
-
-function v2DeleteSubscription(dataStore)
-  local clientId = ngx.var.client_id
-  local tenantId = ngx.var.tenant_id
-  local artifactId = ngx.req.get_uri_args()["artifact_id"]
-  if clientId == nil or clientId == "" then
-    request.err(400, "Missing client_id")
-  end
-  if artifactId == nil or artifactId == "" then
-    request.err(400, "Missing artifact_id")
-  end
-  local res = subscriptions.deleteSubscription(dataStore, artifactId, tenantId, clientId)
-  if res == false then
-    request.err(404, "Subscription doesn't exist")
-  end
-  redis.close(red)
-  request.success(204)
-end
-
-
--- v1 --
-
-function v1(dataStore)
-  local requestMethod = ngx.req.get_method()
-  if requestMethod == "POST" or requestMethod == "PUT" then
-    addSubscription(dataStore)
-  elseif requestMethod == "DELETE" then
-    deleteSubscription(dataStore)
-  else
-    dataStore:close()
-    request.err(400, "Invalid verb")
-  end
-end
-
-function addSubscription(dataStore)
-  local redisKey = validateSubscriptionBody(dataStore)
-  dataStore:createSubscription(redisKey)
-  dataStore:close()
-  request.success(200, "Subscription created.")
-end
-
-function deleteSubscription(dataStore)
-  local redisKey = validateSubscriptionBody(dataStore)
-  dataStore:deleteSubscription(redisKey)
-  dataStore:close()
-  request.success(200, "Subscription deleted.")
-end
-
-function validateSubscriptionBody(dataStore)
+local function validateSubscriptionBody(dataStore)
   -- Read in the PUT JSON Body
   ngx.req.read_body()
   local args = ngx.req.get_body_data()
@@ -188,4 +76,114 @@
   return redisKey
 end
 
+local function addSubscription(dataStore)
+  local redisKey = validateSubscriptionBody(dataStore)
+  dataStore:createSubscription(redisKey)
+  dataStore:close()
+  request.success(200, "Subscription created.")
+end
+
+local function deleteSubscription(dataStore)
+  local redisKey = validateSubscriptionBody(dataStore)
+  dataStore:deleteSubscription(redisKey)
+  dataStore:close()
+  request.success(200, "Subscription deleted.")
+end
+
+-- v2 --
+
+local function v2AddSubscription(dataStore)
+  ngx.req.read_body()
+  local args = ngx.req.get_body_data()
+  if not args then
+    dataStore:close()
+    request.err(400, "Missing request body.")
+  end
+  local decoded = cjson.decode(args)
+  local res, err = utils.tableContainsAll(decoded, {"client_id", "artifact_id"})
+  if res == false then
+    request.err(err.statusCode, err.message)
+  end
+  local artifactId = decoded.artifact_id
+  local tenantId = ngx.var.tenant_id
+  local clientId = decoded.client_id
+  local clientSecret = decoded.client_secret
+  subscriptions.addSubscription(dataStore, artifactId, tenantId, clientId, clientSecret, utils.hash)
+  dataStore:close()
+  local result = {
+    message = utils.concatStrings({"Subscription '", clientId, "' created for API '", artifactId, "'"})
+  }
+  ngx.header.content_type = "application/json; charset=utf-8"
+  request.success(200, cjson.encode(result))
+end
+
+local function v2GetSubscriptions(dataStore)
+  local tenantId = ngx.var.tenant_id
+  local artifactId = ngx.req.get_uri_args()["artifact_id"]
+  if artifactId == nil or artifactId == "" then
+    request.err(400, "Missing artifact_id")
+  end
+  local subscriptionList = subscriptions.getSubscriptions(dataStore, artifactId, tenantId)
+  dataStore:close()
+  ngx.header.content_type = "application/json; charset=utf-8"
+  request.success(200, cjson.encode(subscriptionList))
+end
+
+local function v2DeleteSubscription(dataStore)
+  local clientId = ngx.var.client_id
+  local tenantId = ngx.var.tenant_id
+  local artifactId = ngx.req.get_uri_args()["artifact_id"]
+  if clientId == nil or clientId == "" then
+    request.err(400, "Missing client_id")
+  end
+  if artifactId == nil or artifactId == "" then
+    request.err(400, "Missing artifact_id")
+  end
+  local res = subscriptions.deleteSubscription(dataStore, artifactId, tenantId, clientId)
+  if res == false then
+    request.err(404, "Subscription doesn't exist")
+  end
+  dataStore:close()
+  request.success(204)
+end
+
+local function v2(dataStore)
+  local requestMethod = ngx.req.get_method()
+  if requestMethod == "POST" or requestMethod == "PUT" then
+    v2AddSubscription(dataStore)
+  elseif requestMethod == "GET" then
+    v2GetSubscriptions(dataStore)
+  elseif requestMethod == "DELETE" then
+    v2DeleteSubscription(dataStore)
+  else
+    dataStore:close()
+    request.err(400, "Invalid verb")
+  end
+end
+
+-- v1 --
+
+local function v1(dataStore)
+  local requestMethod = ngx.req.get_method()
+  if requestMethod == "POST" or requestMethod == "PUT" then
+    addSubscription(dataStore)
+  elseif requestMethod == "DELETE" then
+    deleteSubscription(dataStore)
+  else
+    dataStore:close()
+    request.err(400, "Invalid verb")
+  end
+end
+
+function _M.requestHandler(dataStore)
+  local version = ngx.var.version
+  if version == "v2" then
+    v2(dataStore)
+  elseif version == "v1" then
+    v1(dataStore)
+  else
+    request.err(404, "404 Not found")
+  end
+end
+
 return _M
diff --git a/scripts/lua/management/routes/tenants.lua b/scripts/lua/management/routes/tenants.lua
index 9e26020..4b92bdd 100644
--- a/scripts/lua/management/routes/tenants.lua
+++ b/scripts/lua/management/routes/tenants.lua
@@ -29,22 +29,23 @@
 
 local _M = {};
 
---- Request handler for routing tenant calls appropriately
-function _M.requestHandler(dataStore)
-  local requestMethod = ngx.req.get_method()
-  ngx.header.content_type = "application/json; charset=utf-8"
-  if requestMethod == "GET" then
-    getTenants(dataStore)
-  elseif requestMethod == "PUT" or requestMethod == "POST" then
-    addTenant(dataStore)
-  elseif requestMethod == "DELETE" then
-    deleteTenant(dataStore)
-  else
-    request.err(400, "Invalid verb.")
+--- Check for tenant id from uri and use existing tenant if it already exists in redis
+-- @param red Redis client instance
+local function checkForExistingTenant(dataStore)
+  local id = ngx.var.tenant_id
+  local existing
+  -- Get object from redis
+  if id ~= nil and id ~= '' then
+    existing = dataStore:getTenant(id)
+    if existing == nil then
+      dataStore:close()
+      request.err(404, utils.concatStrings({"Unknown Tenant id ", id}))
+    end
   end
+  return existing
 end
 
-function addTenant(dataStore)
+local function addTenant(dataStore)
   -- Open connection to redis or use one from connection pool
   -- Check for tenant id and use existingTenant if it already exists in redis
   local existingTenant = checkForExistingTenant(dataStore)
@@ -76,25 +77,9 @@
   request.success(200, tenantObj)
 end
 
---- Check for tenant id from uri and use existing tenant if it already exists in redis
--- @param red Redis client instance
-function checkForExistingTenant(dataStore)
-  local id = ngx.var.tenant_id
-  local existing
-  -- Get object from redis
-  if id ~= nil and id ~= '' then
-    existing = dataStore:getTenant(id)
-    if existing == nil then
-      dataStore:close()
-      request.err(404, utils.concatStrings({"Unknown Tenant id ", id}))
-    end
-  end
-  return existing
-end
-
 --- Get one or all tenants from the gateway
 -- GET /v1/tenants
-function getTenants(dataStore)
+local function getTenants(dataStore)
   local queryParams = ngx.req.get_uri_args()
   local id = ngx.var.tenant_id
   if id == '' then
@@ -125,7 +110,7 @@
 
 --- Delete tenant from gateway
 -- DELETE /v1/tenants/<id>
-function deleteTenant(dataStore)
+local function deleteTenant(dataStore)
   local id = ngx.var.tenant_id
   if id == nil or id == '' then
     request.err(400, "No id specified.")
@@ -139,4 +124,19 @@
   request.success(200, cjson.encode({}))
 end
 
+--- Request handler for routing tenant calls appropriately
+function _M.requestHandler(dataStore)
+  local requestMethod = ngx.req.get_method()
+  ngx.header.content_type = "application/json; charset=utf-8"
+  if requestMethod == "GET" then
+    getTenants(dataStore)
+  elseif requestMethod == "PUT" or requestMethod == "POST" then
+    addTenant(dataStore)
+  elseif requestMethod == "DELETE" then
+    deleteTenant(dataStore)
+  else
+    request.err(400, "Invalid verb.")
+  end
+end
+
 return _M
diff --git a/scripts/lua/oauth/facebook.lua b/scripts/lua/oauth/facebook.lua
index a27b295..08b1f5b 100644
--- a/scripts/lua/oauth/facebook.lua
+++ b/scripts/lua/oauth/facebook.lua
@@ -20,25 +20,8 @@
 local utils = require "lib/utils"
 
 local _M = {}
-function _M.process(dataStore, token)
 
-  local headerName = utils.concatStrings({'http_', 'x-facebook-app-token'}):gsub("-", "_")
-
-  local facebookAppToken = ngx.var[headerName]
-  if facebookAppToken == nil then
-    request.err(401, 'Facebook requires you provide an app token to validate user tokens. Provide a X-Facebook-App-Token header')
-    return nil
-  end
-
-  local result = dataStore:getOAuthToken('facebook', utils.concatStrings({token, facebookAppToken}))
-  if result ~= ngx.null then
-    return cjson.decode(result)
-  end
-
-   return exchangeOAuthToken(dataStore, token, facebookAppToken)
-end
-
-function exchangeOAuthToken(dataStore, token, facebookAppToken)
+local function exchangeOAuthToken(dataStore, token, facebookAppToken)
   local http = require 'resty.http'
   local request = require "lib/request"
   local httpc = http.new()
@@ -73,4 +56,22 @@
   return json_resp
 end
 
+function _M.process(dataStore, token)
+
+  local headerName = utils.concatStrings({'http_', 'x-facebook-app-token'}):gsub("-", "_")
+
+  local facebookAppToken = ngx.var[headerName]
+  if facebookAppToken == nil then
+    request.err(401, 'Facebook requires you provide an app token to validate user tokens. Provide a X-Facebook-App-Token header')
+    return nil
+  end
+
+  local result = dataStore:getOAuthToken('facebook', utils.concatStrings({token, facebookAppToken}))
+  if result ~= ngx.null then
+    return cjson.decode(result)
+  end
+
+   return exchangeOAuthToken(dataStore, token, facebookAppToken)
+end
+
 return _M
diff --git a/scripts/lua/oauth/google.lua b/scripts/lua/oauth/google.lua
index bd8e11b..efdbf28 100644
--- a/scripts/lua/oauth/google.lua
+++ b/scripts/lua/oauth/google.lua
@@ -29,7 +29,7 @@
 
   local httpc = http.new()
   if result ~= ngx.null then
-    json_resp = cjson.decode(result)
+    local json_resp = cjson.decode(result)
     ngx.header['X-OIDC-Sub'] = json_resp['sub']
     ngx.header['X-OIDC-Email'] = json_resp['email']
     ngx.header['X-OIDC-Scope'] = json_resp['scope']
diff --git a/scripts/lua/policies/backendRouting.lua b/scripts/lua/policies/backendRouting.lua
index 646de94..e426e53 100644
--- a/scripts/lua/policies/backendRouting.lua
+++ b/scripts/lua/policies/backendRouting.lua
@@ -26,6 +26,14 @@
 
 local _M = {}
 
+local function setUpstream(u)
+  local upstream = utils.concatStrings({u.scheme, '://', u.host})
+  if u.port ~= nil and u.port ~= '' then
+    upstream = utils.concatStrings({upstream, ':', u.port})
+  end
+  ngx.var.upstream = upstream
+end
+
 --- Set upstream based on the backendUrl
 function _M.setRoute(backendUrl, gatewayPath)
   _M.setRouteWithOverride(backendUrl, gatewayPath, backendOverride)
@@ -109,12 +117,4 @@
   end
 end
 
-function setUpstream(u)
-  local upstream = utils.concatStrings({u.scheme, '://', u.host})
-  if u.port ~= nil and u.port ~= '' then
-    upstream = utils.concatStrings({upstream, ':', u.port})
-  end
-  ngx.var.upstream = upstream
-end
-
 return _M
diff --git a/scripts/lua/policies/mapping.lua b/scripts/lua/policies/mapping.lua
index 63ba789..3ed6385 100644
--- a/scripts/lua/policies/mapping.lua
+++ b/scripts/lua/policies/mapping.lua
@@ -30,33 +30,58 @@
 local headers
 local path
 
---- Implementation for the mapping policy.
--- @param map The mapping object that contains details about request tranformations
-function processMap(map)
-  getRequestParams()
-  for k, v in pairs(map) do
-    if v.action == "insert" then
-      insertParam(v)
-    elseif v.action == "remove" then
-      removeParam(v)
-    elseif v.action == "transform" then
-      transformParam(v)
-    elseif v.action == "default" then
-      checkDefault(v)
-    else
-      logger.err(utils.concatStrings({'Map action not recognized. Skipping... ', v.action}))
-    end
+local function insertHeader(k, v)
+  ngx.req.set_header(k, v)
+  headers[k] = v
+end
+
+local function insertQuery(k, v)
+  query[k] = v
+end
+
+local function insertBody(k, v)
+  body[k] = v
+end
+
+local function insertPath(k, v)
+  v = ngx.unescape_uri(v)
+  path = path:gsub(utils.concatStrings({"%{", k ,"%}"}), v)
+  ngx.req.set_uri(path)
+end
+
+local function removeHeader(k)
+  ngx.req.clear_header(k)
+end
+
+local function removeQuery(k)
+  query[k] = nil
+end
+
+local function removeBody(k)
+  body[k] = nil
+end
+
+local function decodeQuery(param)
+  local decoded = param:gsub('+', ' '):gsub('%%(%x%x)',
+    function(hex) return string.char(tonumber(hex, 16)) end)
+  return decoded
+end
+
+local function parseUrl(url)
+  local map = {}
+  for k,v in url:gmatch('([^&=?]+)=([^&=?]+)') do
+    map[ k ] = decodeQuery(v)
   end
-  finalize()
+  return map
 end
 
 --- Get request body, params, and headers from incoming requests
-function getRequestParams()
+local function getRequestParams()
   ngx.req.read_body()
   body = ngx.req.get_body_data()
   if body ~= nil then
     -- decode body if json
-    decoded, err = cjson.decode(body)
+    local decoded, err = cjson.decode(body)
     if err == nil then
       body = decoded
     end
@@ -74,7 +99,7 @@
 
 --- Insert parameter value to header, body, or query params into request
 -- @param m Parameter value to add to request
-function insertParam(m)
+local function insertParam(m)
   local v
   local k = m.to.name
   if m.from.value ~= nil then
@@ -102,7 +127,7 @@
 
 --- Remove parameter value to header, body, or query params from request
 -- @param m Parameter value to remove from request
-function removeParam(m)
+local function removeParam(m)
   if m.from.location == "header" then
     removeHeader(m.from.name)
   elseif m.from.location == "query" then
@@ -112,35 +137,12 @@
   end
 end
 
---- Move parameter value from one location to another in the request
--- @param m Parameter value to move within request
-function transformParam(m)
-  if m.from.name == '*' then
-    transformAllParams(m.from.location, m.to.location)
-  else
-    insertParam(m)
-    removeParam(m)
-  end
-end
-
---- Checks if the header has been set, and sets the header to a value if found to be null.
--- @param m Header name and value to be set, if header is null.
-function checkDefault(m)
-  if m.to.location == "header" and headers[m.to.name] == nil then
-    insertHeader(m.to.name, m.from.value)
-  elseif m.to.location == "query" and query[m.to.name] == nil then
-    insertQuery(m.to.name, m.from.value)
-  elseif m.to.location == "body" and body[m.to.name] == nil then
-    insertBody(m.to.name, m.from.value)
-  end
-end
-
 --- Function to handle wildcarding in the transform process.
 -- If the value in the from object is '*', this function will pull all values from the incoming request
 -- and move them to the location provided in the to object
 -- @param s The source object from which we pull all parameters
 -- @param d The destination object that we will move all found parameters to.
-function transformAllParams(s, d)
+local function transformAllParams(s, d)
   if s == 'query' then
     for k, v in pairs(query) do
       local t = {}
@@ -192,7 +194,30 @@
   end
 end
 
-function finalize()
+--- Move parameter value from one location to another in the request
+-- @param m Parameter value to move within request
+local function transformParam(m)
+  if m.from.name == '*' then
+    transformAllParams(m.from.location, m.to.location)
+  else
+    insertParam(m)
+    removeParam(m)
+  end
+end
+
+--- Checks if the header has been set, and sets the header to a value if found to be null.
+-- @param m Header name and value to be set, if header is null.
+local function checkDefault(m)
+  if m.to.location == "header" and headers[m.to.name] == nil then
+    insertHeader(m.to.name, m.from.value)
+  elseif m.to.location == "query" and query[m.to.name] == nil then
+    insertQuery(m.to.name, m.from.value)
+  elseif m.to.location == "body" and body[m.to.name] == nil then
+    insertBody(m.to.name, m.from.value)
+  end
+end
+
+local function finalize()
   if type(body) == 'table' and next(body) ~= nil then
     local bodyJson = cjson.encode(body)
     ngx.req.set_body_data(bodyJson)
@@ -200,49 +225,24 @@
   ngx.req.set_uri_args(query)
 end
 
-function insertHeader(k, v)
-  ngx.req.set_header(k, v)
-  headers[k] = v
-end
-
-function insertQuery(k, v)
-  query[k] = v
-end
-
-function insertBody(k, v)
-  body[k] = v
-end
-
-function insertPath(k, v)
-  v = ngx.unescape_uri(v)
-  path = path:gsub(utils.concatStrings({"%{", k ,"%}"}), v)
-  ngx.req.set_uri(path)
-end
-
-function removeHeader(k)
-  ngx.req.clear_header(k)
-end
-
-function removeQuery(k)
-  query[k] = nil
-end
-
-function removeBody(k)
-  body[k] = nil
-end
-
-function parseUrl(url)
-  local map = {}
-  for k,v in url:gmatch('([^&=?]+)=([^&=?]+)') do
-    map[ k ] = decodeQuery(v)
+--- Implementation for the mapping policy.
+-- @param map The mapping object that contains details about request tranformations
+local function processMap(map)
+  getRequestParams()
+  for k, v in pairs(map) do
+    if v.action == "insert" then
+      insertParam(v)
+    elseif v.action == "remove" then
+      removeParam(v)
+    elseif v.action == "transform" then
+      transformParam(v)
+    elseif v.action == "default" then
+      checkDefault(v)
+    else
+      logger.err(utils.concatStrings({'Map action not recognized. Skipping... ', v.action}))
+    end
   end
-  return map
-end
-
-function decodeQuery(param)
-  local decoded = param:gsub('+', ' '):gsub('%%(%x%x)',
-    function(hex) return string.char(tonumber(hex, 16)) end)
-  return decoded
+  finalize()
 end
 
 _M.processMap = processMap
diff --git a/scripts/lua/policies/rateLimit.lua b/scripts/lua/policies/rateLimit.lua
index 5f2ca98..468852f 100644
--- a/scripts/lua/policies/rateLimit.lua
+++ b/scripts/lua/policies/rateLimit.lua
@@ -26,7 +26,7 @@
 -- @param dataStore the datastore object
 -- @param obj rateLimit object containing interval, rate, scope, subscription fields
 -- @param apiKey optional api key to use if subscription is set to true
-function limit(dataStore, obj, apiKey)
+local function limit(dataStore, obj, apiKey)
   local rate = obj.interval / obj.rate
   local tenantId = ngx.var.tenant
   local gatewayPath = ngx.var.gatewayPath
diff --git a/scripts/lua/policies/security.lua b/scripts/lua/policies/security.lua
index 2bcdeb0..4afe76c 100644
--- a/scripts/lua/policies/security.lua
+++ b/scripts/lua/policies/security.lua
@@ -24,7 +24,7 @@
 --- Allow or block a request by calling a loaded security policy
 -- @param dataStore the datastore object
 -- @param securityObj an object out of the security array in a given tenant / api / resource
-function process(dataStore, securityObj)
+local function process(dataStore, securityObj)
   local ok, result = pcall(require, utils.concatStrings({'policies/security/', securityObj.type}))
   if not ok then
     ngx.log(ngx.ERR, 'An unexpected error ocurred while processing the security policy: ' .. securityObj.type)
diff --git a/scripts/lua/policies/security/apiKey.lua b/scripts/lua/policies/security/apiKey.lua
index 409d6d9..7abee5b 100644
--- a/scripts/lua/policies/security/apiKey.lua
+++ b/scripts/lua/policies/security/apiKey.lua
@@ -18,13 +18,9 @@
 --- @module apiKey
 -- Check a subscription with an API Key
 
-local dataStore = require "lib/dataStore"
 local utils = require "lib/utils"
 local request = require "lib/request"
-
-local REDIS_HOST = os.getenv("REDIS_HOST")
-local REDIS_PORT = os.getenv("REDIS_PORT")
-local REDIS_PASS = os.getenv("REDIS_PASS")
+local logger = require "lib/logger"
 
 local _M = {}
 
@@ -36,7 +32,7 @@
 -- @param scope scope of the subscription
 -- @param apiKey the subscription api key
 -- @param return boolean value indicating if the subscription exists in redis
-function validate(dataStore, tenant, gatewayPath, apiId, scope, apiKey)
+local function validate(dataStore, tenant, gatewayPath, apiId, scope, apiKey)
   -- Open connection to redis or use one from connection pool
   local k
   if scope == 'tenant' then
@@ -54,27 +50,24 @@
   end
 end
 
-function process(dataStore, securityObj)
-  return processWithHashFunction(dataStore, securityObj, sha256)
-end
-
 --- Process the security object
 -- @param dataStore the datastore object
 -- @param securityObj security object from nginx conf file
 -- @param hashFunction a function that will be called to hash the string
 -- @return apiKey api key for the subscription
-function processWithHashFunction(dataStore, securityObj, hashFunction)
+local function processWithHashFunction(dataStore, securityObj, hashFunction)
   local tenant = ngx.var.tenant
   local gatewayPath = ngx.var.gatewayPath
   local apiId = dataStore:resourceToApi(utils.concatStrings({'resources:', tenant, ':', gatewayPath}))
   local scope = securityObj.scope
-  local name = (securityObj.name == nil) and ((securityObj.header == nil) and 'x-api-key' or securityObj.header) or securityObj.name
   local queryString = ngx.req.get_uri_args()
   local location = (securityObj.location == nil) and 'header' or securityObj.location
 -- backwards compatible with "header" argument for name value. "name" argument takes precedent if both provided
   local name = (securityObj.name == nil and securityObj.header == nil) and 'x-api-key' or (securityObj.name or securityObj.header)
   local apiKey = nil
 
+  ngx.log(ngx.DEBUG, "Processing API_KEY security policy")
+
   if location == "header" then
     apiKey = ngx.var[utils.concatStrings({'http_', name}):gsub("-", "_")]
   end
@@ -97,17 +90,10 @@
   return apiKey
 end
 
---- Calculate the sha256 hash of a string
--- @param str the string you want to hash
--- @return a hashed version of the string
-function sha256(str)
-  local resty_sha256 = require "resty.sha256"
-  local resty_str = require "resty.string"
-  local sha = resty_sha256:new()
-  sha:update(str)
-  local digest = sha:final()
-  return resty_str.to_hex(digest)
+local function process(dataStore, securityObj)
+  return processWithHashFunction(dataStore, securityObj, utils.sha256)
 end
+
 _M.processWithHashFunction = processWithHashFunction
 _M.process = process
 
diff --git a/scripts/lua/policies/security/clientSecret.lua b/scripts/lua/policies/security/clientSecret.lua
index 79f2b82..132c58a 100644
--- a/scripts/lua/policies/security/clientSecret.lua
+++ b/scripts/lua/policies/security/clientSecret.lua
@@ -19,76 +19,9 @@
 -- Check a subscription with a client id and a hashed secret
 local _M = {}
 
-local dataStore = require "lib/dataStore"
 local utils = require "lib/utils"
 local request = require "lib/request"
-
-local REDIS_HOST = os.getenv("REDIS_HOST")
-local REDIS_PORT = os.getenv("REDIS_PORT")
-local REDIS_PASS = os.getenv("REDIS_PASS")
-
---- Process function main entry point for the security block.
---  Takes 2 headers and decides if the request should be allowed based on a hashed secret key
---@param dataStore the datastore object
---@param securityObj the security object loaded from nginx.conf
---@return a string representation of what this looks like in redis :clientsecret:clientid:hashed secret
-function process(dataStore, securityObj)
-  local result = processWithHashFunction(dataStore, securityObj, utils.hash)
-end
-
---- In order to properly test this functionallity, I use this function to do all of the business logic with injected dependencies
--- Takes 2 headers and decides if the request should be allowed based on a hashed secret key
--- @param dataStore the datastore object
--- @param securityObj the security configuration for the tenant/resource/api we are verifying
--- @param hashFunction the function used to perform the hash of the api secret
-function processWithHashFunction(dataStore, securityObj, hashFunction)
-  -- pull the configuration from nginx
-  local tenant = ngx.var.tenant
-  local gatewayPath = ngx.var.gatewayPath
-  local apiId = ngx.var.apiId
-  local scope = securityObj.scope
-  local queryString = ngx.req.get_uri_args()
-  local location = (securityObj.location == nil) and 'header' or securityObj.location
-  local clientId = nil
-  local clientSecret = nil
-
-  -- allow support for custom names in query or header
-  local clientIdName = (securityObj.idFieldName == nil) and 'X-Client-ID' or securityObj.idFieldName
-  if location == "header" then
-    clientId = ngx.var[utils.concatStrings({'http_', clientIdName}):gsub("-", "_")]
-  end
-  if location == "query" then
-    clientId = queryString[clientIdName]
-  end
--- if they didn't supply whatever name this is configured to require, error out
-  if clientId == nil or clientId == '' then
-    request.err(401, clientIdName .. " required")
-    return false
-  end
-
--- allow support for custom names in query or header
-  local clientSecretName = (securityObj.secretFieldName == nil) and 'X-Client-Secret' or securityObj.secretFieldName
-  _G.clientSecretName = clientSecretName:lower()
-  if location == "header" then
-    clientSecret = ngx.var[utils.concatStrings({'http_', clientSecretName}):gsub("-","_")]
-  end
-  if location == "query" then
-    clientSecret = queryString[clientSecretName]
-  end
--- if they didn't supply whatever name this is configured to require, error out
-  if clientSecret == nil or clientSecret == '' then
-    request.err(401, clientSecretName .. " required")
-    return false
-  end
-
--- hash the secret
-  local result = validate(dataStore, tenant, gatewayPath, apiId, scope, clientId, hashFunction(clientSecret))
-  if result == nil then
-    request.err(401, "Secret mismatch or not subscribed to this api.")
-  end
-  ngx.var.apiKey = clientId
-  return result
-end
+local logger = require "lib/logger"
 
 --- Validate that the subscription exists in the dataStore
 -- @param dataStore the datastore object
@@ -98,24 +31,90 @@
 -- @param scope which values should we be using to find the location of the secret
 -- @param clientId the subscribed client id
 -- @param clientSecret the hashed client secret
-function validate(dataStore, tenant, gatewayPath, apiId, scope, clientId, clientSecret)
--- Open connection to redis or use one from connection pool
+local function validate(dataStore, tenant, gatewayPath, apiId, scope, clientId, clientSecret)
+  -- Open connection to redis or use one from connection pool
   local k
-  if scope == 'tenant' then
-    k = utils.concatStrings({'subscriptions:tenant:', tenant})
-  elseif scope == 'resource' then
-    k = utils.concatStrings({'subscriptions:tenant:', tenant, ':resource:', gatewayPath})
-  elseif scope == 'api' then
-    k = utils.concatStrings({'subscriptions:tenant:', tenant, ':api:', apiId})
+  if scope == "tenant" then
+    k = utils.concatStrings({"subscriptions:tenant:", tenant})
+  elseif scope == "resource" then
+    k = utils.concatStrings({"subscriptions:tenant:", tenant, ":resource:", gatewayPath})
+  elseif scope == "api" then
+    k = utils.concatStrings({"subscriptions:tenant:", tenant, ":api:", apiId})
   end
   -- using the same key location in redis, just using :clientsecret: instead of :key:
-  k = utils.concatStrings({k, ':clientsecret:', clientId, ':', clientSecret})
+  k = utils.concatStrings({k, ":clientsecret:", clientId, ":", clientSecret})
   if dataStore:exists(k) == 1 then
     return k
   else
     return nil
   end
 end
+
+--- In order to properly test this functionallity, I use this function to do all of the business logic with injected dependencies
+-- Takes 2 headers and decides if the request should be allowed based on a hashed secret key
+-- @param dataStore the datastore object
+-- @param securityObj the security configuration for the tenant/resource/api we are verifying
+-- @param hashFunction the function used to perform the hash of the api secret
+local function processWithHashFunction(dataStore, securityObj, hashFunction)
+  -- pull the configuration from nginx
+  local tenant = ngx.var.tenant
+  local gatewayPath = ngx.var.gatewayPath
+  local apiId = ngx.var.apiId
+  local scope = securityObj.scope
+  local queryString = ngx.req.get_uri_args()
+  local location = (securityObj.location == nil) and "header" or securityObj.location
+  local clientId = nil
+  local clientSecret = nil
+
+  ngx.log(ngx.DEBUG, "Processing CLIENT_SECRET security policy")
+
+  -- allow support for custom names in query or header
+  local clientIdName = (securityObj.idFieldName == nil) and "X-Client-ID" or securityObj.idFieldName
+  if location == "header" then
+    clientId = ngx.var[utils.concatStrings({"http_", clientIdName}):gsub("-", "_")]
+  end
+  if location == "query" then
+    clientId = queryString[clientIdName]
+  end
+  -- if they didn't supply whatever name this is configured to require, error out
+  if clientId == nil or clientId == "" then
+    request.err(401, clientIdName .. " required")
+    return false
+  end
+
+  -- allow support for custom names in query or header
+  local clientSecretName = (securityObj.secretFieldName == nil) and "X-Client-Secret" or securityObj.secretFieldName
+  ngx.ctx.clientSecretName = clientSecretName:lower()
+  if location == "header" then
+    clientSecret = ngx.var[utils.concatStrings({"http_", clientSecretName}):gsub("-", "_")]
+  end
+  if location == "query" then
+    clientSecret = queryString[clientSecretName]
+  end
+  -- if they didn't supply whatever name this is configured to require, error out
+  if clientSecret == nil or clientSecret == "" then
+    request.err(401, clientSecretName .. " required")
+    return false
+  end
+
+  -- hash the secret
+  local result = validate(dataStore, tenant, gatewayPath, apiId, scope, clientId, hashFunction(clientSecret))
+  if result == nil then
+    request.err(401, "Secret mismatch or not subscribed to this api.")
+  end
+  ngx.var.apiKey = clientId
+  return result
+end
+
+--- Process function main entry point for the security block.
+--  Takes 2 headers and decides if the request should be allowed based on a hashed secret key
+--@param dataStore the datastore object
+--@param securityObj the security object loaded from nginx.conf
+--@return a string representation of what this looks like in redis :clientsecret:clientid:hashed secret
+local function process(dataStore, securityObj)
+  return processWithHashFunction(dataStore, securityObj, utils.hash)
+end
+
 _M.processWithHashFunction = processWithHashFunction
 _M.process = process
 return _M
diff --git a/scripts/lua/policies/security/oauth2.lua b/scripts/lua/policies/security/oauth2.lua
index 6b58bf9..c1492e5 100644
--- a/scripts/lua/policies/security/oauth2.lua
+++ b/scripts/lua/policies/security/oauth2.lua
@@ -20,20 +20,37 @@
 
 local utils = require "lib/utils"
 local request = require "lib/request"
-local dataStore = require "lib/dataStore"
-local cjson = require "cjson"
-
-local REDIS_HOST = os.getenv("REDIS_HOST")
-local REDIS_PORT = os.getenv("REDIS_PORT")
-local REDIS_PASS = os.getenv("REDIS_PASS")
 
 local _M = {}
 
+--- Exchange tokens with an oauth provider. Loads a provider based on configuration in the nginx.conf
+-- @param dataStore the datastore object
+-- @param token the accessToken passed in the authorization header of the routing request
+-- @param provider the name of the provider we will load from a file. Currently supported google/github/facebook
+-- @return the json object recieved from exchanging tokens with the provider
+local function exchange(dataStore, token, provider, securityObj)
+  -- exchange tokens with the provider
+  local loaded, impl = pcall(require, utils.concatStrings({'oauth/', provider}))
+  if not loaded then
+    request.err(500, 'Error loading OAuth provider authentication module')
+    print("error loading provider:", impl)
+    return nil
+  end
+
+  local result = impl.process(dataStore, token, securityObj)
+  if result == nil then
+    request.err('401', 'OAuth token didn\'t work or provider doesn\'t support OpenID connect')
+  end
+  -- cache the token
+  return result
+end
 
 -- Process the security object
 -- @param securityObj security object from nginx conf file
 -- @return oauthId oauth identification
-function process(dataStore, securityObj)
+local function process(dataStore, securityObj)
+  ngx.log(ngx.DEBUG, "Processing OAUTH2 security policy")
+
   local accessToken = ngx.var['http_Authorization']
   if accessToken == nil then
     request.err(401, "No Authorization header provided")
@@ -56,27 +73,5 @@
   return token
 end
 
---- Exchange tokens with an oauth provider. Loads a provider based on configuration in the nginx.conf
--- @param dataStore the datastore object
--- @param token the accessToken passed in the authorization header of the routing request
--- @param provider the name of the provider we will load from a file. Currently supported google/github/facebook
--- @return the json object recieved from exchanging tokens with the provider
-function exchange(dataStore, token, provider, securityObj)
-    -- exchange tokens with the provider
-    local loaded, impl = pcall(require, utils.concatStrings({'oauth/', provider}))
-    if not loaded then
-      request.err(500, 'Error loading OAuth provider authentication module')
-      print("error loading provider:", impl)
-      return nil
-    end
-
-    local result = impl.process(dataStore, token, securityObj)
-    if result == nil then
-      request.err('401', 'OAuth token didn\'t work or provider doesn\'t support OpenID connect')
-    end
-    -- cache the token
-    return result
-end
-
 _M.process = process
 return _M
diff --git a/scripts/lua/routing.lua b/scripts/lua/routing.lua
index f4d1845..080fca6 100644
--- a/scripts/lua/routing.lua
+++ b/scripts/lua/routing.lua
@@ -44,6 +44,46 @@
 
 local _M = {}
 
+local function setRequestLogs()
+  local requestHeaders = ngx.req.get_headers()
+  for k, v in pairs(requestHeaders) do
+    if k == 'authorization' or k == ngx.ctx.clientSecretName then
+      requestHeaders[k] = '[redacted]'
+    end
+  end
+  ngx.var.requestHeaders = cjson.encode(requestHeaders)
+  ngx.req.read_body()
+  ngx.var.requestBody = ngx.req.get_body_data()
+end
+
+--- Function to read the list of policies and send implementation to the correct backend
+-- @param red redis client instance
+-- @param obj List of policies containing a type and value field. This function reads the type field and routes it appropriately.
+-- @param apiKey optional subscription api key
+local function parsePolicies(dataStore, obj, apiKey)
+  for k, v in pairs (obj) do
+    if v.type == 'reqMapping' then
+      mapping.processMap(v.value)
+    elseif v.type == 'rateLimit' then
+      rateLimit.limit(dataStore, v.value, apiKey)
+    elseif v.type == 'backendRouting' then
+      backendRouting.setDynamicRoute(v.value)
+    end
+  end
+end
+
+--- Given a verb, transforms the backend request to use that method
+-- @param v Verb to set on the backend request
+local function setVerb(v)
+  local allowedVerbs = {'GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'}
+  local verb = string.upper(v)
+  if utils.tableContains(allowedVerbs, verb) then
+    ngx.req.set_method(ngx[utils.concatStrings({"HTTP_", verb})])
+  else
+    ngx.req.set_method(ngx.HTTP_GET)
+  end
+end
+
 --- Main function that handles parsing of invocation details and carries out implementation
 function _M.processCall(dataStore)
   -- Get request headers
@@ -154,7 +194,7 @@
   end
 
   local resourceKeys = dataStore:getAllResources(tenant)
-  local result = _M.slowLookup(resourceKeys, tenant, path, redisKey, cfRedisKey)
+  result = _M.slowLookup(resourceKeys, tenant, path, redisKey, cfRedisKey)
 
   if OPTIMIZE > 0 and result ~= nil then
     dataStore:optimizeLookup(tenant, result, path)
@@ -177,6 +217,7 @@
       return key
     end
   end
+  local cfUrl = ngx.req.get_headers()["x-cf-forwarded-url"]
   if cfUrl ~= nil and cfUrl ~= "" then
     return nil
   end
@@ -242,46 +283,6 @@
   return false
 end
 
---- Function to read the list of policies and send implementation to the correct backend
--- @param red redis client instance
--- @param obj List of policies containing a type and value field. This function reads the type field and routes it appropriately.
--- @param apiKey optional subscription api key
-function parsePolicies(dataStore, obj, apiKey)
-  for k, v in pairs (obj) do
-    if v.type == 'reqMapping' then
-      mapping.processMap(v.value)
-    elseif v.type == 'rateLimit' then
-      rateLimit.limit(dataStore, v.value, apiKey)
-    elseif v.type == 'backendRouting' then
-      backendRouting.setDynamicRoute(v.value)
-    end
-  end
-end
-
---- Given a verb, transforms the backend request to use that method
--- @param v Verb to set on the backend request
-function setVerb(v)
-  local allowedVerbs = {'GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'}
-  local verb = string.upper(v)
-  if utils.tableContains(allowedVerbs, verb) then
-    ngx.req.set_method(ngx[utils.concatStrings({"HTTP_", verb})])
-  else
-    ngx.req.set_method(ngx.HTTP_GET)
-  end
-end
-
-function setRequestLogs()
-  local requestHeaders = ngx.req.get_headers()
-  for k, v in pairs(requestHeaders) do
-    if k == 'authorization' or k == _G.clientSecretName then
-      requestHeaders[k] = '[redacted]'
-    end
-  end
-  ngx.var.requestHeaders = cjson.encode(requestHeaders)
-  ngx.req.read_body()
-  ngx.var.requestBody = ngx.req.get_body_data()
-end
-
 function _M.setResponseLogs()
   ngx.var.responseHeaders = cjson.encode(ngx.resp.get_headers())
   local resp_body = ngx.arg[1]
diff --git a/tools/lua-releng b/tools/lua-releng
new file mode 100755
index 0000000..7560316
--- /dev/null
+++ b/tools/lua-releng
@@ -0,0 +1,104 @@
+#!/usr/bin/env perl
+
+use strict;
+use warnings;
+
+use Getopt::Std;
+
+my (@luas, @tests);
+
+my %opts;
+getopts('Lse', \%opts) or die "Usage: lua-releng [-L] [-s] [-e] [files]\n";
+
+my $silent = $opts{s};
+my $stop_on_error = $opts{e};
+my $no_long_line_check = $opts{L};
+
+my $check_lua_ver = "luac -v | awk '{print\$2}'| grep 5.1";
+my $output = `$check_lua_ver`;
+if ($output eq '') {
+    die "ERROR: lua-releng ONLY supports Lua 5.1!\n";
+}
+
+if ($#ARGV != -1) {
+    @luas = @ARGV;
+
+} else {
+    @luas = map glob, qw{ *.lua lib/*.lua lib/*/*.lua lib/*/*/*.lua lib/*/*/*/*.lua lib/*/*/*/*/*.lua };
+    if (-d 't') {
+        @tests = map glob, qw{ t/*.t t/*/*.t t/*/*/*.t };
+    }
+}
+
+for my $f (sort @luas) {
+    process_file($f);
+}
+
+for my $t (@tests) {
+    blank(qq{grep -H -n --color -E '\\--- ?(ONLY|LAST)' $t});
+}
+# p: prints a string to STDOUT appending \n
+# w: prints a string to STDERR appending \n
+# Both respect the $silent value
+sub p { print "$_[0]\n" if (!$silent) }
+sub w { warn  "$_[0]\n" if (!$silent) }
+
+# blank: runs a command and looks at the output. If the output is not
+# blank it is printed (and the program dies if stop_on_error is 1)
+sub blank {
+    my ($command) = @_;
+    if ($stop_on_error) {
+        my $output = `$command`;
+        if ($output ne '') {
+            die $output;
+        }
+    } else {
+        system($command);
+    }
+}
+
+my $version;
+sub process_file {
+    my $file = shift;
+    # Check the sanity of each .lua file
+    open my $in, $file or
+        die "ERROR: Can't open $file for reading: $!\n";
+    my $found_ver;
+    while (<$in>) {
+        my ($ver, $skipping);
+        if (/(?x) (?:_VERSION|version) \s* = .*? ([\d\.]*\d+) (.*? SKIP)?/) {
+            my $orig_ver = $ver = $1;
+            $found_ver = 1;
+            $skipping = $2;
+            $ver =~ s{^(\d+)\.(\d{3})(\d{3})$}{join '.', int($1), int($2), int($3)}e;
+            w("$file: $orig_ver ($ver)");
+            last;
+
+        } elsif (/(?x) (?:_VERSION|version) \s* = \s* ([a-zA-Z_]\S*)/) {
+            w("$file: $1");
+            $found_ver = 1;
+            last;
+        }
+
+        if ($ver and $version and !$skipping) {
+            if ($version ne $ver) {
+                die "$file: $ver != $version\n";
+            }
+        } elsif ($ver and !$version) {
+            $version = $ver;
+        }
+    }
+    if (!$found_ver) {
+        w("WARNING: No \"_VERSION\" or \"version\" field found in `$file`.");
+    }
+    close $in;
+
+    p("Checking use of Lua global variables in file $file...");
+    p("\top no.\tline\tinstruction\targs\t; code");
+    blank("luac -p -l $file | grep -E '[GS]ETGLOBAL' | grep -vE '\\<(require|type|tostring|error|ngx|ndk|jit|setmetatable|getmetatable|string|table|io|os|print|tonumber|math|pcall|xpcall|unpack|pairs|ipairs|assert|module|package|coroutine|[gs]etfenv|next|rawget|rawset|rawlen|select)\\>'");
+    unless ($no_long_line_check) {
+        p("Checking line length exceeding 80...");
+        blank("grep -H -n -E --color '.{81}' $file");
+    }
+}
+ 
\ No newline at end of file