pvl/args.py
author Tero Marttila <terom@paivola.fi>
Wed, 01 May 2013 00:22:58 +0300
changeset 13 69a35866264b
parent 10 08bb817a9966
child 15 e699ed00fcf1
permissions -rw-r--r--
MIT License
1
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
     1
"""
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
     2
    CLI argument handling; common stuff: logging
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
     3
"""
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
     4
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
     5
import optparse
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
     6
import logging
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
     7
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
     8
import pwd, grp, os, sys
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
     9
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    10
import logging; log = logging.getLogger('pvl.args')
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    11
9
5e9290c55d77 pvl.args: make setuid options optional
Tero Marttila <terom@paivola.fi>
parents: 1
diff changeset
    12
def parser (parser, setuid=None) :
1
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    13
    """
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    14
        Return an optparse.OptionGroup.
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    15
    """
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    16
9
5e9290c55d77 pvl.args: make setuid options optional
Tero Marttila <terom@paivola.fi>
parents: 1
diff changeset
    17
    if setuid is None :
5e9290c55d77 pvl.args: make setuid options optional
Tero Marttila <terom@paivola.fi>
parents: 1
diff changeset
    18
        # autodetect: only if we will be capable of
5e9290c55d77 pvl.args: make setuid options optional
Tero Marttila <terom@paivola.fi>
parents: 1
diff changeset
    19
        # XXX: use linux capabilities?
5e9290c55d77 pvl.args: make setuid options optional
Tero Marttila <terom@paivola.fi>
parents: 1
diff changeset
    20
        setuid = (os.geteuid() == 0)
5e9290c55d77 pvl.args: make setuid options optional
Tero Marttila <terom@paivola.fi>
parents: 1
diff changeset
    21
1
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    22
    general = optparse.OptionGroup(parser, "General options")
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    23
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    24
    general.add_option('-q', '--quiet',     dest='loglevel', action='store_const', const=logging.ERROR, help="Less output")
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    25
    general.add_option('-v', '--verbose',   dest='loglevel', action='store_const', const=logging.INFO,  help="More output")
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    26
    general.add_option('-D', '--debug',     dest='loglevel', action='store_const', const=logging.DEBUG, help="Even more output")
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    27
    general.add_option('--log-file',                                                                    help="Log to file")
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    28
    general.add_option('--debug-module',    action='append', metavar='MODULE', 
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    29
            help="Enable logging for the given logger/module name")
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    30
    
9
5e9290c55d77 pvl.args: make setuid options optional
Tero Marttila <terom@paivola.fi>
parents: 1
diff changeset
    31
    if setuid :
5e9290c55d77 pvl.args: make setuid options optional
Tero Marttila <terom@paivola.fi>
parents: 1
diff changeset
    32
        general.add_option('--uid',             help="Change uid")
5e9290c55d77 pvl.args: make setuid options optional
Tero Marttila <terom@paivola.fi>
parents: 1
diff changeset
    33
        general.add_option('--gid',             help="Change gid")
1
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    34
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    35
    # defaults
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    36
    parser.set_defaults(
10
08bb817a9966 pvl.args: fix optional setuid options
Tero Marttila <terom@paivola.fi>
parents: 9
diff changeset
    37
        _setuid             = setuid,
1
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    38
        logname             = parser.prog,
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    39
        loglevel            = logging.WARN,
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    40
        debug_module        = [],
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    41
    )
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    42
 
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    43
    return general
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    44
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    45
def options (**options) :
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    46
    """
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    47
        Synthensise options.
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    48
    """
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    49
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    50
    return optparse.Values(options)
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    51
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    52
def apply_setid (options, rootok=None) :
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    53
    """
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    54
        Drop privileges if running as root.
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    55
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    56
        XXX: this feature isn't very useful (import-time issues etc), but in certain cases (syslog-ng -> python),
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    57
        it's difficult to avoid this without some extra wrapper tool..?
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    58
    """
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    59
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    60
    # --uid -> pw
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    61
    if not options.uid :
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    62
        pw = None
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    63
    elif options.uid.isdigit() :
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    64
        pw = pwd.getpwuid(int(options.uid))
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    65
    else :
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    66
        pw = pwd.getpwnam(options.uid)
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    67
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    68
    # --gid -> gr
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    69
    if not options.gid and not pw :
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    70
        gr = None
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    71
    elif not options.gid :
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    72
        gr = grp.getgrgid(pw.pw_gid)
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    73
    elif options.gid.isdigit() :
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    74
        gr = grp.getgrgid(str(options.gid))
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    75
    else :
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    76
        gr = grp.getgrnam(options.gid)
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    77
    
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    78
    if gr :
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    79
        # XXX: secondary groups? seem to get cleared
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    80
        log.info("setgid: %s: %s", gr.gr_name, gr.gr_gid)
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    81
        os.setgid(gr.gr_gid)
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    82
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    83
    if pw :
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    84
        log.info("setuid: %s: %s", pw.pw_name, pw.pw_uid)
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    85
        os.setuid(pw.pw_uid)
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    86
    
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    87
    elif os.getuid() == 0 :
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    88
        if rootok :
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    89
            log.info("running as root")
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    90
        else :
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    91
            log.error("refusing to run as root, use --uid 0 to override")
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    92
            sys.exit(2)
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    93
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    94
def apply (options, logname=None, rootok=True) :
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    95
    """
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    96
        Apply the optparse options.
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    97
    """
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    98
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    99
    if logname :
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   100
        prefix = options.logname + ': '
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   101
    else :
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   102
        prefix = ''
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   103
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   104
    # configure
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   105
    logging.basicConfig(
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   106
        # XXX: log Class.__init__ as Class, not __init__?
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   107
        format      = prefix + '%(name)-20s: %(levelname)5s %(funcName)s: %(message)s',
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   108
        level       = options.loglevel,
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   109
        filename    = options.log_file,
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   110
    )
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   111
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   112
    # TODO: use --quiet for stdout output?
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   113
    options.quiet = options.loglevel > logging.WARN
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   114
    
10
08bb817a9966 pvl.args: fix optional setuid options
Tero Marttila <terom@paivola.fi>
parents: 9
diff changeset
   115
    if options._setuid :
08bb817a9966 pvl.args: fix optional setuid options
Tero Marttila <terom@paivola.fi>
parents: 9
diff changeset
   116
        if options.uid or options.gid or not rootok :
08bb817a9966 pvl.args: fix optional setuid options
Tero Marttila <terom@paivola.fi>
parents: 9
diff changeset
   117
            # set uid/gid
08bb817a9966 pvl.args: fix optional setuid options
Tero Marttila <terom@paivola.fi>
parents: 9
diff changeset
   118
            apply_setid(options, rootok=rootok)
1
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   119
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   120
    # enable debugging for specific targets
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   121
    for logger in options.debug_module :
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   122
        logging.getLogger(logger).setLevel(logging.DEBUG)
ce931075b69e import pvl.args,invoke from pvl-verkko
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   123