1SUDO_PLUGIN_PYTHON(5)       BSD File Formats Manual      SUDO_PLUGIN_PYTHON(5)
2

NAME

4     sudo_plugin_python — Sudo Plugin API (Python)
5

DESCRIPTION

7     Starting with version 1.9, sudo plugins can be written in python.  The
8     API closely follows the C sudo plugin API described by sudo_plugin(5).
9
10     The supported plugins types are:
11
12         ·  Policy plugin
13         ·  I/O plugin
14         ·  Audit plugin
15         ·  Approval plugin
16         ·  Group provider plugin
17
18     Python plugin support needs to be explicitly enabled at build time with
19     the configure option “--enable-python”.  Python version 3.0 or higher is
20     required.
21
22   Sudo Python Plugin Base
23     A plugin written in Python should be a class in a python file that inher‐
24     its from sudo.Plugin.  The sudo.Plugin base class has no real purpose
25     other than to identify this class as a plugin.
26
27     The only implemented method is a constructor, which stores the keyword
28     arguments it receives as fields (member variables) in the object.  This
29     is intended as a convenience to allow you to avoid writing the construc‐
30     tor yourself.
31
32     For example:
33
34           import sudo
35
36           class MySudoPlugin(sudo.Plugin):
37               # example constructor (optional)
38               def __init__(self, *args, **kwargs):
39                   super().__init__(*args, **kwargs)
40
41               # example destructor (optional)
42               def __del__(self):
43                   pass
44
45     Both the constructor and destructor are optional and can be omitted.
46
47     The customized Plugin class should define a few plugin-specific methods.
48     When the plugin loads, sudo will create an instance of this class and
49     call the methods.  The actual methods required depent on the type of the
50     plugin, but most return an “int” result code, as documented in
51     sudo_plugin(@mansctsu@), that indicates whether or not the method was
52     successful.  The Python sudo module defines the following constants to
53     improve readability:
54
55         Define                 Value
56         sudo.RC.OK             1
57         sudo.RC.ACCEPT         1
58         sudo.RC.REJECT         0
59         sudo.RC.ERROR          -1
60         sudo.RC.USAGE_ERROR    -2
61
62     If a function returns None (for example, if it does not call return), it
63     will be considered to have returned sudo.RC.OK.  If an exception is
64     raised (other than sudo.PluginException), the backtrace will be shown to
65     the user and the plugin function will return sudo.RC.ERROR.  If that is
66     not acceptable, you must catch the exception and handle it yourself.
67
68     Instead of just returning sudo.RC.ERROR or sudo.RC.REJECT result code the
69     plugin can also provide a message describing the problem.  This can be
70     done by raising one of the special exceptions:
71
72           raise sudo.PluginError("Message")
73           raise sudo.PluginReject("Message")
74
75     This added message will be used by the audit plugins.  Both exceptions
76     inherit from sudo.PluginException
77
78   Python Plugin Loader
79     Running the Python interpreter and bridging between C and Python is han‐
80     dled by the sudo plugin python_plugin.so.  This shared object can be
81     loaded like any other dynamic sudo plugin and should receive the path and
82     the class name of the Python plugin it is loading as arguments.
83
84     Example usage in sudo.conf(5):
85
86           Plugin python_policy python_plugin.so ModulePath=<path> ClassName=<class>
87           Plugin python_io python_plugin.so ModulePath=<path> ClassName=<class>
88           Plugin python_audit python_plugin.so ModulePath=<path> ClassName=<class>
89           Plugin python_approval python_plugin.so ModulePath=<path> ClassName=<class>
90
91     Example group provider plugin usage in the sudoers file:
92
93           Defaults group_plugin="python_plugin.so ModulePath=<path> ClassName=<class>"
94
95     The plugin arguments are as follows:
96
97     ModulePath
98           The path of a python file which contains the class of the sudo
99           Python plugin.  It must be either an absolute path or a path rela‐
100           tive to the sudo Python plugin directory:
101           "/usr/libexec/sudo/python".
102
103     ClassName
104           (Optional.) The name of the class implementing the sudo Python
105           plugin.  If not supplied, the one and only sudo.Plugin that is
106           present in the module will be used.  If there are multiple such
107           plugins in the module (or none), it will result in an error.
108
109   Policy plugin API
110     Policy plugins must be registered in sudo.conf(5).  For example:
111
112           Plugin python_policy python_plugin.so ModulePath=<path> ClassName=<class>
113
114     Currently, only a single policy plugin may be specified in sudo.conf(5).
115
116     A policy plugin may have the following member functions:
117
118     constructor
119
120           __init__(self, user_env: Tuple[str, ...], settings: Tuple[str, ...],
121               version: str, user_info: Tuple[str, ...],
122               plugin_options: Tuple[str, ...])
123
124           Implementing this function is optional.  The default constructor
125           will set the keyword arguments it receives as member variables in
126           the object.
127
128           The constructor matches the open() function in the C sudo plugin
129           API.
130
131           The function arguments are as follows:
132
133           user_env
134                 The user's environment as a tuple of strings in “key=value”
135                 format.
136
137           settings
138                 A tuple of user-supplied sudo settings in the form of
139                 “key=value” strings.
140
141           version
142                 The version of the Python Policy Plugin API.
143
144           user_info
145                 A tuple of information about the user running the command in
146                 the form of “key=value” strings.
147
148           plugin_options
149                 The plugin options passed as arguments in the sudo.conf(5)
150                 plugin registration.  This is a tuple of strings, usually
151                 (but not necessarily) in “key=value” format.
152
153           The sudo.options_as_dict() convenience function can be used to con‐
154           vert “key=value” pairs to a dictionary.  For a list of recognized
155           keys and their supported values, see the policy plugin open() docu‐
156           mentation in sudo_plugin(5).
157
158     check_policy
159           check_policy(self, argv: Tuple[str, ...], env_add: Tuple[str, ...])
160
161           The check_policy() function is called by sudo to determine whether
162           the user is allowed to run the specified command.  Implementing
163           this function is mandatory for a policy plugin.
164
165           The function arguments are as follows:
166
167           argv  A tuple describing the command the user wishes to run.
168
169           env_add
170                 Additional environment variables specified by the user on the
171                 command line in the form of a tuple of “key=value” pairs.
172                 The sudo.options_as_dict() convenience function can be used
173                 to convert them to a dictionary.
174
175           This function should return a result code or a tuple in the follow‐
176           ing format:
177
178                 return (rc, command_info_out, argv_out, user_env_out)
179
180           The tuple values are as follows:
181
182           rc    The result of the policy check, one of the sudo.RC.* con‐
183                 stants.  sudo.RC.ACCEPT if the command is allowed,
184                 sudo.RC.REJECT if not allowed, sudo.RC.ERROR for a general
185                 error, or sudo.RC.USAGE_ERROR for a usage error.
186
187           command_info_out
188                 Optional (only required when the command is accepted).
189                 Information about the command being run in the form of
190                 “key=value” strings.
191
192                 To accept a command, at the very minimum the plugin must set
193                 in the command, runas_uid and runas_gid keys.
194
195                 For a list of recognized keys and supported values, see the
196                 check_policy() documentation in sudo_plugin(5).
197
198           argv_out
199                 Optional (only required when the command is accepted).  The
200                 arguments to pass to the execve(2) system call when executing
201                 the command.
202
203           user_env_out
204                 Optional (only required when the command is accepted).  The
205                 environment to use when executing the command in the form of
206                 a tuple of strings in “key=value” format.
207
208     init_session
209           init_session(self, user_pwd: Tuple, user_env: Tuple[str, ...])
210
211           Perform session setup (optional).  The init_session() function is
212           called before sudo sets up the execution environment for the com‐
213           mand before any uid or gid changes.
214
215           The function arguments are as follows:
216
217           user_pwd
218                 A tuple describing the user's passwd entry.  Convertible to
219                 pwd.struct_passwd or None if the user is not present in the
220                 password database.
221
222                 Example conversion:
223                       user_pwd = pwd.struct_passwd(user_pwd) if user_pwd else None
224
225           user_env
226                 The environment the command will run in.  This is a tuple of
227                 strings in “key=value” format.
228
229           This function should return a result code or a tuple in the follow‐
230           ing format:
231
232               return (rc, user_env_out)
233
234           The tuple values are as follows:
235
236           rc    The result of the session init, one of the sudo.RC.* con‐
237                 stants.  sudo.RC.OK on success, 0 on failure, or
238                 sudo.RC.ERROR if an error occurred.
239
240           user_env_out
241                 Optional.  If the init_session() function needs to modify the
242                 user environment, it can return the new environment in
243                 user_env_out.  If this is omitted, no changes will be made to
244                 user_env.
245
246     list
247           list(self, argv: Tuple[str, ...], is_verbose: int, user: str)
248
249           List available privileges for the invoking user.
250
251           The function arguments are as follows:
252
253           argv  If not set to None, an argument vector describing a command
254                 the user wishes to check against the policy.
255
256           is_verbose
257                 Flag indicating whether to list in verbose mode or not.
258
259           user  The name of a different user to list privileges for if the
260                 policy allows it.  If None, the plugin should list the privi‐
261                 leges of the invoking user.
262
263     validate
264           validate(self)
265
266           For policy plugins that cache authentication credentials, this
267           function is used to validate and cache the credentials (optional).
268
269     invalidate
270           invalidate(self, remove: int)
271
272           For policy plugins that cache authentication credentials, this
273           function is used to invalidate the credentials (optional).
274
275           The function arguments are as follows:
276
277           remove
278                 If this flag is set, the plugin may remove the credentials
279                 instead of simply invalidating them.
280
281     show_version
282           show_version(self, is_verbose: int)
283
284           Display the plugin version information to the user.  The
285           sudo.log_info() function should be used.
286
287           The function arguments are as follows:
288
289           is_verbose
290                 A flag to indicate displaying more verbose information.  Cur‐
291                 rently this is 1 if ‘sudo -V’ is run as the root user.
292
293     close
294           close(self, exit_status: int, error: int)
295
296           Called when a command finishes executing.
297
298           Works the same as the close() function in the C sudo plugin API,
299           except that it only gets called if sudo attempts to execute the
300           command.
301
302           The function arguments are as follows:
303
304           exit_status
305                 The exit status of the command if was executed, otherwise -1.
306
307           error
308                 If the command could not be executed, this is set to the
309                 value of errno set by the execve(2) system call, otherwise 0.
310
311   Policy plugin example
312     Sudo ships with an example Python policy plugin.  To try it, register it
313     by adding the following lines to /etc/sudo.conf:
314
315     Plugin python_policy python_plugin.so \
316         ModulePath=/usr/share/doc/sudo/examples/example_policy_plugin.py \
317         ClassName=SudoPolicyPlugin
318
319     Be aware, however, that you cannot enable the Python policy plugin in
320     addition to another policy plugin, such as sudoers(5).
321
322   I/O plugin API
323     I/O plugins must be registered in sudo.conf(5).  For example:
324
325           Plugin python_io python_plugin.so ModulePath=<path> ClassName=<class>
326
327     Sudo supports loading multiple I/O plugins.  Currently only 8 python I/O
328     plugins can be loaded at once.
329
330     An I/O plugin may have the following member functions:
331
332     constructor
333           __init__(self, user_env: Tuple[str, ...], settings: Tuple[str, ...],
334               version: str, user_info: Tuple[str, ...],
335               plugin_options: Tuple[str, ...])
336
337           Implementing this function is optional.  The default constructor
338           will set the keyword arguments it receives as member variables in
339           the object.
340
341           The constructor matches the open() function in the C sudo plugin
342           API.
343
344           The function arguments are as follows:
345
346           user_env
347                 The user's environment as a tuple of strings in “key=value”
348                 format.
349
350           settings
351                 A tuple of user-supplied sudo settings in the form of
352                 “key=value” strings.
353
354           version
355                 The version of the Python I/O Plugin API.
356
357           user_info
358                 A tuple of information about the user running the command in
359                 the form of “key=value” strings.
360
361           plugin_options
362                 The plugin options passed as arguments in the sudo.conf(5)
363                 plugin registration.  This is a tuple of strings, usually
364                 (but not necessarily) in “key=value” format.
365
366           The sudo.options_as_dict() convenience function can be used to con‐
367           vert “key=value” pairs to a dictionary.  For a list of recognized
368           keys and their supported values, see the I/O plugin open() documen‐
369           tation in sudo_plugin(5).
370
371     open
372           open(self, argv: Tuple[str, ...],
373               command_info: Tuple[str, ...]) -> int
374
375           Receives the command the user wishes to run.
376
377           Works the same as the open() function in the C sudo plugin API
378           except that:
379
380               ·  It only gets called before the user would execute some com‐
381                  mand (and not for a version query for example).
382               ·  Other arguments of the C API open() function are received
383                  through the constructor.
384
385           The function arguments are as follows:
386
387           argv  A tuple of the arguments describing the command the user
388                 wishes to run.
389
390           command_info
391                 Information about the command being run in the form of
392                 “key=value” strings.
393
394           The sudo.options_as_dict() convenience function can be used to con‐
395           vert “key=value” pairs to a dictionary.  For a list of recognized
396           keys and their supported values, see the I/O plugin open() documen‐
397           tation in sudo_plugin(5).
398
399           The open() function should return a result code, one of the
400           sudo.RC.* constants.  If the function returns sudo.RC.REJECT, no
401           I/O will be sent to the plugin.
402
403     log_ttyin, log_ttyout, log_stdin, log_stdout, log_stderr
404           log_ttyin(self, buf: str) -> int
405           log_ttyout(self, buf: str) -> int
406           log_stdin(self, buf: str) -> int
407           log_stdout(self, buf: str) -> int
408           log_stderr(self, buf: str) -> int
409
410           Receive the user input or output of the terminal device and appli‐
411           cation standard input / output / error.  See the matching calls in
412           sudo_plugin(5).
413
414           The function arguments are as follows:
415
416           buf   The input (or output) buffer in the form of a string.
417
418           The function should return a result code, one of the sudo.RC.* con‐
419           stants.
420
421           If sudo.RC.ERROR is returned, the running command will be termi‐
422           nated and all of the plugin's logging functions will be disabled.
423           Other I/O logging plugins will still receive any remaining input or
424           output that has not yet been processed.
425
426           If an input logging function rejects the data by returning
427           sudo.RC.REJECT, the command will be terminated and the data will
428           not be passed to the command, though it will still be sent to any
429           other I/O logging plugins.  If an output logging function rejects
430           the data by returning sudo.RC.REJECT, the command will be termi‐
431           nated and the data will not be written to the terminal, though it
432           will still be sent to any other I/O logging plugins.
433
434     change_winsize
435           change_winsize(self, line: int, cols: int) -> int
436
437           Called whenever the window size of the terminal changes.  The func‐
438           tion arguments are as follows:
439
440           line  The number of lines of the terminal.
441
442           cols  The number of columns of the terminal.
443
444     log_suspend
445           log_suspend(self, signo: int) -> int
446           Called whenever a command is suspended or resumed.
447
448           The function arguments are as follows:
449
450           signo
451                 The number of the signal that caused the command to be sus‐
452                 pended or SIGCONT if the command was resumed.
453
454     show_version
455           show_version(self, is_verbose: int)
456           Display the plugin version information to the user.  The
457           sudo.log_info() function should be used.
458
459           The function arguments are as follows:
460
461           is_verbose
462                 A flag to indicate displaying more verbose information.  Cur‐
463                 rently this is 1 if ‘sudo -V’ is run as the root user.
464
465     close
466           close(self, exit_status: int, error: int) -> None
467           Called when a command execution finished.
468
469           Works the same as the close() function in the C sudo plugin API,
470           except that it only gets called if sudo attempts to execute the
471           command.
472
473           The function arguments are as follows:
474
475           exit_status
476                 The exit status of the command if was executed, otherwise -1.
477
478           error
479                 If the command could not be executed, this is set to the
480                 value of errno set by the execve(2) system call, otherwise 0.
481
482   I/O plugin example
483     Sudo ships a Python I/O plugin example.  To try it, register it by adding
484     the following lines to /etc/sudo.conf:
485
486           Plugin python_io python_plugin.so \
487               ModulePath=/usr/share/doc/sudo/examples/example_io_plugin.py \
488               ClassName=SudoIOPlugin
489
490   Audit plugin API
491     Audit plugins must be registered in sudo.conf(5).  For example:
492
493           Plugin python_audit python_plugin.so ModulePath=<path> ClassName=<class>
494
495     Sudo supports loading multiple audit plugins.  Currently only 8 python
496     audit plugins can be loaded at once.
497
498     An audit plugin may have the following member functions (all of them are
499     optional):
500
501     constructor
502           __init__(self, user_env: Tuple[str, ...], settings: Tuple[str, ...],
503               version: str, user_info: Tuple[str, ...], plugin_options: Tuple[str, ...])
504
505           The default constructor will set the keyword arguments it receives
506           as member variables in the object.
507
508           The constructor matches the open() function in the C sudo plugin
509           API.
510
511           The function arguments are as follows:
512
513           user_env
514                 The user's environment as a tuple of strings in “key=value”
515                 format.
516
517           settings
518                 A tuple of user-supplied sudo settings in the form of
519                 “key=value” strings.
520
521           version
522                 The version of the Python Audit Plugin API.
523
524           user_info
525                 A tuple of information about the user running the command in
526                 the form of “key=value” strings.
527
528           plugin_options
529                 The plugin options passed as arguments in the sudo.conf(5)
530                 plugin registration.  This is a tuple of strings, usually
531                 (but not necessarily) in “key=value” format.
532
533     open
534           open(self, submit_optind: int,
535               submit_argv: Tuple[str, ...]) -> int
536
537           The function arguments are as follows:
538
539           submit_optind
540                 The index into submit_argv that corresponds to the first
541                 entry that is not a command line option.
542
543           submit_argv
544                 The argument vector sudo was invoked with, including all com‐
545                 mand line options.
546
547     close
548           close(self, status_type: int, status: int) -> None
549
550           Called when sudo is finished, shortly before it exits.
551
552           The function arguments are as follows:
553
554           status_type
555                 The type of status being passed.  One of the sudo.EXIT_REA‐
556                 SON.* constants.
557
558           status
559                 Depending on the value of status_type, this value is either
560                 ignored, the command's exit status as returned by the wait(2)
561                 system call, the value of errno set by the execve(2) system
562                 call, or the value of errno resulting from an error in the
563                 sudo front end.
564
565     show_version
566           show_version(self, is_verbose: int) -> int
567
568           Display the plugin version information to the user.  The
569           sudo.log_info() function should be used.
570
571           The function arguments are as follows:
572
573           is_verbose
574                 A flag to indicate displaying more verbose information.  Cur‐
575                 rently this is 1 if ‘sudo -V’ is run as the root user.
576
577     accept
578           accept(self, plugin_name: str, plugin_type: int, command_info: Tuple[str, ...],
579                  run_argv: Tuple[str, ...], run_envp: Tuple[str, ...]) -> int
580
581           This function is called when a command or action is accepted by the
582           policy plugin.  The function arguments are as follows:
583
584           plugin_name
585                 The name of the plugin that accepted the command.
586
587           plugin_type
588                 The type of plugin that accepted the command, currently
589                 always sudo.PLUGIN_TYPE.POLICY.
590
591           command_info
592                 A vector of information describing the command being run.
593                 See the sudo_plugin(5) manual for possible values.
594
595           run_argv
596                 Argument vector describing a command that will be run.
597
598           run_envp
599                 The environment the command will be run with.
600
601     reject
602           reject(self, plugin_name: str, plugin_type: int, audit_msg: str,
603                  command_info: Tuple[str, ...]) -> int
604
605           This function is called when a command or action is rejected by the
606           policy plugin.  The function arguments are as follows:
607
608           plugin_name
609                 The name of the plugin that accepted the command.
610
611           plugin_type
612                 The type of plugin that accepted the command, currently
613                 always sudo.PLUGIN_TYPE.POLICY.
614
615           audit_msg
616                 An optional string describing the reason the command was
617                 rejected by the plugin.  If the plugin did not provide a rea‐
618                 son, audit_msg will be None
619
620           command_info
621                 A vector of information describing the rejected command.  See
622                 the sudo_plugin(5) manual for possible values.
623
624     error
625           error(self, plugin_name: str, plugin_type: int, audit_msg: str,
626                 command_info: Tuple[str, ...]) -> int
627
628           This function is called when a plugin returns an error.  The func‐
629           tion arguments are as follows:
630
631           plugin_name
632                 The name of the plugin that accepted the command.
633
634           plugin_type
635                 The type of plugin that accepted the command, currently
636                 sudo.PLUGIN_TYPE.POLICY or sudo.PLUGIN_TYPE.IO
637
638           audit_msg
639                 An optional string describing the plugin error.  If the plug‐
640                 in did not provide a description, it will be None
641
642           command_info
643                 A vector of information describing the command.  See the
644                 sudo_plugin(5) manual for possible values.
645
646   Audit plugin example
647     Sudo ships a Python Audit plugin example.  To try it, register it by
648     adding the following lines to /etc/sudo.conf:
649
650           Plugin python_audit python_plugin.so \
651               ModulePath=/usr/share/doc/sudo/examples/example_audit_plugin.py \
652               ClassName=SudoAuditPlugin
653
654     It will log the plugin accept / reject / error results to the output.
655
656   Approval plugin API
657     Approval plugins must be registered in sudo.conf(5).  For example:
658
659           Plugin python_approval python_plugin.so ModulePath=<path> ClassName=<class>
660
661     Sudo supports loading multiple approval plugins.  Currently only 8 python
662     approval plugins can be loaded at once.
663
664     An approval plugin may have the following member functions:
665
666     constructor
667           __init__(self, user_env: Tuple[str, ...], settings: Tuple[str, ...],
668               version: str, user_info: Tuple[str, ...], plugin_options: Tuple[str, ...],
669               submit_optind: int, submit_argv: Tuple[str, ...])
670
671           Optional.  The default constructor will set the keyword arguments
672           it receives as member variables in the object.
673
674           The constructor matches the open() function in the C sudo plugin
675           API.
676
677           The function arguments are as follows:
678
679           user_env
680                 The user's environment as a tuple of strings in “key=value”
681                 format.
682
683           settings
684                 A tuple of user-supplied sudo settings in the form of
685                 “key=value” strings.
686
687           version
688                 The version of the Python Approval Plugin API.
689
690           user_info
691                 A tuple of information about the user running the command in
692                 the form of “key=value” strings.
693
694           plugin_options
695                 The plugin options passed as arguments in the sudo.conf(5)
696                 plugin registration.  This is a tuple of strings, usually
697                 (but not necessarily) in “key=value” format.
698
699           submit_optind
700                 The index into submit_argv that corresponds to the first
701                 entry that is not a command line option.
702
703           submit_argv
704                 The argument vector sudo was invoked with, including all com‐
705                 mand line options.
706
707     show_version
708           show_version(self, is_verbose: int) -> int
709
710           Display the version. (Same as for all the other plugins.)
711
712     check
713           check(self, command_info: Tuple[str, ...], run_argv: Tuple[str, ...],
714                 run_env: Tuple[str, ...]) -> int
715
716           This function is called after policy plugin's check_policy has suc‐
717           ceeded.  It can reject execution of the command by returning
718           sudo.RC.REJECT or raising the special exception:
719
720                 raise sudo.PluginReject("some message")
721
722           with the message describing the problem.  In the latter case, the
723           audit plugins will get the description.
724
725           The function arguments are as follows:
726
727           command_info
728                 A vector of information describing the command that will run.
729                 See the sudo_plugin(5) manual for possible values.
730
731           run_argv
732                 Argument vector describing a command that will be run.
733
734           run_env
735                 The environment the command will be run with.
736
737   Approval plugin example
738     Sudo ships a Python Approval plugin example.  To try it, register it by
739     adding the following lines to /etc/sudo.conf:
740
741           Plugin python_approval python_plugin.so \
742               ModulePath=/usr/share/doc/sudo/examples/example_approval_plugin.py \
743               ClassName=BusinessHoursApprovalPlugin
744
745     It will only allow execution of commands in the "business hours" (from
746     Monday to Friday between 8:00 and 17:59:59).
747
748   Sudoers group provider plugin API
749     A group provider plugin is registered in the sudoers(5) file.  For exam‐
750     ple:
751
752           Defaults group_plugin="python_plugin.so ModulePath=<path> ClassName=<class>"
753
754     Currently, only a single group plugin can be registered in sudoers.
755
756     A group provider plugin may have the following member functions:
757
758     constructor
759           __init__(self, args: Tuple[str, ...], version: str)
760
761           Implementing this function is optional.  The default constructor
762           will set the keyword arguments it receives as member variables in
763           the object.
764
765           The function arguments are as follows:
766
767           args  The plugin options passed as arguments in the sudoers file
768                 plugin registration.  All the arguments are free form strings
769                 (not necessarily in “key=value” format).
770
771           version
772                 The version of the Python Group Plugin API.
773
774     query
775           query(self, user: str, group: str, user_pwd: Tuple)
776
777           The query() function is used to ask the group plugin whether user
778           is a member of group.  This method is required.
779
780     The function arguments are as follows:
781
782     user  The name of the user being looked up in the external group data‐
783           base.
784
785     group
786           The name of the group being queried.
787
788     user_pwd
789           The password database entry for the user, if any.  If user is not
790           present in the password database, user_pwd will be NULL.
791
792   Group plugin example
793     Sudo ships a Python group plugin example.  To try it, register it in the
794     sudoers file by adding the following lines:
795
796           Defaults group_plugin="python_plugin.so \
797               ModulePath=/usr/share/doc/sudo/examples/example_group_plugin.py \
798               ClassName=SudoGroupPlugin"
799
800     The example plugin will tell sudo that the user test is part of the non-
801     unix group mygroup.  If you add a rule that uses this group, it will
802     affect the test user.  For example:
803
804           %:mygroup ALL=(ALL) NOPASSWD: ALL
805
806     Will allow user test to run sudo without a password.
807
808   Hook function API
809     The hook function API is currently not supported for plugins written in
810     Python.
811
812   Conversation API
813     A Python plugin can interact with the user using the sudo.conv() function
814     which displays one or more messages described by the sudo.ConvMessage
815     class.  This is the Python equivalent of the conversation() function in
816     the C sudo plugin API.  A plugin should not attempt to read directly from
817     the standard input or the user's tty (neither of which are guaranteed to
818     exist).
819
820     The sudo.ConvMessage class specifies how the user interaction should
821     occur:
822
823         sudo.ConvMessage(msg_type: int, msg: str, timeout: int)
824
825     sudo.ConvMessage member variables:
826
827     msg_type
828           Specifies the type of the conversation.  See the sudo.CONV.* con‐
829           stants below.
830
831     msg   The message to display to the user.  The caller must include a
832           trailing newline in msg if one is to be displayed.
833
834     timeout
835           Optional.  The maximum amount of time for the conversation in sec‐
836           onds.  If the timeout is exceeded, the sudo.conv() function will
837           raise a sudo.ConversationInterrupted exception.  The default is to
838           wait forever (no timeout).
839
840     To specify the message type, the following constants are available:
841
842         ·  sudo.CONV.PROMPT_ECHO_OFF
843         ·  sudo.CONV.PROMPT_ECHO_ON
844         ·  sudo.CONV.ERROR_MSG
845         ·  sudo.CONV.INFO_MSG
846         ·  sudo.CONV.PROMPT_MASK
847         ·  sudo.CONV.PROMPT_ECHO_OK
848         ·  sudo.CONV.PREFER_TTY
849
850     See the sudo_plugin(5) manual for a description of the message types.
851
852     The sudo.conv() function performs the actual user interaction:
853
854         sudo.conv(message(s), on_suspend=suspend_function,
855             on_resume=resume_function)
856
857     The function arguments are as follows:
858
859     messsage(s)
860           One of more messages (of type sudo.ConvMessage), each describing a
861           conversation.  At least one message is required.
862
863     on_suspend
864           An optional callback function which gets called if the conversation
865           is suspended, for example by the user pressing control-Z.  The
866           specified function must take a single argument which will be filled
867           with the number of the signal that caused the process to be sus‐
868           pended.
869
870     on_resume
871           An optional callback function which gets called when the previously
872           suspended conversation is resumed.  The specified function must
873           take a single argument which will be filled with the number of the
874           signal that caused the process to be suspended.
875
876     The sudo.conv() function can raise the following exceptions:
877
878     sudo.SudoException
879           If the conversation fails, for example when the conversation func‐
880           tion is not available.
881
882     sudo.ConversationInterrupted
883           If the conversation function returns an error, e.g., the timeout
884           passed or the user interrupted the conversation by pressing con‐
885           trol-C.
886
887   Conversation example
888     Sudo ships with an example plugin demonstrating the Python conversation
889     API.  To try it, register it by adding the following lines to
890     /etc/sudo.conf:
891
892           Plugin python_io python_plugin.so \
893               ModulePath=/usr/share/doc/sudo/examples/example_conversation.py \
894               ClassName=ReasonLoggerIOPlugin
895
896   Information / error display API
897     sudo.log_info(string(s), sep=" ", end="\n")
898     sudo.log_error(string(s), sep=" ", end="\n")
899
900     To display information to the user, the sudo.log_info() function can be
901     used.  To display error messages, use sudo.log_error().  The syntax is
902     similar to the Python print() function.
903
904     The function arguments are as follows:
905
906     string(s)
907           One or more strings to display.
908
909     sep   An optional string which will be used as the separator between the
910           specified strings.  The default is a space character, (‘ ’).
911
912     end   An optional string which will be displayed at the end of the mes‐
913           sage.  The default is a new line character (‘\n’).
914
915   Debug API
916     Debug messages are not visible to the user and are only logged debugging
917     is explicitly enabled in sudo.conf(5).  Python plugins can use the
918     sudo.debug() function to make use of sudo's debug system.
919
920     Enabling debugging in sudo.conf
921
922     To enable debug messages, add a Debug line to sudo.conf(5) with the pro‐
923     gram set to python_plugin.so.  For example, to store debug output in
924     /var/log/sudo_python_debug, use a line like the following:
925
926           Debug python_plugin.so /var/log/sudo_python_debug \
927               plugin@trace,c_calls@trace
928
929     The debug options are in the form of multiple “subsystem@level” strings,
930     separated by commas (‘,’).  For example to just see the debug output of
931     sudo.debug() calls, use:
932
933           Debug python_plugin.so /var/log/sudo_python_debug plugin@trace
934
935     See sudo_conf(5) for more details.
936
937     The most interesting subsystems for Python plugin development are:
938
939     plugin
940           Logs each sudo.debug() API call.
941
942     py_calls
943           Logs whenever a C function calls into the python module.  For exam‐
944           ple, calling the __init__() function.
945
946     c_calls
947           Logs whenever python calls into a C sudo API function.
948
949     internal
950           Logs internal functions of the python language wrapper plugin.
951
952     sudo_cb
953           Logs when sudo calls into the python plugin API.
954
955     load  Logs python plugin loading / unloading events.
956
957     You can also specify “all” as the subsystem name to log debug messages
958     for all subsystems.
959
960     The sudo.debug() function is defined as:
961
962         sudo.debug(level, message(s))
963
964     The function arguments are as follows:
965
966     level
967           an integer, use one of the log level constants below
968
969     messsage(s)
970           one or more messages to log
971
972     Available log levels:
973
974     sudo.conf name       Python constant    description
975     crit                 sudo.DEBUG.CRIT    only cricital messages
976     err                  sudo.DEBUG.ERROR
977     warn                 sudo.DEBUG.WARN
978     notice               sudo.DEBUG.NOTICE
979     diag                 sudo.DEBUG.DIAG
980     info                 sudo.DEBUG.INFO
981     trace                sudo.DEBUG.TRACE
982     debug                sudo.DEBUG.DEBUG   very extreme verbose debugging
983
984     Using the logging module
985
986     Alternatively, a plugin can use the built in logging module of Python as
987     well.  Sudo adds its log handler to the root logger, so by default all
988     output of a logger will get forwarded to sudo log system, as it would
989     call sudo.debug.
990
991     The log handler of sudo will map each Python log level of a message to
992     the appropriate sudo debug level.  Note however, that sudo debug system
993     will only get the messages not filtered out by the Python loggers.  For
994     example, the log level of the python logger will be an additional filter
995     for the log messages, and is usually very different from what level is
996     set in sudo.conf for the sudo debug system.
997
998   Debug example
999     Sudo ships an example debug plugin by default.  To try it, register it by
1000     adding the following lines to /etc/sudo.conf:
1001
1002           Plugin python_io python_plugin.so \
1003               ModulePath=/usr/share/doc/sudo/examples/example_debugging.py \
1004               ClassName=DebugDemoPlugin
1005
1006           Debug python_plugin.so \
1007               /var/log/sudo_python_debug plugin@trace,c_calls@trace
1008
1009   Option conversion API
1010     The Python plugin API includes two convenience functions to convert
1011     options in “key=value” format to a dictionary and vice versa.
1012
1013     options_as_dict
1014           options_as_dict(options)
1015
1016           The function arguments are as follows:
1017
1018           options
1019                 An iterable (tuple, list, etc.) of strings, each in
1020                 “key=value” format.  This is how the plugin API passes
1021                 options and settings to a Python plugin.
1022
1023           The function returns the resulting dictionary.  Each string of the
1024           passed in options will be split at the first equal sign (‘=’) into
1025           a key and value.  Dictionary keys will never contain this symbol
1026           (but values may).
1027
1028     options_from_dict
1029           options_from_dict(options_dict)
1030
1031           The function arguments are as follows:
1032
1033           options_dict
1034                 A dictionary where both the key and the value are strings.
1035                 Note that the key should not contain an equal sign (‘=’),
1036                 otherwise the resulting string will have a different meaning.
1037                 However, this is not currently enforced.
1038
1039           The function returns a tuple containing the strings in “key=value”
1040           form for each key and value in the options_dict dictionary passed
1041           in.  This is how the plugin API accepts options and settings.
1042

