diff options
Diffstat (limited to 'dynamic-layers/meta-perl/recipes-security/bastille/files/set_required_questions.py')
| -rwxr-xr-x | dynamic-layers/meta-perl/recipes-security/bastille/files/set_required_questions.py | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/dynamic-layers/meta-perl/recipes-security/bastille/files/set_required_questions.py b/dynamic-layers/meta-perl/recipes-security/bastille/files/set_required_questions.py new file mode 100755 index 0000000..f306109 --- /dev/null +++ b/dynamic-layers/meta-perl/recipes-security/bastille/files/set_required_questions.py | |||
| @@ -0,0 +1,157 @@ | |||
| 1 | #!/usr/bin/env python3 | ||
| 2 | |||
| 3 | #Signed-off-by: Anne Mulhern <mulhern@yoctoproject.org> | ||
| 4 | |||
| 5 | import argparse, os, shutil, sys, tempfile, traceback | ||
| 6 | from os import path | ||
| 7 | |||
| 8 | |||
| 9 | |||
| 10 | def get_config(lines): | ||
| 11 | """ | ||
| 12 | From a sequence of lines retrieve the question file name, question identifier | ||
| 13 | pairs. | ||
| 14 | """ | ||
| 15 | for l in lines: | ||
| 16 | if not l.startswith("#"): | ||
| 17 | try: | ||
| 18 | (coord, value) = l.split("=") | ||
| 19 | try: | ||
| 20 | (fname, ident) = coord.split(".") | ||
| 21 | yield fname, ident | ||
| 22 | except ValueError as e: | ||
| 23 | raise ValueError("Badly formatted coordinates %s in line %s." % (coord, l.strip())) | ||
| 24 | except ValueError as e: | ||
| 25 | raise ValueError("Skipping badly formatted line %s, %s" % (l.strip(), e)) | ||
| 26 | |||
| 27 | |||
| 28 | |||
| 29 | def check_contains(line, name): | ||
| 30 | """ | ||
| 31 | Check if the value field for REQUIRE_DISTRO contains the given name. | ||
| 32 | @param name line The REQUIRE_DISTRO line | ||
| 33 | @param name name The name to look for in the value field of the line. | ||
| 34 | """ | ||
| 35 | try: | ||
| 36 | (label, distros) = line.split(":") | ||
| 37 | return name in distros.split() | ||
| 38 | except ValueError as e: | ||
| 39 | raise ValueError("Error splitting REQUIRE_DISTRO line: %s" % e) | ||
| 40 | |||
| 41 | |||
| 42 | |||
| 43 | def add_requires(the_ident, distro, lines): | ||
| 44 | |||
| 45 | """ | ||
| 46 | Yield a sequence of lines the same as lines except that where | ||
| 47 | the_ident matches a question identifier change the REQUIRE_DISTRO so that | ||
| 48 | it includes the specified distro. | ||
| 49 | |||
| 50 | @param name the_ident The question identifier to be matched. | ||
| 51 | @param name distro The distribution to added to the questions REQUIRE_DISTRO | ||
| 52 | field. | ||
| 53 | @param lines The sequence to be processed. | ||
| 54 | """ | ||
| 55 | for l in lines: | ||
| 56 | yield l | ||
| 57 | if l.startswith("LABEL:"): | ||
| 58 | try: | ||
| 59 | (label, ident) = l.split(":") | ||
| 60 | if ident.strip() == the_ident: | ||
| 61 | break | ||
| 62 | except ValueError as e: | ||
| 63 | raise ValueError("Unexpected line %s in questions file." % l.strip()) | ||
| 64 | for l in lines: | ||
| 65 | if l.startswith("REQUIRE_DISTRO"): | ||
| 66 | if not check_contains(l, distro): | ||
| 67 | yield l.rstrip() + " " + distro + "\n" | ||
| 68 | else: | ||
| 69 | yield l | ||
| 70 | break; | ||
| 71 | else: | ||
| 72 | yield l | ||
| 73 | for l in lines: | ||
| 74 | yield l | ||
| 75 | |||
| 76 | |||
| 77 | |||
| 78 | def xform_file(qfile, distro, qlabel): | ||
| 79 | """ | ||
| 80 | Transform a Questions file. | ||
| 81 | @param name qfile The designated questions file. | ||
| 82 | @param name distro The distribution to add to the required distributions. | ||
| 83 | @param name qlabel The question label for which the distro is to be added. | ||
| 84 | """ | ||
| 85 | questions_in = open(qfile) | ||
| 86 | questions_out = tempfile.NamedTemporaryFile(mode="w+", delete=False) | ||
| 87 | for l in add_requires(qlabel, distro, questions_in): | ||
| 88 | questions_out.write(l) | ||
| 89 | questions_out.close() | ||
| 90 | questions_in.close() | ||
| 91 | shutil.copystat(qfile, questions_out.name) | ||
| 92 | os.remove(qfile) | ||
| 93 | shutil.move(questions_out.name, qfile) | ||
| 94 | |||
| 95 | |||
| 96 | |||
| 97 | def handle_args(parser): | ||
| 98 | parser.add_argument('config_file', | ||
| 99 | help = "Configuration file path.") | ||
| 100 | parser.add_argument('questions_dir', | ||
| 101 | help = "Directory containing Questions files.") | ||
| 102 | parser.add_argument('--distro', '-d', | ||
| 103 | help = "The distribution, the default is Yocto.", | ||
| 104 | default = "Yocto") | ||
| 105 | parser.add_argument('--debug', '-b', | ||
| 106 | help = "Print debug information.", | ||
| 107 | action = 'store_true') | ||
| 108 | return parser.parse_args() | ||
| 109 | |||
| 110 | |||
| 111 | |||
| 112 | def check_args(args): | ||
| 113 | args.config_file = os.path.abspath(args.config_file) | ||
| 114 | args.questions_dir = os.path.abspath(args.questions_dir) | ||
| 115 | |||
| 116 | if not os.path.isdir(args.questions_dir): | ||
| 117 | raise ValueError("Specified Questions directory %s does not exist or is not a directory." % args.questions_dir) | ||
| 118 | |||
| 119 | if not os.path.isfile(args.config_file): | ||
| 120 | raise ValueError("Specified configuration file %s not found." % args.config_file) | ||
| 121 | |||
| 122 | |||
| 123 | |||
| 124 | def main(): | ||
| 125 | opts = handle_args(argparse.ArgumentParser(description="A simple script that sets required questions based on the question/answer pairs in a configuration file.")) | ||
| 126 | |||
| 127 | try: | ||
| 128 | check_args(opts) | ||
| 129 | except ValueError as e: | ||
| 130 | if opts.debug: | ||
| 131 | traceback.print_exc() | ||
| 132 | else: | ||
| 133 | sys.exit("Fatal error:\n%s" % e) | ||
| 134 | |||
| 135 | |||
| 136 | try: | ||
| 137 | config_in = open(opts.config_file) | ||
| 138 | for qfile, qlabel in get_config(config_in): | ||
| 139 | questions_file = os.path.join(opts.questions_dir, qfile + ".txt") | ||
| 140 | xform_file(questions_file, opts.distro, qlabel) | ||
| 141 | config_in.close() | ||
| 142 | |||
| 143 | except IOError as e: | ||
| 144 | if opts.debug: | ||
| 145 | traceback.print_exc() | ||
| 146 | else: | ||
| 147 | sys.exit("Fatal error reading or writing file:\n%s" % e) | ||
| 148 | except ValueError as e: | ||
| 149 | if opts.debug: | ||
| 150 | traceback.print_exc() | ||
| 151 | else: | ||
| 152 | sys.exit("Fatal error:\n%s" % e) | ||
| 153 | |||
| 154 | |||
| 155 | |||
| 156 | if __name__ == "__main__": | ||
| 157 | main() | ||
