commit 02f24b2: [Project] Add vault support for dkim and arc signing

Vsevolod Stakhov vsevolod at highsecure.ru
Mon Apr 22 13:35:04 UTC 2019


Author: Vsevolod Stakhov
Date: 2019-04-22 14:28:40 +0100
URL: https://github.com/rspamd/rspamd/commit/02f24b232c96cefa456c7b0823f05fb38480a613 (HEAD -> master)

[Project] Add vault support for dkim and arc signing

---
 lualib/lua_dkim_tools.lua        | 60 +++++++++++++++++++++++++++++++++++++++-
 src/plugins/lua/arc.lua          | 46 ++++++++++++++++--------------
 src/plugins/lua/dkim_signing.lua | 34 +++++++++++++----------
 3 files changed, 103 insertions(+), 37 deletions(-)

diff --git a/lualib/lua_dkim_tools.lua b/lualib/lua_dkim_tools.lua
index 332fd06f4..bb88a2a35 100644
--- a/lualib/lua_dkim_tools.lua
+++ b/lualib/lua_dkim_tools.lua
@@ -542,7 +542,7 @@ exports.sign_using_redis = function(N, task, settings, selectors, sign_func, err
           {settings.selector_prefix, p.domain} -- arguments
       )
       if not rret then
-        err_func(task, string.format("cannot make Redis request to load DKIM selector for domain %s: %s",
+        err_func(task, string.format("cannot make Redis request to load DKIM selector for domain %s",
             p.domain))
       end
     else
@@ -551,6 +551,64 @@ exports.sign_using_redis = function(N, task, settings, selectors, sign_func, err
   end
 end
 
+exports.sign_using_vault = function(N, task, settings, selectors, sign_func, err_func)
+  local http = require "rspamd_http"
+  local ucl = require "ucl"
+
+  local full_url = settings.vault_url .. '/' .. selectors.domain
+
+  local function vault_callback(err, code, body, _)
+    if code ~= 200 then
+      err_func(task, string.format('cannot request data from the vault url: %s; %s (%s)',
+          full_url, err, body))
+    else
+      local parser = ucl.parser()
+      local res,parser_err = parser:parse_string(body)
+      if not res then
+        err_func(task, string.format('vault reply for %s (data=%s) cannot be parsed: %s',
+            full_url, body, parser_err))
+      else
+        local obj = parser:get_object()
+
+        if not obj or not obj.data then
+          err_func(task, string.format('vault reply for %s (data=%s) is invalid, no data',
+              full_url, body))
+        else
+          local elts = obj.data.selectors or {}
+
+          for _,p in ipairs(elts) do
+            local dkim_sign_data = {
+              rawkey = p.key,
+              selector = p.selector,
+              domain = selectors.domain
+            }
+            lua_util.debugm(N, task, 'found and parsed key for %s:%s in Vault',
+                dkim_sign_data.domain, dkim_sign_data.selector)
+            sign_func(task, dkim_sign_data)
+          end
+        end
+      end
+    end
+  end
+
+  local ret = http.request{
+    task = task,
+    url = full_url,
+    callback = vault_callback,
+    timeout = settings.http_timeout or 5.0,
+    no_ssl_verify = settings.no_ssl_verify,
+    keepalive = true,
+    headers = {
+      ['X-Vault-Token'] = settings.vault_token,
+    },
+  }
+
+  if not ret then
+    err_func(task, string.format("cannot make HTTP request to load DKIM data domain %s",
+        selectors.domain))
+  end
+end
+
 exports.validate_signing_settings = function(settings)
   return settings.use_redis or
       settings.path or
diff --git a/src/plugins/lua/arc.lua b/src/plugins/lua/arc.lua
index 764a6e5a0..0bdaf5e14 100644
--- a/src/plugins/lua/arc.lua
+++ b/src/plugins/lua/arc.lua
@@ -582,31 +582,35 @@ local function arc_signing_cb(task)
   if settings.use_redis then
     dkim_sign_tools.sign_using_redis(N, task, settings, selectors, do_sign, sign_error)
   else
-    if ((p.key or p.rawkey) and p.selector) then
-      if p.key then
-        p.key = lua_util.template(p.key, {
-          domain = p.domain,
-          selector = p.selector
-        })
-
-        local exists,err = rspamd_util.file_exists(p.key)
-        if not exists then
-          if err and err == 'No such file or directory' then
-            lua_util.debugm(N, task, 'cannot read key from %s: %s', p.key, err)
-          else
-            rspamd_logger.warnx(task, 'cannot read key from %s: %s', p.key, err)
+    if selectors.vault then
+      dkim_sign_tools.sign_using_vault(N, task, settings, selectors, do_sign, sign_error)
+    else
+      if ((p.key or p.rawkey) and p.selector) then
+        if p.key then
+          p.key = lua_util.template(p.key, {
+            domain = p.domain,
+            selector = p.selector
+          })
+
+          local exists,err = rspamd_util.file_exists(p.key)
+          if not exists then
+            if err and err == 'No such file or directory' then
+              lua_util.debugm(N, task, 'cannot read key from %s: %s', p.key, err)
+            else
+              rspamd_logger.warnx(task, 'cannot read key from %s: %s', p.key, err)
+            end
+            return false
           end
-          return false
         end
-      end
 
-      local dret, hdr = dkim_sign(task, p)
-      if dret then
-        return arc_sign_seal(task, p, hdr)
+        local dret, hdr = dkim_sign(task, p)
+        if dret then
+          return arc_sign_seal(task, p, hdr)
+        end
+      else
+        rspamd_logger.infox(task, 'key path or dkim selector unconfigured; no signing')
+        return false
       end
-    else
-      rspamd_logger.infox(task, 'key path or dkim selector unconfigured; no signing')
-      return false
     end
   end
 end
diff --git a/src/plugins/lua/dkim_signing.lua b/src/plugins/lua/dkim_signing.lua
index 2a3930b4b..035c58492 100644
--- a/src/plugins/lua/dkim_signing.lua
+++ b/src/plugins/lua/dkim_signing.lua
@@ -99,23 +99,27 @@ local function dkim_signing_cb(task)
   if settings.use_redis then
     dkim_sign_tools.sign_using_redis(N, task, settings, selectors, do_sign, sign_error)
   else
-    if #selectors > 0 then
-      for _, k in ipairs(selectors) do
-        -- templates
-        if k.key then
-          k.key = lua_util.template(k.key, {
-            domain = k.domain,
-            selector = k.selector
-          })
-          lua_util.debugm(N, task, 'using key "%s", use selector "%s" for domain "%s"',
-              k.key, k.selector, k.domain)
+    if selectors.vault then
+      dkim_sign_tools.sign_using_vault(N, task, settings, selectors, do_sign, sign_error)
+    else
+      if #selectors > 0 then
+        for _, k in ipairs(selectors) do
+          -- templates
+          if k.key then
+            k.key = lua_util.template(k.key, {
+              domain = k.domain,
+              selector = k.selector
+            })
+            lua_util.debugm(N, task, 'using key "%s", use selector "%s" for domain "%s"',
+                k.key, k.selector, k.domain)
+          end
+
+          do_sign(task, k)
         end
-
-        do_sign(task, k)
+      else
+        rspamd_logger.infox(task, 'key path or dkim selector unconfigured; no signing')
+        return false
       end
-    else
-      rspamd_logger.infox(task, 'key path or dkim selector unconfigured; no signing')
-      return false
     end
   end
 end


More information about the Commits mailing list