PLUGIN API CHANGELOG (Python)

1044     None yet
1045

LIMITATIONS

1047     Only a maximum number of 8 python I/O plugins can be loaded at once.  If
1048     /etc/sudo.conf contains more, those will be rejected with a warning mes‐
1049     sage.
1050
1051     The Event API and the hook function API is currently not accessible for
1052     Python plugins.
1053

SEE ALSO

1055     sudo.conf(5), sudo_plugin(5), sudoers(5), sudo(8)
1056

AUTHORS

1058     Many people have worked on sudo over the years; this version consists of
1059     code written primarily by:
1060
1061           Todd C. Miller
1062
1063     See the CONTRIBUTORS file in the sudo distribution
1064     (https://www.sudo.ws/contributors.html) for an exhaustive list of people
1065     who have contributed to sudo.
1066

BUGS

1068     Python plugin support is currently considered experimental.
1069
1070     If you feel you have found a bug in sudo, please submit a bug report at
1071     https://bugzilla.sudo.ws/
1072

SECURITY CONSIDERATIONS

1074     All Python plugin handling is implemented inside the python_plugin.so
1075     dynamic plugin.  Therefore, if no Python plugin is registered in
1076     sudo.conf(5) or the sudoers file, sudo will not load the Python inter‐
1077     preter or the Python libraries.
1078
1079     By default, a Python plugin can only import Python modules which are
1080     owned by root and are only writable by the owner.  The reason for this is
1081     to prevent a file getting imported accidentally which is modifiable by a
1082     non-root user.  As sudo plugins run as root, accidentally importing such
1083     file would make it possible for any user (having write access) to execute
1084     any code with administrative rights.
1085
1086     However, during development of a plugin this might not be very conve‐
1087     nient.  The sudo.conf(5) developer_mode option can be used to disable it.
1088     For example:
1089           Set developer_mode true
1090
1091     Please note that this creates a security risk, so it is not recommended
1092     on critical systems such as a desktop machine for daily use, but is
1093     intended to be used in development environments (VM, container, etc).
1094     Before enabling developer mode, ensure you understand the implications.
1095

SUPPORT

1097     Limited free support is available via the sudo-users mailing list, see
1098     https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or search
1099     the archives.
1100

DISCLAIMER

1102     sudo is provided “AS IS” and any express or implied warranties, includ‐
1103     ing, but not limited to, the implied warranties of merchantability and
1104     fitness for a particular purpose are disclaimed.  See the LICENSE file
1105     distributed with sudo or https://www.sudo.ws/license.html for complete
1106     details.
1107
1108Sudo 1.9.0b4                   February 19, 2020                  Sudo 1.9.0b4
Impressum