| /* |
| * Copyright 2021 Google LLC |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| syntax = "proto3"; |
| |
| package localtoast; |
| |
| option go_package = "github.com/google/localtoast/scannerlib/proto/scan_instructions_go_proto"; |
| |
| // Describes how the scanner should check for compliance with a given |
| // benchmark. |
| message BenchmarkScanInstructionDef { |
| // Either the same instructions are used for all scan types or there |
| // are separate instructions for instance and image scanning. |
| oneof instructions { |
| BenchmarkScanInstruction generic = 1; |
| ScanTypeSpecificInstruction scan_type_specific = 2; |
| } |
| } |
| message ScanTypeSpecificInstruction { |
| BenchmarkScanInstruction instance_scanning = 1; |
| BenchmarkScanInstruction image_scanning = 2; |
| } |
| |
| message BenchmarkScanInstruction { |
| // The benchmark is compliant if at least one of the checks in |
| // check_alternatives passes (OR condition). |
| repeated CheckAlternative check_alternatives = 1; |
| } |
| message CheckAlternative { |
| // The CheckAlternative passes if all the checks it includes pass (AND |
| // condition). |
| repeated FileCheck file_checks = 1; |
| repeated SQLCheck sql_checks = 2; |
| } |
| |
| // A check to be performed on one or more files. |
| message FileCheck { |
| reserved 8; |
| repeated FileSet files_to_check = 1; |
| oneof check_type { |
| ExistenceCheck existence = 2; |
| PermissionCheck permission = 3; |
| ContentCheck content = 4; |
| ContentEntryCheck content_entry = 5; |
| } |
| // Optional, display this instead of the autogenerated non-compliance message. |
| string non_compliance_msg = 6; |
| // Optional, display this command for showing the non-compliant files instead |
| // of listing them all. |
| string file_display_command = 7; |
| // Optional, can be used to make the check run several times with slightly |
| // different settings. |
| RepeatConfig repeat_config = 9; |
| } |
| |
| message RepeatConfig { |
| enum RepeatType { |
| // Run the checks just once. |
| ONCE = 0; |
| // Run the checks for each user found in /etc/passwd, replace "$user", |
| // "$home", "$uid", and "$gid" with the username, home directory, etc. in |
| // file names and file checks. |
| FOR_EACH_USER = 5; |
| // Same as FOR_EACH_USER, but skips users that don't have login shells. |
| FOR_EACH_USER_WITH_LOGIN = 1; |
| // Same as FOR_EACH_USER_WITH_LOGIN, but only includes system users (whose |
| // UID is < UID_MIN). |
| FOR_EACH_SYSTEM_USER_WITH_LOGIN = 2; |
| // Run the checks for each open ipv4/ipv6 port, replace "$port" with the |
| // port in file names and file checks. |
| FOR_EACH_OPEN_IPV4_PORT = 3; |
| FOR_EACH_OPEN_IPV6_PORT = 4; |
| } |
| RepeatType type = 1; |
| // A list of substitutions to opt out from scanning. If set, substitutions |
| // where a given wildcard would be replaced with a given value are skipped. |
| // For example, if type=FOR_EACH_USER_WITH_LOGIN, wildcard=$user, |
| // value=shutdown, then then "shutdown" user would not be processed in the |
| // check. |
| message OptOutSubstitution { |
| string wildcard = 1; |
| string value = 2; |
| } |
| repeated OptOutSubstitution opt_out = 2; |
| } |
| |
| message ExistenceCheck { |
| // At least one file specified in the FileSet should exist if true. |
| // No files should exist if false. |
| bool should_exist = 1; |
| } |
| |
| message PermissionCheck { |
| // The bits from the file permissions' octal representation (flags, owner, |
| // group, others) that should be set and clear. |
| int32 set_bits = 1; |
| int32 clear_bits = 2; |
| |
| // The bit check passes iff... |
| enum BitMatchCriterion { |
| NOT_SET = 0; |
| // ...both the right bits are set and cleared |
| BOTH_SET_AND_CLEAR = 1; |
| // ...either the right bits are set or cleared |
| EITHER_SET_OR_CLEAR = 2; |
| } |
| BitMatchCriterion bits_should_match = 3; |
| |
| // The user/group that should (not) own the file. |
| message OwnerCheck { |
| string name = 1; |
| bool should_own = 2; |
| } |
| OwnerCheck user = 4; |
| OwnerCheck group = 5; |
| } |
| |
| // Checks for the content of the file matching a predefined value. |
| // For .gz files, the unzipped content is checked. |
| message ContentCheck { |
| string content = 1; |
| } |
| |
| // Checks for entries (usually lines) in the file matching a given regex. |
| // For .gz files, the unzipped content is checked. |
| message ContentEntryCheck { |
| // The characters to split entries by. Uses '\n' if empty. |
| bytes delimiter = 1; |
| |
| // Compliant iff... |
| enum MatchType { |
| // ...no criterion is satisfied or the file doesn't exist. |
| NONE_MATCH = 0; |
| // ...all criteria satisfied at least once, in strict order. |
| ALL_MATCH_STRICT_ORDER = 1; |
| // ...all criteria satisfied at least once, in any order. |
| ALL_MATCH_ANY_ORDER = 2; |
| } |
| MatchType match_type = 2; |
| |
| repeated MatchCriterion match_criteria = 3; |
| } |
| |
| // Describes one criterion that the the content entries need to match. |
| message MatchCriterion { |
| // Base criterion: Entries matching `filter_regex` should also |
| // match `expected_regex`. |
| // Example: |
| // filter_regex: "PROMPT_FOR_CONFIRM=.*" |
| // expected_regex: "PROMPT_FOR_CONFIRM=no" |
| string filter_regex = 1; |
| string expected_regex = 2; |
| |
| repeated GroupCriterion group_criteria = 3; |
| } |
| |
| // Additional criteria that the matched regex groups should satisfy. |
| message GroupCriterion { |
| int32 group_index = 1; |
| enum Type { |
| // The group... |
| // ...is an integer < `comparison_value`. |
| LESS_THAN = 0; |
| // ...is an integer > `comparison_value`. |
| GREATER_THAN = 1; |
| // ...represents rwx umask at least as strict as (const) `comparison_value`. |
| NO_LESS_RESTRICTIVE_UMASK = 2; |
| // ...appears exactly once. |
| UNIQUE = 3; |
| } |
| Type type = 2; |
| |
| // The value to compare against is... |
| message Today {} |
| oneof comparison_value { |
| // ...a constant integer. |
| int32 const = 3; |
| // ...the number of days since the epoch. |
| Today today = 4; |
| } |
| } |
| |
| // Describes the files a given FileCheck should look at. |
| message FileSet { |
| // A single file. |
| message SingleFile { |
| string path = 1; |
| } |
| |
| // Several files inside a directory. |
| message FilesInDir { |
| string dir_path = 1; |
| // Includes all files under the dir and subdirs if true, and only the files |
| // in the top dir if false. |
| bool recursive = 2; |
| // If set, includes only files. |
| bool files_only = 3; |
| // If set, includes only directories. |
| bool dirs_only = 4; |
| // If set, omits symlinks. |
| bool skip_symlinks = 7; |
| // If set, includes only the files whose name matches the regex. |
| string filename_regex = 5; |
| // A list of file paths to opt out of traversing. For directories, none of |
| // the files under it will be traversed either. |
| repeated string opt_out_path_regexes = 6; |
| } |
| |
| // A file in the /proc/[0-9]+/ directory of a given process, or the directory |
| // itself. |
| message ProcessPath { |
| // Process name as it's used in the /proc/[0-9]+/stat file. |
| // Should not be longer than 16 characters since names are truncated in |
| // stat. |
| string proc_name = 1; |
| // (Optional) The filename inside the /proc/[0-9]+/ directory. |
| // Example: `environ` refers to the /proc/[0-9]+/environ file. |
| // If left empty, the check will use the /proc/[0-9]+/ directory itself. |
| string file_name = 2; |
| // (Optional) A regex for the CLI args of the process. When set, processes |
| // will only be matched if their /proc/[0-9]+/cmdline file contains the |
| // specified regex. |
| string cli_arg_regex = 3; |
| } |
| |
| // Paths listed in a Unix environment variable of a user running the scanner, |
| // such as $PATH. |
| message UnixEnvVarPaths { |
| string var_name = 1; |
| // If set, includes only files. |
| bool files_only = 2; |
| // If set, includes only directories. |
| bool dirs_only = 3; |
| } |
| |
| oneof file_path { |
| SingleFile single_file = 1; |
| FilesInDir files_in_dir = 2; |
| ProcessPath process_path = 3; |
| UnixEnvVarPaths unix_env_var_paths = 4; |
| } |
| } |
| |
| // A check that executes a SQL query. |
| message SQLCheck { |
| enum SQLDatabase { |
| DB_UNSPECIFIED = 0; |
| DB_MYSQL = 1; |
| DB_CASSANDRA = 2; |
| DB_ELASTICSEARCH = 3; |
| } |
| |
| SQLDatabase target_database = 1; |
| string query = 2; |
| // Compliant iff the query returns or does not return results as we expect. |
| bool expect_results = 3; |
| // Optional, display this instead of the autogenerated non-compliance message. |
| string non_compliance_msg = 4; |
| // Only needed for ElasticSearch database, perform regex match on response. |
| string filter_regex = 5; |
| } |