restclient.el icon indicating copy to clipboard operation
restclient.el copied to clipboard

Add support for certs, keys and cacert.

Open narendraj9 opened this issue 5 years ago • 3 comments

Currently, here is what I do:

  (defun do-it-with-curl ()
    "Execute current request with curl, with key and certs.
Define variables :key, :cert and :cacert as absolute paths to the
respective files."
    (interactive)
    (restclient-http-parse-current-and-do
     (lambda (method url headers entity)
       (let* ((vars (restclient-find-vars-before-point))
              (restclient-display-buffer-name (if restclient-same-buffer-response
                                                  restclient-same-buffer-response-name
                                                (format "*HTTP %s %s*" method url)))
              ;; Extra arguments to curl for handling TLS stuff: certificates and keys
              (keyfile (assoc-default ":key" vars))
              (ca-cert (assoc-default ":cacert" vars))
              (client-cert (assoc-default ":cert" vars))
              (header-args (apply 'append (mapcar (lambda (header) (list "-H" (format "%s: %s" (car header) (cdr header)))) headers)))
              (curl-command (concat "curl " (mapconcat 'shell-quote-argument
                                                       (append '("-sD" "-")
                                                               (when keyfile `("--key" ,keyfile))
                                                               (when ca-cert `("--cacert" ,ca-cert))
                                                               (when client-cert `("--cert" ,client-cert))
                                                               header-args
                                                               (list (concat "-X" method))
                                                               (list url)
                                                               (when (> (string-width entity) 0)
                                                                 (list "-d" entity)))
                                                       " "))))
         (with-temp-buffer
           (insert (shell-command-to-string curl-command))
           ;; Remove 
 characters
           (goto-char (point-min))
           (replace-regexp "
" "")
           (restclient-http-handle-response nil
                                            method
                                            url
                                            restclient-display-buffer-name
                                            nil
                                            t
                                            ))))))

This uses some variables that need to be defined and curl needs to be installed.

narendraj9 avatar Aug 09 '18 16:08 narendraj9

Client certificates seem to have better support in Emacs 27. I did the following to get restclient to talk to a host with a certificate:

  1. Tell network-stream to look for matching certificates: (setq network-stream-use-client-certificates t)
  2. Add host and certificate path in ~/.authinfo like this
machine host.example.com port 443 key /path/to/key cert /path/to/cert

No special configuration of restclient itself is needed.

mpolden avatar Sep 21 '20 09:09 mpolden

@mpolden Do you have any idea if restclient package can handle p12 cert types though authinfo?

This is how it is done in curl

curl --cert-type p12 --cert cert.pfx:${password} -X GET https://${url}/ -H 'Content-Type: application/json'

cert.pfx is a certificate file.

I know that I can rewrite @narendraj9's do-it-with-curl function accordingly but Is there elegant way like you mentioned above?

Thanks

CsBigDataHub avatar Sep 29 '20 19:09 CsBigDataHub

Can confirm that @mpolden Emacs auth-source works.

Of course key and cert can be generate from p12 -

openssl pkcs12 -in mycert.p12 -out file.key.pem -nocerts -nodes
openssl pkcs12 -in mycert.p12 -out file.crt.pem -clcerts -nokeys

CsBigDataHub avatar Feb 10 '21 19:02 CsBigDataHub