-
Notifications
You must be signed in to change notification settings - Fork 2
/
tramp-auto-auth.el
176 lines (157 loc) · 6.73 KB
/
tramp-auto-auth.el
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
;;; tramp-auto-auth.el --- TRAMP automatic authentication library -*- lexical-binding: t -*-
;; Copyright (C) 2019 Bruno Félix Rezende Ribeiro <[email protected]>
;; Author: Bruno Félix Rezende Ribeiro <[email protected]>
;; Keywords: comm, processes
;; Package: tramp-auto-auth
;; Homepage: https://github.com/oitofelix/tramp-auto-auth
;; Version: 20191027.1117
;; Package-Requires: ((emacs "24.4") (tramp "0.0"))
;; This program is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
;; This library provides ‘tramp-auto-auth-mode’: a global minor mode
;; whose purpose is to automatically feed TRAMP sub-processes with
;; passwords for paths matching regexps. This is useful in situations
;; where interactive user input is not desirable or feasible. For
;; instance, in sub-nets with large number of hosts or whose hosts
;; have dynamic IPs assigned to them. In those cases it’s not
;; practical to query passwords using the ‘auth-source’ library
;; directly, since this would require each host to be listed
;; explicitly and immutably in a Netrc file. Another scenario where
;; this mode is useful are non-interactive Emacs sessions (like those
;; used for batch processing or by evaluating ‘:async’ Org Babel
;; source blocks) in which it’s impossible for the user to answer a
;; password-asking prompt.
;;
;; When a TRAMP prompt is encountered, ‘tramp-auto-auth-mode’ queries
;; the alist ‘tramp-auto-auth-alist’ for the auth-source spec value
;; whose regexp key matches the correspondent TRAMP path. This spec
;; is then used to query the auth-source library for a presumably
;; phony entry exclusively dedicated to the whole class of TRAMP
;; paths matching that regexp.
;;
;; To make use of the automatic authentication feature, on the Lisp
;; side the variable ‘tramp-auto-auth-alist’ must be customized to
;; hold the path regexps and their respective auth-source specs, and
;; then ‘tramp-auto-auth-mode’ must be enabled. For example:
;;
;; ---- ~/.emacs.el -------------------------------------------------
;; (require 'tramp-auto-auth)
;;
;; (add-to-list
;; 'tramp-auto-auth-alist
;; '("root@10\\.0\\." .
;; (:host "Funny-Machines" :user "root" :port "ssh")))
;;
;; (tramp-auto-auth-mode)
;; ------------------------------------------------------------------
;;
;; After this, just put the respective sacred secret in an
;; authentication source supported by auth-source library. For
;; instance:
;;
;; ---- ~/.authinfo.gpg ---------------------------------------------
;; machine Funny-Machines login root password "$r00tP#sWD!" port ssh
;; ------------------------------------------------------------------
;;
;; In case you are feeling lazy or the secret is not so secret (nor so
;; sacred) -- or for any reason you need to do it all from Lisp --
;; it’s enough to:
;;
;; (auth-source-remember '(:host "Funny-Machines" :user "root" :port "ssh")
;; '((:secret "$r00tP#sWD!")))
;;
;; And happy TRAMPing!
;;; Code:
(require 'tramp)
(require 'auth-source)
(defcustom tramp-auto-auth-alist
nil
"Alist of TRAMP paths regexps and their respective auth-source SPEC.
Each element has the form (PATH-REGEXP . SPEC), where PATH-REGEXP
is a regular expression to be matched against TRAMP paths and
SPEC is the respective auth-source SPEC which will be used to
retrieve the password to be sent to the TRAMP’s sub-process in
case a match does occur.
SPEC is exactly the one expected by ‘auth-source-search’."
:type '(alist
:key-type
(string :tag "Path Regexp"
:help-echo "Regexp which matches the desired TRAMP path")
:value-type
(plist :key-type (choice :tag "Key"
:help-echo "Auth-source spec key"
(const :tag "Host" :host)
(const :tag "User" :user)
(const :tag "Port" :port)
(symbol :tag "Other keyword"))
:value-type (string :tag "Value"
:help-echo "Auth-source spec value")
:tag "Auth-source spec"
:help-echo "Password for the TRAMP path resource"))
:group 'tramp
:require 'tramp-auto-auth)
;;;###autoload
(define-minor-mode tramp-auto-auth-mode
"Toggle Tramp-Auto-Auth global minor mode on or off.
With a prefix argument ARG, enable Tramp-Auto-Auth mode if ARG is
positive, and disable it otherwise. If called from Lisp, enable
the mode if ARG is omitted or nil, and toggle it if ARG is ‘toggle’.
When enabled ‘tramp-auto-auth-alist’ is used to automatically
authenticate to remote servers."
:group 'tramp
:global t
:require 'tramp-auto-auth
(if tramp-auto-auth-mode
(progn
(advice-add #'tramp-action-password :around
(lambda (tramp-action-password proc vec)
(pcase (or (car (last vec)) "")
((and (app (lambda (expval)
(assoc-default expval
tramp-auto-auth-alist
#'string-match-p))
spec)
(guard spec)
(let pre-secret (plist-get
(car (apply
#'auth-source-search
spec))
:secret))
(guard pre-secret)
(let secret (if (functionp pre-secret)
(funcall pre-secret)
pre-secret))
(guard secret))
(when (and spec pre-secret) ; See [0] below.
(process-send-string
proc (concat secret tramp-local-end-of-line))))
(_ (funcall tramp-action-password proc vec))))
'((name . tramp-auto-auth-mode)))
(advice-add #'tramp-action-yesno :around
(lambda (tramp-action-yesno proc vec)
(pcase (or (car (last vec)) "")
((pred (lambda (expval)
(assoc-default expval tramp-auto-auth-alist
#'string-match-p)))
(tramp-send-string
vec (concat "yes" tramp-local-end-of-line)))
(_ (funcall tramp-action-yesno proc vec))))
'((name . tramp-auto-auth-mode))))
(advice-remove #'tramp-action-password 'tramp-auto-auth-mode)
(advice-remove #'tramp-action-yesno 'tramp-auto-auth-mode)))
;; [0] This ‘when’ is superfluous, but pacifies the byte compiler
;; which would otherwise spuriously warn that ‘spec’ and
;; ‘pre-secret’ are unused lexical variables. This bug should be
;; reported to Emacs core developers. Thanks to Chris Rayner for
;; pointing this out.
(provide 'tramp-auto-auth)
;;; tramp-auto-auth.el ends here