return err or (math.floor(data.code / 100) ~= 2)
end
+local function parse_vault_reply(data)
+ local p = ucl.parser()
+ local res,parser_err = p:parse_string(data)
+
+ if not res then
+ return nil,parser_err
+ else
+ return p:get_object(),nil
+ end
+end
+
local function maybe_print_vault_data(opts, data, func)
if data then
- local p = ucl.parser()
- local res,parser_err = p:parse_string(data)
+ local res,parser_err = parse_vault_reply(data)
if not res then
printf('vault reply for cannot be parsed: %s', parser_err)
else
- local obj = p:get_object()
-
if func then
- printf(ucl.to_format(func(obj), opts.output))
+ printf(ucl.to_format(func(res), opts.output))
else
- printf(ucl.to_format(obj, opts.output))
+ printf(ucl.to_format(res, opts.output))
end
end
else
if #b64 < 255 then
labels = {'"' .. b64 .. '"'}
else
- for sl=1,#b64,255 do
+ for sl=1,#b64,256 do
table.insert(labels, '"' .. b64:sub(sl, sl + 255) .. '"')
end
end
return cr.gen_dkim_keypair(opts.algorithm, opts.bits)
end
+local function create_and_push_key(opts, domain, existing)
+ local uri = vault_url(opts, domain)
+ local sk,pk = genkey(opts)
+
+ local res = {
+ selectors = {
+ [1] = {
+ selector = opts.selector,
+ domain = domain,
+ key = tostring(sk),
+ alg = opts.algorithm,
+ }
+ }
+ }
+
+ for _,sel in ipairs(existing) do
+ res.selectors[#res.selectors + 1] = sel
+ end
+
+ if opts.expire then
+ res.selectors[1].valid_end = os.time() + opts.expire * 3600 * 24
+ end
+
+ local err,data = rspamd_http.request{
+ config = rspamd_config,
+ ev_base = rspamadm_ev_base,
+ session = rspamadm_session,
+ resolver = rspamadm_dns_resolver,
+ url = uri,
+ method = 'put',
+ headers = {
+ ['X-Vault-Token'] = opts.token
+ },
+ body = {
+ ucl.to_format(res, 'json-compact')
+ },
+ }
+
+ if is_http_error(err, data) then
+ printf('cannot get request to the vault (%s), HTTP error code %s', uri, data.code)
+ maybe_print_vault_data(opts, data.content)
+ os.exit(1)
+ else
+ maybe_printf(opts,'stored key for: %s, selector: %s', domain, opts.selector)
+ maybe_printf(opts, 'please place the corresponding public key as following:')
+
+ if opts.silent then
+ printf('%s', pk)
+ else
+ print_dkim_txt_record(tostring(pk), opts.selector, opts.algorithm)
+ end
+ end
+end
+
local function newkey_handler(opts, domain)
local uri = vault_url(opts, domain)
}
}
- if is_http_error(err, data) or not data.content.data then
- local sk,pk = genkey(opts)
-
- local res = {
- selectors = {
- [1] = {
- selector = opts.selector,
- domain = domain,
- key = tostring(sk),
- alg = opts.algorithm,
- }
- }
- }
+ if is_http_error(err, data) or not data.content then
+ create_and_push_key(opts, domain,{})
+ else
+ -- Key exists
+ local rep = parse_vault_reply(data.content)
- if opts.expire then
- res.selectors[1].valid_end = os.time() + opts.expire * 3600 * 24
+ if not rep or not rep.data then
+ printf('cannot parse reply for %s: %s', uri, data.content)
+ os.exit(1)
end
- err,data = rspamd_http.request{
- config = rspamd_config,
- ev_base = rspamadm_ev_base,
- session = rspamadm_session,
- resolver = rspamadm_dns_resolver,
- url = uri,
- method = 'put',
- headers = {
- ['X-Vault-Token'] = opts.token
- },
- body = {
- ucl.to_format(res, 'json-compact')
- },
- }
+ local elts = rep.data.selectors
- if is_http_error(err, data) then
- printf('cannot get request to the vault (%s), HTTP error code %s', uri, data.code)
- maybe_print_vault_data(opts, data.content)
- os.exit(1)
- else
- maybe_printf(opts,'stored key for: %s, selector: %s', domain, opts.selector)
- maybe_printf(opts, 'please place the corresponding public key as following:')
+ if not elts then
+ create_and_push_key(opts, domain,{})
+ os.exit(0)
+ end
- if opts.silent then
- printf('%s', pk)
+ for _,sel in ipairs(elts) do
+ if sel.alg == opts.algorithm then
+ printf('key with the specific algorithm %s is already presented at %s selector for %s domain',
+ opts.algorithm, sel.selector, domain)
+ os.exit(1)
else
- print_dkim_txt_record(tostring(pk), opts.selector, opts.algorithm)
+ create_and_push_key(opts, domain, elts)
end
end
end