1CVTSUDOERS(1) BSD General Commands Manual CVTSUDOERS(1)
2
4 cvtsudoers — convert between sudoers file formats
5
7 cvtsudoers [-ehMpV] [-b dn] [-c conf_file] [-d deftypes]
8 [-f output_format] [-i input_format] [-I increment]
9 [-l log_file] [-m filter] [-o output_file] [-O start_point]
10 [-P padding] [-s sections] [input_file ...]
11
13 The cvtsudoers utility accepts one or more security policies in either
14 sudoers or LDIF format as input, and generates a single policy of the
15 specified format as output. The default input format is sudoers. The de‐
16 fault output format is LDIF. It is only possible to convert a policy
17 file that is syntactically correct.
18
19 If no input_file is specified, or if it is ‘-’, the policy is read from
20 the standard input. Input files may be optionally prefixed with a host
21 name followed by a colon (‘:’) to make the policy rules specific to a
22 host when merging multiple files. By default, the result is written to
23 the standard output.
24
25 The options are as follows:
26
27 -b dn, --base=dn
28 The base DN (distinguished name) that will be used when perform‐
29 ing LDAP queries. Typically this is of the form
30 “ou=SUDOers,dc=my-domain,dc=com” for the domain my-domain.com.
31 If this option is not specified, the value of the SUDOERS_BASE
32 environment variable will be used instead. Only necessary when
33 converting to LDIF format.
34
35 -c conf_file, --config=conf_file
36 Specify the path to the configuration file. Defaults to
37 /etc/cvtsudoers.conf.
38
39 -d deftypes, --defaults=deftypes
40 Only convert Defaults entries of the specified types. One or
41 more Defaults types may be specified, separated by a comma (‘,’).
42 The supported types are:
43
44 all All Defaults entries.
45
46 global Global Defaults entries that are applied regardless of
47 user, runas, host, or command.
48
49 user Per-user Defaults entries.
50
51 runas Per-runas user Defaults entries.
52
53 host Per-host Defaults entries.
54
55 command Per-command Defaults entries.
56
57 See the Defaults section in sudoers(5) for more information.
58
59 If the -d option is not specified, all Defaults entries will be
60 converted.
61
62 -e, --expand-aliases
63 Expand aliases in input_file. Aliases are preserved by default
64 when the output format is JSON or sudoers.
65
66 -f output_format, --output-format=output_format
67 Specify the output format (case-insensitive). The following for‐
68 mats are supported:
69
70 CSV CSV (comma-separated value) files are often used by
71 spreadsheets and report generators. See CSV output
72 format for more details.
73
74 JSON JSON (JavaScript Object Notation) files are usually eas‐
75 ier for third-party applications to consume than the
76 traditional sudoers format. The various values have ex‐
77 plicit types which removes much of the ambiguity of the
78 sudoers format. See JSON output format for more de‐
79 tails.
80
81 LDIF LDIF (LDAP Data Interchange Format) files can be im‐
82 ported into an LDAP server for use with sudoers.ldap(5).
83
84 Conversion to LDIF has the following limitations:
85
86 • Command, host, runas, and user-specific Defaults
87 lines cannot be translated as they don't have an
88 equivalent in the sudoers LDAP schema.
89
90 • Command, host, runas, and user aliases are not sup‐
91 ported by the sudoers LDAP schema so they are ex‐
92 panded during the conversion.
93
94 sudoers Traditional sudoers format. A new sudoers file will be
95 reconstructed from the parsed input file. Comments are
96 not preserved and data from any include files will be
97 output inline.
98
99 --group-file=file
100 When the -M option is also specified, perform group queries using
101 file instead of the system group database.
102
103 -h, --help
104 Display a short help message to the standard output and exit.
105
106 -i input_format, --input-format=input_format
107 Specify the input format. The following formats are supported:
108
109 LDIF LDIF (LDAP Data Interchange Format) files can be ex‐
110 ported from an LDAP server to convert security policies
111 used by sudoers.ldap(5). If a base DN (distinguished
112 name) is specified, only sudoRole objects that match the
113 base DN will be processed. Not all sudoOptions speci‐
114 fied in a sudoRole can be translated from LDIF to sudo‐
115 ers format.
116
117 sudoers Traditional sudoers format. This is the default input
118 format.
119
120 -I increment, --increment=increment
121 When generating LDIF output, increment each sudoOrder attribute
122 by the specified number. Defaults to an increment of 1.
123
124 -l log_file, --logfile=log_file
125 Log conversion warnings to log_file instead of to the standard
126 error. This is particularly useful when merging multiple sudoers
127 files, which can generate a large number of warnings.
128
129 -m filter, --match=filter
130 Only output rules that match the specified filter. A filter ex‐
131 pression is made up of one or more key = value pairs, separated
132 by a comma (‘,’). The key may be “cmnd” (or “cmd”), “host”,
133 “group”, or “user”. For example, user = operator or host = www.
134 An upper-case Cmnd_Alias, Host_alias, or User_Alias may be speci‐
135 fied as the “cmnd”, “host”, or “user”.
136
137 A matching sudoers rule may also include users, groups, and hosts
138 that are not part of the filter. This can happen when a rule in‐
139 cludes multiple users, groups, or hosts. To prune out any non-
140 matching user, group, or host from the rules, the -p option may
141 be used.
142
143 By default, the password and group databases are not consulted
144 when matching against the filter so the users and groups do not
145 need to be present on the local system (see the -M option). Only
146 aliases that are referenced by the filtered policy rules will be
147 displayed.
148
149 -M, --match-local
150 When the -m option is also specified, use password and group
151 database information when matching users and groups in the fil‐
152 ter. Only users and groups in the filter that exist on the local
153 system will match, and a user's groups will automatically be
154 added to the filter. If the -M is not specified, users and
155 groups in the filter do not need to exist on the local system,
156 but all groups used for matching must be explicitly listed in the
157 filter.
158
159 -o output_file, --output=output_file
160 Write the converted output to output_file. If no output_file is
161 specified, or if it is ‘-’, the converted sudoers policy will be
162 written to the standard output.
163
164 -O start_point, --order-start=start_point
165 When generating LDIF output, use the number specified by
166 start_point in the sudoOrder attribute of the first sudoRole ob‐
167 ject. Subsequent sudoRole object use a sudoOrder value generated
168 by adding an increment, see the -I option for details. Defaults
169 to a starting point of 1. A starting point of 0 will disable the
170 generation of sudoOrder attributes in the resulting LDIF file.
171
172 --passwd-file=file
173 When the -M option is also specified, perform passwd queries us‐
174 ing file instead of the system passwd database.
175
176 -p, --prune-matches
177 When the -m option is also specified, cvtsudoers will prune out
178 non-matching users, groups, and hosts from matching entries.
179
180 -P padding, --padding=padding
181 When generating LDIF output, construct the initial sudoOrder
182 value by concatenating order_start and increment, padding the
183 increment with zeros until it consists of padding digits. For
184 example, if order_start is 1027, padding is 3, and increment is
185 1, the value of sudoOrder for the first entry will be 1027000,
186 followed by 1027001, 1027002, etc. If the number of sudoRole en‐
187 tries is larger than the padding would allow, cvtsudoers will
188 exit with an error. By default, no padding is performed.
189
190 -s sections, --suppress=sections
191 Suppress the output of specific sections of the security policy.
192 One or more section names may be specified, separated by a comma
193 (‘,’). The supported section name are: defaults, aliases and
194 privileges (which may be shortened to privs).
195
196 -V, --version
197 Print the cvtsudoers and sudoers grammar versions and exit.
198
199 Merging multiple files
200 When multiple input files are specified, cvtsudoers will attempt to merge
201 them into a single policy file. It is assumed that user and group names
202 are consistent among the policy files to be merged. For example, user
203 “bob” on one host is the same as user “bob” on another host.
204
205 When merging policy files, it is possible to prefix the input file name
206 with a host name, separated by a colon (‘:’). When the files are merged,
207 the host name will be used to restrict the policy rules to that specific
208 host where possible.
209
210 The merging process is performed as follows:
211
212 • Each input file is parsed into internal sudoers data structures.
213
214 • Aliases are merged and renamed as necessary to avoid conflicts. In
215 the event of a conflict, the first alias found is left as-is and sub‐
216 sequent aliases of the same name are renamed with a numeric suffix
217 separated with a underscore (‘_’). For example, if there are two dif‐
218 ferent aliases named SERVERS, the first will be left as-is and the
219 second will be renamed SERVERS_1. References to the renamed alias are
220 also updated in the policy file. Duplicate aliases (those with iden‐
221 tical contents) are pruned.
222
223 • Defaults settings are merged and duplicates are removed. If there are
224 conflicts in the Defaults settings, a warning is emitted for each con‐
225 flict. If a host name is specified with the input file, cvtsudoers
226 will change the global Defaults settings in that file to be host-spe‐
227 cific. A warning is emitted for command, user, or runas-specific De‐
228 faults settings which cannot be made host-specific.
229
230 • Per-user rules are merged and duplicates are removed. If a host name
231 is specified with the input file, cvtsudoers will change rules that
232 specify a host name of ALL to the host name associated with the policy
233 file being merged. The merging of rules is currently fairly simplis‐
234 tic but will be improved in a later release.
235
236 It is possible to merge policy files with differing formats.
237
238 The cvtsudoers.conf file
239 Options in the form “keyword = value” may also be specified in a configu‐
240 ration file, /etc/cvtsudoers.conf by default. The following keywords are
241 recognized:
242
243 defaults = deftypes
244 See the description of the -d command line option.
245
246 expand_aliases = yes | no
247 See the description of the -e command line option.
248
249 group_file = file
250 See the description of the --group-file command line option.
251
252 input_format = ldif | sudoers
253 See the description of the -i command line option.
254
255 match = filter
256 See the description of the -m command line option.
257
258 match_local = yes | no
259 See the description of the -M command line option.
260
261 order_increment = increment
262 See the description of the -I command line option.
263
264 order_start = start_point
265 See the description of the -O command line option.
266
267 output_format = csv | json | ldif | sudoers
268 See the description of the -f command line option.
269
270 padding = padding
271 See the description of the -P command line option.
272
273 passwd_file = file
274 See the description of the --passwd-file command line option.
275
276 prune_matches = yes | no
277 See the description of the -p command line option.
278
279 sudoers_base = dn
280 See the description of the -b command line option.
281
282 suppress = sections
283 See the description of the -s command line option.
284
285 Options on the command line will override values from the configuration
286 file.
287
288 JSON output format
289 The sudoers JSON format may contain any of the following top-level ob‐
290 jects:
291
292 Defaults
293 An array of objects, each containing an Options array and an op‐
294 tional Binding array.
295
296 The Options array consists of one or more objects, each containing
297 a “name:value” pair that corresponds to a sudoers Defaults setting.
298 Options that operate on a list will also include an operation entry
299 in the object, with a value of “list_assign” for ‘=’, “list_add”
300 for ‘+=’, or “list_remove” for ‘-=’.
301
302 The optional Binding array consists of one or more objects, each
303 containing a “name:value” pair and an optional negated entry, which
304 will negate any comparison performed with the object. If a Binding
305 is present, the setting will only take effect if one of the speci‐
306 fied command, hostname, netgroup, networkaddr, nonunixgid,
307 nonunixgroup, usergid, usergroup, userid, username, or alias en‐
308 tries match.
309
310 For example, the following sudoers entry:
311
312 Defaults@somehost set_home, env_keep += DISPLAY
313
314 converts to:
315
316 "Defaults": [
317 {
318 "Binding": [
319 { "hostname": "somehost" }
320 ],
321 "Options": [
322 { "set_home": true },
323 {
324 "operation": "list_add",
325 "env_keep": [
326 "DISPLAY"
327 ]
328 }
329 ]
330 }
331 ]
332
333 User_Aliases
334 A JSON object containing one or more sudoers User_Alias entries
335 where each named alias has as its value an array containing one or
336 more objects. Each object contains a “name:value” pair and an op‐
337 tional negated entry, which will negate any comparison performed
338 with the object. The name may be one of netgroup, nonunixgid,
339 nonunixgroup, useralias, usergid, usergroup, userid, or username.
340
341 For example, the following sudoers entry:
342
343 User_Alias SYSADMIN = will, %wheel, +admin
344
345 converts to:
346
347 "User_Aliases": {
348 "SYSADMIN": [
349 { "username": "will" },
350 { "usergroup": "wheel" },
351 { "netgroup": "admin" }
352 ]
353 }
354
355 Runas_Aliases
356 A JSON object containing one or more sudoers Runas_Alias entries,
357 where each named alias has as its value an array containing one or
358 more objects. Each object contains a “name:value” pair and an op‐
359 tional negated entry, which will negate any comparison performed
360 with the object. The name may be one of netgroup, nonunixgid,
361 nonunixgroup, runasalias, usergid, usergroup, userid, or username.
362
363 For example, the following sudoers entry:
364
365 Runas_Alias DB = oracle, sybase : OP = root, operator
366
367 converts to:
368
369 "Runas_Aliases": {
370 "DB": [
371 { "username": "oracle" },
372 { "username": "sybase" }
373 ],
374 "OP": [
375 { "username": "root" },
376 { "username": "operator" }
377 ]
378 }
379
380 Host_Aliases
381 A JSON object containing one or more sudoers Host_Alias entries
382 where each named alias has as its value an array containing one or
383 more objects. Each object contains a “name:value” pair and an op‐
384 tional negated entry, which will negate any comparison performed
385 with the object. The name may be one of hostalias, hostname,
386 netgroup, or networkaddr.
387
388 For example, the following sudoers entries:
389
390 Host_Alias DORMNET = 128.138.243.0, 128.138.204.0/24
391 Host_Alias SERVERS = boulder, refuge
392
393 convert to:
394
395 "Host_Aliases": {
396 "DORMNET": [
397 { "networkaddr": "128.138.243.0" },
398 { "networkaddr": "128.138.204.0/24" }
399 ],
400 "SERVERS": [
401 { "hostname": "boulder" },
402 { "hostname": "refuge" }
403 ]
404 }
405
406 Cmnd_Aliases
407 A JSON object containing one or more sudoers Cmnd_Alias entries
408 where each named alias has as its value an array containing one or
409 more objects. Each object contains a “name:value” pair and an op‐
410 tional negated entry, which will negate any comparison performed
411 with the object. The name may be either another cmndalias or a
412 command. For example, the following sudoers entries:
413
414 Cmnd_Alias SHELLS = /bin/bash, /bin/csh, /bin/sh, /bin/zsh
415 Cmnd_Alias VIPW = /usr/bin/chpass, /usr/bin/chfn, /usr/bin/chsh, \
416 /usr/bin/passwd, /usr/sbin/vigr, /usr/sbin/vipw
417
418 convert to:
419
420 "Cmnd_Aliases": {
421 "SHELLS": [
422 { "command": "/bin/bash" },
423 { "command": "/bin/csh" },
424 { "command": "/bin/sh" },
425 { "command": "/bin/zsh" }
426 ],
427 "VIPW": [
428 { "command": "/usr/bin/chpass" },
429 { "command": "/usr/bin/chfn" },
430 { "command": "/usr/bin/chsh" },
431 { "command": "/usr/bin/passwd" },
432 { "command": "/usr/sbin/vigr" },
433 { "command": "/usr/sbin/vipw" }
434 ]
435 }
436
437 User_Specs
438 A JSON array containing one or more objects, each representing a
439 sudoers User_Spec. Each object in the User_Specs array should con‐
440 tain a User_List array, a Host_List array and a Cmnd_Specs array.
441
442 A User_List consists of one or more objects. Each object contains
443 a “name:value” pair and an optional negated entry, which will
444 negate any comparison performed with the object. The name may be
445 one of netgroup, nonunixgid, nonunixgroup, useralias, usergid,
446 usergroup, userid, or username. If username is set to the special
447 value ALL, it will match any user.
448
449 A Host_List consists of one or more objects. Each object contains
450 a “name:value” pair and an optional negated entry, which will
451 negate any comparison performed with the object. The name may be
452 one of hostalias, hostname, netgroup, or networkaddr. If hostname
453 is set to the special value ALL, it will match any host.
454
455 The Cmnd_Specs array consists of one or more JSON objects describ‐
456 ing a command that may be run. Each Cmnd_Specs is made up of a
457 Commands array, an optional runasusers array, an optional
458 runasgroups array, and an optional Options array.
459
460 The Commands array consists of one or more objects containing
461 “name:value” pair elements. The following names and values are
462 supported:
463
464 command A string containing the command to run. The special value
465 ALL it will match any command.
466
467 negated A boolean value that, if true, will negate any comparison
468 performed with the object.
469
470 sha224 A string containing the SHA224 digest of the command.
471
472 sha256 A string containing the SHA256 digest of the command.
473
474 sha384 A string containing the SHA384 digest of the command.
475
476 sha512 A string containing the SHA512 digest of the command.
477
478 The runasusers array consists of objects describing users the com‐
479 mand may be run as. Each object contains a “name:value” pair and
480 an optional negated entry, which will negate any comparison per‐
481 formed with the object. The name may be one of netgroup,
482 nonunixgid, nonunixgroup, runasalias, usergid, usergroup, userid,
483 or username. If username is set to the special value ALL, it will
484 match any user. If username is set to the empty string “”, it will
485 match the invoking user.
486
487 The runasgroups array consists of objects describing groups the
488 command may be run as. Each object contains a “name:value” pair
489 and an optional negated entry, which will negate any comparison
490 performed with the object. The name may be one of runasalias,
491 usergid, or usergroup. If usergroup is set to the special value
492 ALL, it will match any group.
493
494 The Options array is of the same format as the one in the Defaults
495 object. Any Tag_Spec entries in sudoers are converted to Options.
496 A user with “sudo ALL” privileges will automatically have the
497 setenv option enabled to match the implicit behavior provided by
498 sudoers.
499
500 For example, the following sudoers entry:
501
502 millert ALL = (ALL : ALL) NOPASSWD: ALL, !/usr/bin/id
503
504 converts to:
505
506 "User_Specs": [
507 {
508 "User_List": [
509 { "username": "millert" }
510 ],
511 "Host_List": [
512 { "hostname": "ALL" }
513 ],
514 "Cmnd_Specs": [
515 {
516 "runasusers": [
517 { "username": "ALL" }
518 ],
519 "runasgroups": [
520 { "usergroup": "ALL" }
521 ],
522 "Options": [
523 { "authenticate": false },
524 { "setenv": true }
525 ],
526 "Commands": [
527 { "command": "ALL" },
528 {
529 "command": "/usr/bin/id",
530 "negated": true
531 }
532 ]
533 }
534 ]
535 }
536 ]
537
538 CSV output format
539 CSV (comma-separated value) files are often used by spreadsheets and re‐
540 port generators. For CSV output, cvtsudoers double quotes strings that
541 contain commas. For each literal double quote character present inside
542 the string, two double quotes are output. This method of quoting commas
543 is compatible with most spreadsheet programs.
544
545 There are three possible sections in cvtsudoers's CSV output, each sepa‐
546 rated by a blank line:
547
548 defaults
549 This section includes any Defaults settings in sudoers. The
550 defaults section begins with the following heading:
551
552 defaults_type,binding,name,operator,value
553
554 The fields are as follows:
555
556 defaults_type
557 The type of Defaults setting; one of defaults,
558 defaults_command, defaults_host, defaults_runas, or
559 defaults_user.
560
561 binding
562 For defaults_command, defaults_host, defaults_runas, and
563 defaults_user this is the value that must match for the set‐
564 ting to be applied.
565
566 name The name of the Defaults setting.
567
568 operator
569 The operator determines how the value is applied to the set‐
570 ting. It may be either ‘=’ (assignment), ‘+=’ (append), or
571 ‘-=’ (remove).
572
573 value
574 The setting's value, usually a string or, for settings used
575 in a boolean context, true or false.
576
577 aliases
578 This section includes any Cmnd_Alias Host_Alias, Runas_Alias, or
579 User_Alias, entries from sudoers. The aliases section begins with
580 the following heading:
581
582 alias_type,alias_name,members
583
584 The fields are as follows:
585
586 alias_type
587 The type of alias; one of Cmnd_Alias, Host_Alias,
588 Runas_Alias, or User_Alias.
589
590 alias_name
591 The name of the alias; a string starting with an upper-case
592 letter that consists of upper-case letters, digits, or under‐
593 scores.
594
595 members
596 A comma-separated list of members belonging to the alias.
597 Due to the use of commas, members is surrounded by double
598 quotes if it contains more than one member.
599
600 rules
601 This section includes the sudoers rules that grant privileges. The
602 rules section begins with the following heading:
603
604 rule,user,host,runusers,rungroups,options,command
605
606 The fields are as follows:
607
608 rule This field indicates a sudoers rule entry.
609
610 user The user the rule applies to. This may also be a Unix group
611 (preceded by a ‘%’ character), a non-Unix group (preceded by
612 ‘%:’) or a netgroup (preceded by a ‘+’ character) or a
613 User_Alias. If set to the special value ALL, it will match
614 any user.
615
616 host The host the rule applies to. This may also be a netgroup
617 (preceded by a ‘+’ character) or a Host_Alias. If set to the
618 special value ALL, it will match any host.
619
620 runusers
621 An optional comma-separated list of users (or Runas_Aliases)
622 the command may be run as. If it contains more than one mem‐
623 ber, the value is surrounded by double quotes. If set to the
624 special value ALL, it will match any user. If empty, the
625 root user is assumed.
626
627 rungroups
628 An optional comma-separated list of groups (or Runas_Aliases)
629 the command may be run as. If it contains more than one mem‐
630 ber, the value is surrounded by double quotes. If set to the
631 special value ALL, it will match any group. If empty, the
632 runuser's group is used.
633
634 options
635 An optional list of Defaults settings to apply to the com‐
636 mand. Any Tag_Spec entries in sudoers are converted to
637 options.
638
639 commands
640 A list of commands, with optional arguments, that the user is
641 allowed to run. If set to the special value ALL, it will
642 match any command.
643
644 For example, the following sudoers entry:
645
646 millert ALL = (ALL : ALL) NOPASSWD: ALL, !/usr/bin/id
647
648 converts to:
649
650 rule,millert,ALL,ALL,ALL,"!authenticate","ALL,!/usr/bin/id"
651
653 /etc/cvtsudoers.conf default configuration for cvtsudoers
654
656 Convert /etc/sudoers to LDIF (LDAP Data Interchange Format) where the
657 ldap.conf file uses a sudoers_base of my-domain,dc=com, storing the re‐
658 sult in sudoers.ldif:
659
660 $ cvtsudoers -b ou=SUDOers,dc=my-domain,dc=com -o sudoers.ldif \
661 /etc/sudoers
662
663 Convert /etc/sudoers to JSON format, storing the result in sudoers.json:
664
665 $ cvtsudoers -f json -o sudoers.json /etc/sudoers
666
667 Parse /etc/sudoers and display only rules that match user ambrose on host
668 hastur:
669
670 $ cvtsudoers -f sudoers -m user=ambrose,host=hastur /etc/sudoers
671
672 Same as above, but expand aliases and prune out any non-matching users
673 and hosts from the expanded entries.
674
675 $ cvtsudoers -ep -f sudoers -m user=ambrose,host=hastur /etc/sudoers
676
677 Convert sudoers.ldif from LDIF to traditional sudoers format:
678
679 $ cvtsudoers -i ldif -f sudoers -o sudoers.new sudoers.ldif
680
681 Merge a global sudoers file with two host-specific policy files from the
682 hosts “xyzzy” and “plugh”:
683
684 $ cvtsudoers -f sudoers -o sudoers.merged sudoers \
685 xyzzy:sudoers.xyzzy plugh:sudoers.plugh
686
688 sudoers(5), sudoers.ldap(5), sudo(8)
689
691 Many people have worked on sudo over the years; this version consists of
692 code written primarily by:
693
694 Todd C. Miller
695
696 See the CONTRIBUTORS.md file in the sudo distribution
697 (https://www.sudo.ws/about/contributors/) for an exhaustive list of peo‐
698 ple who have contributed to sudo.
699
701 If you believe you have found a bug in cvtsudoers, you can submit a bug
702 report at https://bugzilla.sudo.ws/
703
705 Limited free support is available via the sudo-users mailing list, see
706 https://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or search
707 the archives.
708
710 cvtsudoers is provided “AS IS” and any express or implied warranties, in‐
711 cluding, but not limited to, the implied warranties of merchantability
712 and fitness for a particular purpose are disclaimed. See the LICENSE.md
713 file distributed with sudo or https://www.sudo.ws/about/license/ for com‐
714 plete details.
715
716Sudo 1.9.13p2 January 16, 2023 Sudo 1.9.13p2