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