Hallo, dies ist ein Test.
PWD: /www/data-lst1/unixsoft/unixsoft/kaempfer/.public_html
Running in File Mode
Relative path: ./../../../../../../sbin/../bin/compliance
Real path: /usr/bin/compliance
Zurück
#!/usr/bin/python3.9 -Es import solaris.no_site_packages """ # # Copyright (c) 2013, 2021, Oracle and/or its affiliates. # # # This program provides information about installed compliance # benchmarks and allows the user to verify against them # and generate result reports and compliance guides. """ import errno import fcntl import getopt import gettext import locale import os import os.path as path import rad.client import re import sys import textwrap import time # import compliance modules from compliance import common if common.command != "smf-service": # assess and report (indirectly) modules can generate noise in smf log from compliance import assess from compliance import report from compliance import match from compliance import roster from compliance import smf_util from compliance import tailor from compliance import xccdf_util from compliance import benchmark import rad.bindings.com.oracle.solaris.rad.compliance_mgr_1 as radcompliance _ = gettext.gettext # Namespace simplification for certain names in compliance.common create_shared_dirs = common.create_shared_dirs fatal = common.fatal getmtime = common.getmtime strjoin = common.strjoin ComplianceError = common.ComplianceError COMPLIANCE_RAD_ERRORS = common.COMPLIANCE_RAD_ERRORS def usage(m): """print a usage message and terminate""" f = sys.stderr p = common.progname sys.stdout.flush() if m: print(m, file=f) if common.command == "assess": print(_("Usage:" "\t%(p)s assess [-p profile] [-b benchmark] " "[-m matches]\n" "\t\t[-a assessment] [-s store-URI] [-N node-URI]\n" "\t%(p)s assess -t tailoring [-b benchmark] " "[-m matches]\n" "\t\t[-a assessment] [-s store-URI] [-N node-URI]\n" "\t%(p)s assess -r roster " "[-a assessment] [-s store-URI]") % {"p": p}, file=f) elif common.command == "delete": print(_("Usage:" "\t%s delete [-n] [-v] [-N node-URI] " "{-m matches | assessment}") % p, file=f) elif common.command == "get-options": print(_("Usage:" "\t%s get-options [-N node-URI]") % p, file=f) elif common.command == "get-policy": print(_("Usage:" "\t%s get-policy [-N node-URI]") % p, file=f) elif common.command == "guide": print(_("Usage:" "\t%(p)s guide [-p profile] [-b benchmark] [-o file]\n" "\t%(p)s guide -a") % {"p": p}, file=f) elif common.command == "explain": print(_("Usage:" "\t%s explain [-H] [-b benchmark] [-t tailoring]\n" "\t\t[-N node-URI] [all|<keyword> ...]") % p, file=f) elif common.command == "list": print(_("Usage:" "\t%(p)s list [-a] [-b] [-p] [-t] [-v] [-N node-URI]\n" "\t%(p)s list -b [-v] [-p [-N node-URI]] " "[benchmark ...]\n" "\t%(p)s list -a [-v] [-N node-URI] " "{-m matches | assessment ...}") % {"p": p}, file=f) elif common.command == "report": print(_("Usage:" "\t%s report [-f format] [-o file] " "{-m matches | -a assessment}") % p, file=f) elif common.command == "roster": print(_("Usage:" "\t%(p)s roster [-r roster] [subcommand]\n" "\t%(p)s roster -f commandfile\n" "\t%(p)s roster help [subcommand]") % {"p": p}, file=f) elif common.command == "set-options": print(_("Usage:" "\t%s set-options [-a assessment] [-m matches] " "[-s store-URI]\n\t[-N node-URI]") % p, file=f) elif common.command == "set-policy": print(_("Usage:" "\t%s set-policy [-b benchmark] [-p profile] " "[-t tailoring]\n\t[-N node-URI]") % p, file=f) elif common.command == "store": print(_("Usage:" "\t%s store [-n] [-v] [-s store-URI] " "{-m matches | assessment...}") % p, file=f) elif common.command == "tailor": print(_("Usage:" "\t%(p)s tailor [-t tailoring] [subcommand]\n" "\t%(p)s tailor -f commandfile\n" "\t%(p)s tailor help [subcommand]") % {"p": p}, file=f) else: print(_("Usage:" "\t%(p)s subcommand [argument]...\n" "\t%(p)s help [subcommand], \n" " where subcommand is one of assess, delete, explain, " "get-options, get-policy, \n\tguide, list, report, " "roster, set-options, set-policy, store, or tailor") % {"p": p}, file=f) exit(m and 1) def getcmdopt(options): """get options for the particular command""" try: opts, pargs = getopt.getopt(sys.argv[2:], options) except getopt.GetoptError as e: usage(e) return (opts, pargs) # # compliance list -b [-p] [-v] [benchmark...] # compliance list -a [-v] [-m matches] [assessment...] # compliance list -t # def do_list(): """perform list operation""" opts, pargs = getcmdopt("abm:N:prs:tv") opt_a = False opt_b = False opt_m = None opt_N = None opt_p = False opt_r = False opt_t = False opt_verbose = 0 for opt, arg in opts: if opt == '-a': opt_a = True elif opt == '-b': opt_b = True elif opt == '-m': opt_m = arg elif opt == '-N': opt_N = arg elif opt == '-p': opt_p = True elif opt == '-r': opt_r = True elif opt == '-s': # convenience synonym opt_N = arg elif opt == '-t': opt_t = True elif opt == '-v': opt_verbose += 1 if pargs: if not any((opt_b, opt_a)): usage(_("Extra arguments require -b or -a")) if opt_a and any((opt_b, opt_p)): usage(_("Extra arguments used with -a and either -b or -p")) if any((opt_m, opt_r, opt_t)): usage(_("Extra arguments can't be used with -m, -r, or -t")) # list benchmarks if any((opt_b, opt_p)) or not any((opt_a, opt_r, opt_t)): if not any((opt_b, opt_p)) or any((opt_a, opt_r, opt_t)): print(_("Benchmarks:")) benchmark.list_benchmarks(opt_p, opt_N, pargs, opt_verbose) # list assessments if opt_a or not any((opt_b, opt_p, opt_r, opt_t)): if not opt_a or any((opt_b, opt_p, opt_r, opt_t)): print(_("Assessments:")) assess.list_assessments(opt_verbose, opt_m, opt_N, pargs) # list tailorings if opt_t: if any((opt_a, opt_b, opt_p, opt_r)): print(_("Tailorings:")) tailor.list_tailorings(opt_N, opt_verbose) # list rosters if opt_r: if any((opt_a, opt_b, opt_p, opt_t)): print(_("Rosters:")) roster.list_rosters(opt_verbose) # # compliance guide [-a] [-p profile] [-b benchmark] [-o file] # def do_guide(): """perform guide operation""" opts, pargs = getcmdopt("ab:o:p:qv") opt_a = None opt_b = None opt_o = None opt_p = None opt_verbose = 0 for opt, arg in opts: if opt == '-a': opt_a = True if opt == '-b': opt_b = arg elif opt == '-o': opt_o = arg elif opt == '-p': opt_p = arg elif opt == '-v': opt_verbose += 1 if not common.service and len(pargs) > 0: usage(_("Unrecognized parameters specified")) if opt_a and (opt_b or opt_o or opt_p): usage(_("Option -a cannot be used with other options")) guides_locked = [] def lock_guides(): """lock guide generation against simultaneous updates""" if guides_locked: return lock = path.join(common.GUIDES, ".lock") try: lockf = open(lock, 'w') fcntl.lockf(lockf.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB, 1, 1, 0) guides_locked.append(True) except EnvironmentError as exc: # no service error fatal(common.serviceOK(1), _("Cannot lock guides storage: %s") % str(exc)) def guide_path(benchmark, profile): """generate pathname for a guide in repository""" gfile = benchmark if profile: gfile += "." + profile gfile += ".html" return path.join(common.GUIDES, gfile) def gen_guide(xccdf, profile, gfile): """generate guide""" myargv = [common.OSCAP, "xccdf", "generate"] myargv.append("guide") if profile: myargv.extend(["--profile", profile]) myargv.extend(["--output", gfile, xccdf]) if opt_verbose: print(("+ %s %s" % (myargv[0], strjoin(" ", myargv[1:], "'"))), file=sys.stderr) status = os.spawnv(os.P_WAIT, myargv[0], myargv) return os.WIFEXITED(status) and os.WEXITSTATUS(status) == 0 if opt_a or common.service: # # process all installed benchmarks and associated profiles # as a service process, silently give up # if we can't create directories or lock guides # if not path.isdir(common.GUIDES): create_shared_dirs(common.GUIDES, "guides") lock_guides() benchmarks = xccdf_util.bench_list() for benchmark in benchmarks: xccdf = xccdf_util.bench_path(benchmark) xccdftime = getmtime(xccdf, time.time()) guidefile = guide_path(benchmark, None) guidetime = getmtime(guidefile) if guidetime > xccdftime: if not common.service: print(guidefile) elif gen_guide(xccdf, None, guidefile): print(guidefile) else: continue collections = xccdf_util.xccdf_collect(filename=xccdf) for profile in collections.profiles: guidefile = guide_path(benchmark, profile) guidetime = getmtime(guidefile) if guidetime > xccdftime: if not common.service: print(guidefile) elif gen_guide(xccdf, profile, guidefile): print(guidefile) return # # generate a single guide specified by options # if not opt_b: opt_b = "solaris" xccdf = opt_b if not path.isabs(opt_b): xccdf = xccdf_util.bench_path(opt_b) if not path.isfile(xccdf): fatal(1, _("Benchmark tests file not found: %s") % xccdf) if opt_p: collections = xccdf_util.xccdf_collect(filename=xccdf) if opt_p not in collections.profiles: fatal(1, _("Benchmark %(b)s has no '%(p)s' profile") % {"b": opt_b, "p": opt_p}) if opt_o: guidefile = opt_o ruid = os.getuid() if os.geteuid() != ruid: # drop privileges before accessing user-specified pathname os.setreuid(ruid, ruid) else: if not path.isdir(common.GUIDES): create_shared_dirs(common.GUIDES, "guides") gfile = opt_b if opt_p: gfile += "." + opt_p gfile += ".html" guidefile = path.join(common.GUIDES, gfile) if not path.isfile(guidefile): lock_guides() if not opt_o and path.isfile(guidefile) or gen_guide(xccdf, opt_p, guidefile): print(guidefile) exit(0) else: print(_("Unable to create guide file: %s") % guidefile) exit(1) # # compliance assess [-p profile] [-b benchmark] [-a assessment] # def do_assess(): """perform assess operation""" opts, pargs = getcmdopt("a:b:m:N:p:qr:s:t:v") opt_a = None opt_b = None opt_m = None opt_N = None opt_p = None opt_q = False opt_r = None opt_s = None opt_t = None opt_verbose = 0 for opt, arg in opts: if opt == '-a': opt_a = arg elif opt == '-b': opt_b = arg elif opt == '-m': opt_m = arg elif opt == '-N': opt_N = arg elif opt == '-p': opt_p = arg elif opt == '-q': opt_q = True elif opt == '-r': opt_r = arg elif opt == '-s': opt_s = arg elif opt == '-t': opt_t = arg elif opt == '-v': opt_verbose += 1 if len(pargs) > 0: usage(_("Unrecognized parameters specified")) if opt_t and opt_p: usage(_("Option -t cannot be used with -p option")) if opt_r and any((opt_b, opt_m, opt_p, opt_t, opt_N)): usage(_("Option -r cannot be used with -b, -m, -p, -t, or -N options")) assess.run_assessment(opt_a, opt_b, opt_m, opt_N, opt_p, opt_q, opt_r, opt_s, opt_t, opt_verbose) # # compliance report [-f format] [-o outfile] [-v] [-m match] [-a assessment] # def do_report(): """perform report operation""" opts, pargs = getcmdopt("a:f:m:o:s:v") opt_a = None opt_f = None opt_m = None opt_o = None _opt_s = None opt_verbose = 0 for opt, arg in opts: if opt == '-a': opt_a = arg elif opt == '-f': opt_f = arg elif opt == '-m': opt_m = arg elif opt == '-o': opt_o = arg elif opt == '-s': _opt_s = arg # accept and ignore elif opt == '-v': opt_verbose += 1 if opt_a and opt_m: usage(_("Option -m cannot be used with -a option")) if len(pargs) > 0: usage(_("Unrecognized parameters specified")) report.report_assessments(opt_verbose, opt_f, opt_o, opt_m, opt_a) # # compliance delete assessment # def do_delete(): """perform delete operation""" opts, pargs = getcmdopt("m:N:nvs:") opt_m = None opt_N = None opt_n = False opt_verbose = 0 for opt, arg in opts: if opt == "-m": opt_m = arg if opt == "-N": opt_N = arg elif opt == "-n": opt_n = True elif opt == '-s': # convenience synonym opt_N = arg elif opt == "-v": opt_verbose += 1 assess.delete_assessments(opt_verbose, opt_m, opt_N, opt_n, pargs) # # compliance explain # def do_explain(): """List or explain known XCCF rules""" # Translators: 13 for the width of the 1st column, inc. whitespace list_fmt = _("{0:<13}{1}") def raiseincontext(msg, opt_N): """prepend node info to error message and raise""" if opt_N: raise ComplianceError("Node %s: %s" % (opt_N, msg)) else: raise ComplianceError("localnode: %s" % msg) def emit(rid, rtitle, desc): print(list_fmt.format(rid, rtitle) + "\n") desc_input = desc.split("\n") desc_paras = [""] for line in desc_input: if not line.strip(): desc_paras.append("") continue if not desc_paras[-1]: desc_paras[-1] = line.strip() else: desc_paras[-1] += " %s" % line.strip() for para in desc_paras: print(textwrap.fill( para, width=72, initial_indent=" " * 4, subsequent_indent=" " * 4)) print("\n") opt_b = None opt_t = "" opt_H = False opt_N = False opts, pargs = getcmdopt("b:t:HN:") for opt, arg in opts: if opt == "-b": opt_b = arg if opt == "-t": opt_t = arg if opt == "-H": opt_H = True if opt == "-N": opt_N = arg out = [] if not opt_b: opt_b = smf_util.get_policy(opt_N=opt_N)[0] try: rc = common.getRadConn(opt_N) except ComplianceError as exc: raiseincontext("compliance explain: %s" % str(exc), opt_N) try: all_names = rc.list_objects(radcompliance.Benchmark()) if opt_b not in [bench.name for bench in all_names]: fatal(1, _("Unknown benchmark '{0}'").format(opt_b)) for bench_name in all_names: if bench_name.name != opt_b: continue bm = rc.get_object(bench_name) descs = bm.get_descriptions(tailoring=opt_t) for desc in descs: out.append(( desc.ruleid, desc.title.replace("\n", " "), desc.description.strip())) rc.close() except rad.client.ObjectError as exc: raiseincontext("compliance explain: %s" % str(exc), opt_N) # sort the list by the rule id out.sort(key=lambda rule_tup: rule_tup[0]) try: if not pargs: if not opt_H: # Translators: # column headers, 1st defaults to 13 chars inc. wspace print(list_fmt.format(_("RULE ID"), _("TITLE"))) for rid, rtitle, desc in out: print(list_fmt.format(rid, rtitle)) else: for parg in pargs: for rid, rtitle, desc in out: if rid == parg: emit(rid, rtitle, desc) elif parg == "all": emit(rid, rtitle, desc) # note this is a simple substring match elif parg.lower() in desc.lower(): emit(rid, rtitle, desc) except IOError as e: if e.errno != errno.EPIPE: raise e # # compliance store assessment # def do_store(): """perform store operation""" opts, pargs = getcmdopt("m:ns:v") opt_m = None opt_n = False opt_s = None opt_verbose = 0 for opt, arg in opts: if opt == "-m": opt_m = arg elif opt == "-n": opt_n = True elif opt == "-s": opt_s = arg elif opt == "-v": opt_verbose += 1 if opt_s is None: opt_s = smf_util.get_option("store-URI") assess.store_assessments(opt_verbose, opt_m, opt_n, opt_s, pargs) def do_get_options(): """perform get-options operation""" opts, _pargs = getcmdopt("N:") opt_N = None for opt, arg in opts: if opt == '-N': opt_N = arg for (optname, OptName) in (("assessment", _("Assessment Name")), ("matches", _("Matches")), ("store-URI", _("Store-URI"))): optvalue = smf_util.get_option(optname, opt_N=opt_N) print(_("%(n)s:\t%(v)s") % {"n": OptName, "v": optvalue}) def do_set_options(): """perform set-options operation""" opts, pargs = getcmdopt("a:m:N:s:") opt_a = None opt_m = None opt_N = None opt_s = None for opt, arg in opts: if opt == '-a': opt_a = arg if opt == '-m': opt_m = arg if opt == '-N': opt_N = arg if opt == '-s': opt_s = arg if pargs: usage(_("Extra arguments for set-options")) realop = False if opt_a is not None: smf_util.set_option("assessment", opt_a, opt_N=opt_N) realop = True if opt_m is not None: try: match.parse_assessmatcharg(opt_m) except SyntaxError as exc: fatal(1, str(exc)) smf_util.set_option("matches", opt_m, opt_N=opt_N) realop = True if opt_s is not None: smf_util.set_option("store-URI", opt_s, opt_N=opt_N) realop = True if not realop: usage(_("No options parameters specified")) def do_get_policy(): """perform get-policy operation""" opts, _pargs = getcmdopt("N:") opt_N = None for opt, arg in opts: if opt == '-N': opt_N = arg (benchmark, profile, tailoring) = smf_util.get_policy(opt_N=opt_N) print(_("Benchmark:\t%s") % benchmark) print(_("Profile:\t%s") % profile) print(_("Tailoring:\t%s") % tailoring) def do_set_policy(): """perform set-policy operation""" opts, pargs = getcmdopt("b:N:p:t:") opt_b = "" opt_N = None opt_p = "" opt_t = "" for opt, arg in opts: if opt == '-b': opt_b = arg if opt == '-N': opt_N = arg if opt == '-p': opt_p = arg if opt == '-t': opt_t = arg if pargs: usage(_("Extra arguments for set-policy")) if not any((opt_b, opt_p, opt_t)): usage(_("No policy parameters specified")) if opt_p: if opt_t: usage(_("Option -t cannot be used with -p")) elif not opt_b: usage(_("Option -p cannot be used without -b")) # validate parameters for defaults if opt_t: try: tailor.defaults_validate(opt_b, opt_t, opt_N) except ComplianceError as exc: fatal(1, str(exc)) elif opt_b: try: benchmark.defaults_validate(opt_b, opt_p, opt_N) except ComplianceError as exc: fatal(1, str(exc)) smf_util.set_policy(opt_b, opt_p, opt_t, opt_N=opt_N) def do_service(): """perform service operation (guide generation)""" if not os.environ.get("SMF_FMRI"): fatal(1, _("Service functionality invoked outside service context")) if len(sys.argv) < 2: fatal(1, _("Service method not specified")) common.service = sys.argv[2] if common.service not in ("start", "refresh"): fatal(1, _("Invalid service method: %s") % common.service) do_guide() def do_assess_target(): """invoke RAD slave exec'ed target assessment""" assess.assess_target() # # # main program # try: locale.setlocale(locale.LC_ALL, "") except locale.Error: pass gettext.textdomain("compliance") if len(sys.argv) == 1: usage(_("No command specified")) # # main program dispatch # commands = {"assess": do_assess, "assess_target": do_assess_target, "delete": do_delete, "get-options": do_get_options, "get-policy": do_get_policy, "guide": do_guide, "explain": do_explain, "list": do_list, "report": do_report, "roster": roster.do_roster, "set-options": do_set_options, "set-policy": do_set_policy, "store": do_store, "tailor": tailor.do_tailor, "smf-service": do_service} if common.command in commands: try: commands[common.command]() except rad.client.NotFoundError as exc: # We handle the NotFoundError specially, as it might indicate that # we're trying to do multi-node compliance operations on a remote # system which does not support multi-node (e.g. Solaris 11.3) fatal(1, _( "Multi-node compliance may not be supported or enabled: %s") % exc) except COMPLIANCE_RAD_ERRORS as rad_exc: fatal(1, _("Problem communicating with RAD daemon: %s") % rad_exc) elif re.search("help", common.command, re.IGNORECASE): if len(sys.argv) > 2: common.command = sys.argv[2] usage(None) else: usage(_("Command '%s' not recognized") % common.command) exit(common.exit_val)