Add --non-interactive flag

Some commands were recently added to swupd which require user
interaction under certain circumstances, when this happens the user has
to manually enter either Y/N to continue or abort the current process.
This commit provides a --non-interactive=<yes/no> flag that can be used
to avoid getting this interactive prompts.

Signed-off-by: Castulo Martinez <castulo.martinez@intel.com>
This commit is contained in:
Castulo Martinez
2020-02-19 12:30:45 -08:00
committed by Otavio Pontes
parent b0357b1b5a
commit 5a957cfd18
13 changed files with 217 additions and 18 deletions
+3
View File
@@ -82,6 +82,9 @@
# Wait for the post-update scripts to complete (boolean value)
#wait_for_scripts=<true/false>
# Sets an automatic response to all prompts and run non-interactively (string value)
#assume=<yes/no>
#
# The sections below contain the options that apply specifically to
+8
View File
@@ -144,6 +144,10 @@ used to modify the core behavior and resources that swupd uses.
Prints the swupd output as a machine readable JSON stream.
- ``-y, --yes``
Assume yes as answer to all prompts and run non-interactively.
- ``--allow-insecure-http``
For security reasons, swupd only allows system updates using
@@ -175,6 +179,10 @@ used to modify the core behavior and resources that swupd uses.
Wait for the post-update scripts to complete.
- ``--assume={yes|no}``
Sets an automatic response to all prompts and run non-interactively.
SUBCOMMANDS
===========
+2 -2
View File
@@ -166,8 +166,8 @@ static enum swupd_code validate_file_permissions(struct list *files_to_be_instal
if (ret_code == SWUPD_NO) {
/* the bundle has files with dangerous permissions,
* ask the user wether to continue or not */
info("\n");
if (confirm_action("The 3rd-party bundle you are about to install contains files with dangerous permission", " with the installation")) {
warn("\nThe 3rd-party bundle you are about to install contains files with dangerous permission\n");
if (confirm_action()) {
ret_code = SWUPD_OK;
} else {
ret_code = SWUPD_INVALID_FILE;
+2 -2
View File
@@ -224,8 +224,8 @@ static enum swupd_code validate_file_permissions(struct list *files_to_be_update
if (ret_code == SWUPD_NO) {
/* the bundle has files with dangerous permissions,
* ask the user wether to continue or not */
info("\n");
if (confirm_action("The 3rd-party update you are about to install contains files with dangerous permission", " with the update")) {
warn("\nThe 3rd-party update you are about to install contains files with dangerous permission\n");
if (confirm_action()) {
ret_code = SWUPD_OK;
} else {
ret_code = SWUPD_INVALID_FILE;
+38
View File
@@ -42,10 +42,12 @@
#define FLAG_DEBUG 1003
#define FLAG_ALLOW_INSECURE_HTTP 1004
#define FLAG_VERBOSE 1005
#define FLAG_ASSUME 1006
struct globals globals = {
.sigcheck = true,
.timecheck = true,
.user_interaction = INTERACTIVE,
.max_retries = DEFAULT_MAX_RETRIES,
.retry_delay = DEFAULT_RETRY_DELAY,
.update_server_port = -1,
@@ -412,6 +414,34 @@ bool set_default_urls()
return true;
}
bool set_assume_option(char *option)
{
bool ret;
char *option_lower = NULL;
if (!option) {
error("Option shouldn't be NULL, please choose either 'yes' or 'no' as your option\n");
return false;
}
option_lower = str_tolower(option);
if (strcmp(option_lower, "y") == 0 || strcmp(option_lower, "yes") == 0) {
globals.user_interaction = NON_INTERACTIVE_ASSUME_YES;
ret = true;
} else if (strcmp(option_lower, "n") == 0 || strcmp(option_lower, "no") == 0) {
globals.user_interaction = NON_INTERACTIVE_ASSUME_NO;
ret = true;
} else {
error("Please choose either 'yes' or 'no' as your non interactive option\n");
ret = false;
}
free_string(&option_lower);
return ret;
}
bool globals_init(void)
{
if (!globals.state_dir) {
@@ -524,6 +554,8 @@ static const struct option global_opts[] = {
{ "allow-insecure-http", no_argument, 0, FLAG_ALLOW_INSECURE_HTTP },
{ "wait-for-scripts", no_argument, 0, FLAG_WAIT_FOR_SCRIPTS },
{ "verbose", no_argument, 0, FLAG_VERBOSE },
{ "assume", required_argument, 0, FLAG_ASSUME },
{ "yes", no_argument, 0, 'y' },
{ 0, 0, 0, 0 }
};
@@ -613,6 +645,8 @@ static bool global_parse_opt(int opt, char *optarg)
case 'j':
json_format = optarg_to_bool(optarg);
return true;
case 'y':
return set_assume_option("y");
case FLAG_NO_PROGRESS:
progress_set_enabled(!optarg_to_bool(optarg));
return true;
@@ -631,6 +665,8 @@ static bool global_parse_opt(int opt, char *optarg)
case FLAG_VERBOSE:
verbose = true;
return true;
case FLAG_ASSUME:
return set_assume_option(optarg);
default:
return false;
}
@@ -683,12 +719,14 @@ void global_print_help(void)
print(" -N, --no-scripts Do not run the post-update scripts and boot update tool\n");
print(" -b, --no-boot-update Do not install boot files to the boot partition (containers)\n");
print(" -j, --json-output Print all output as a JSON stream\n");
print(" -y, --yes Assume yes as answer to all prompts and run non-interactively\n");
print(" --allow-insecure-http Allow updates over insecure connections\n");
print(" --quiet Quiet output. Print only important information and errors\n");
print(" --verbose Enable verbosity for commands\n");
print(" --debug Print extra information to help debugging problems\n");
print(" --no-progress Don't print progress report\n");
print(" --wait-for-scripts Wait for the post-update scripts to complete\n");
print(" --assume=[yes|no] Sets an automatic response to all prompts and run non-interactively\n");
print("\n");
}
+7
View File
@@ -18,6 +18,12 @@ extern "C" {
#define optarg_to_bool(_optarg) (_optarg ? strtobool(_optarg) : true)
enum user_interaction {
INTERACTIVE = 0,
NON_INTERACTIVE_ASSUME_YES,
NON_INTERACTIVE_ASSUME_NO
};
/*
* Global variables
*/
@@ -50,6 +56,7 @@ extern struct globals {
int update_count;
int update_server_port;
int update_skip;
int user_interaction;
timelist *global_times;
} globals;
+9 -6
View File
@@ -1201,16 +1201,19 @@ char *get_tracking_dir(void)
return sys_path_join(globals.state_dir, "bundles");
}
bool confirm_action(const char *warning_msg, const char *action)
bool confirm_action(void)
{
int response;
if (warning_msg) {
warn("%s\n", warning_msg);
info("Do you want to continue? (y/N): ");
if (globals.user_interaction == INTERACTIVE) {
response = tolower(getchar());
info("\n");
} else {
info("%s\n", globals.user_interaction == NON_INTERACTIVE_ASSUME_YES ? "y" : "N");
info("The \"--assume=%s\" option was used\n", globals.user_interaction == NON_INTERACTIVE_ASSUME_YES ? "yes" : "no");
response = globals.user_interaction == NON_INTERACTIVE_ASSUME_YES ? 'y' : 'n';
}
info("Do you want to continue%s? (y/N): ", action ? action : "");
response = tolower(getchar());
info("%s\n", response == 'y' ? "y" : "N");
return response == 'y';
}
+1 -1
View File
@@ -319,7 +319,7 @@ extern void print_header(const char *header);
extern void prettify_size(long size_in_bytes, char **pretty_size);
extern int link_or_rename(const char *orig, const char *dest);
extern int create_state_dirs(const char *state_dir_path);
extern bool confirm_action(const char *warning_msg, const char *action);
extern bool confirm_action(void);
/* subscription.c */
typedef bool (*subs_fn_t)(struct list **subs, const char *component, int recursion, bool is_optional);
+1 -1
View File
@@ -23,7 +23,7 @@ _swupd()
# $1 is the command being completed, $2 is the current word being expanded
local opts IFS=$' \t\n'
local -i i installed
local global="--help --url --contenturl --versionurl --port --path --format --nosigcheck --ignore-time --statedir --certpath --time --no-scripts --no-boot-update --max-parallel-downloads --max-retries --retry-delay --json-output --allow-insecure-http --debug --verbose --quiet --no-progress --wait-for-scripts"
local global="--help --url --contenturl --versionurl --port --path --format --nosigcheck --ignore-time --statedir --certpath --time --no-scripts --no-boot-update --max-parallel-downloads --max-retries --retry-delay --json-output --allow-insecure-http --debug --verbose --quiet --no-progress --wait-for-scripts --assume --yes"
COMPREPLY=()
for ((i=COMP_CWORD-1;i>=0;i--))
do case "${COMP_WORDS[$i]}" in
+2
View File
@@ -143,8 +143,10 @@ local -a global_opts; global_opts=(
'(help status -t --time)'{-t,--time}'[Show verbose time output for swupd operations]'
'(help status -N --no-scripts)'{-N,--no-scripts}'[Do not run the post-update scripts and boot update tool]'
'(help status -b --no-boot-update)'{-b,--no-boot-update}'[Do not install boot files to the boot partition (containers)]'
'(help status -y --yes)'{-y,--yes}'[Assume yes as answer to all prompts and run non-interactively]'
'(help status)--no-progress[Don`t print progress report]'
'(help status)--wait-for-scripts[Wait for the post-update scripts to complete]'
'(help status)--assume[Sets an automatic response to all prompts and run non-interactively]'
)
# Level-1 completion for sub-command and options to swupd
@@ -43,7 +43,7 @@ test_setup() {
Warning: File /bar/file_2 has dangerous permissions
Warning: File /bar/file_3 has dangerous permissions
Warning: The 3rd-party bundle you are about to install contains files with dangerous permission
Do you want to continue with the installation? (y/N): y
Do you want to continue? (y/N):$SPACE
Installing files...
Warning: post-update helper scripts skipped due to --no-scripts argument
Exporting 3rd-party bundle binaries...
@@ -76,7 +76,7 @@ test_setup() {
Warning: File /bar/file_2 has dangerous permissions
Warning: File /bar/file_3 has dangerous permissions
Warning: The 3rd-party bundle you are about to install contains files with dangerous permission
Do you want to continue with the installation? (y/N): N
Do you want to continue? (y/N):$SPACE
Aborting bundle installation...
Failed to install 1 of 1 bundles
EOM
@@ -84,3 +84,61 @@ test_setup() {
assert_is_output "$expected_output"
}
@test "TPR065: Trying to add a bundle that has dangerous flags from a 3rd-party repository using --assume to run non interactively" {
# If a bundle from a 3rd-party repository has the setuid, setgid or sticky bit flags
# set, then it needs to use the --force flag to be installed since those flags are
# dangerous
run sudo sh -c "$SWUPD 3rd-party bundle-add $SWUPD_OPTS test-bundle1 --assume=no"
assert_status_is "$SWUPD_INVALID_FILE"
expected_output=$(cat <<-EOM
Searching for bundle test-bundle1 in the 3rd-party repositories...
Bundle test-bundle1 found in 3rd-party repository repo1
Bundles added from a 3rd-party repository are forced to run with the --no-scripts flag for security reasons
Loading required manifests...
Validating 3rd-party bundle binaries...
No packs need to be downloaded
Validate downloaded files
Starting download of remaining update content. This may take a while...
Validating 3rd-party bundle file permissions...
Warning: File /bar/file_2 has dangerous permissions
Warning: File /bar/file_3 has dangerous permissions
Warning: The 3rd-party bundle you are about to install contains files with dangerous permission
Do you want to continue? (y/N): N
The "--assume=no" option was used
Aborting bundle installation...
Failed to install 1 of 1 bundles
EOM
)
assert_is_output "$expected_output"
run sudo sh -c "$SWUPD 3rd-party bundle-add $SWUPD_OPTS test-bundle1 --assume=yes"
assert_status_is "$SWUPD_OK"
expected_output=$(cat <<-EOM
Searching for bundle test-bundle1 in the 3rd-party repositories...
Bundle test-bundle1 found in 3rd-party repository repo1
Bundles added from a 3rd-party repository are forced to run with the --no-scripts flag for security reasons
Loading required manifests...
Validating 3rd-party bundle binaries...
No packs need to be downloaded
Validate downloaded files
No extra files need to be downloaded
Validating 3rd-party bundle file permissions...
Warning: File /bar/file_2 has dangerous permissions
Warning: File /bar/file_3 has dangerous permissions
Warning: The 3rd-party bundle you are about to install contains files with dangerous permission
Do you want to continue? (y/N): y
The "--assume=yes" option was used
Installing files...
Warning: post-update helper scripts skipped due to --no-scripts argument
Exporting 3rd-party bundle binaries...
Successfully installed 1 bundle
EOM
)
assert_is_output "$expected_output"
}
@@ -68,7 +68,7 @@ test_setup() {
Warning: The update has a new file /bar/file_4 with dangerous permissions
Warning: The update sets dangerous permissions to file /foo/file_1
Warning: The 3rd-party update you are about to install contains files with dangerous permission
Do you want to continue with the update? (y/N): y
Do you want to continue? (y/N):$SPACE
Installing files...
Update was applied
Updating 3rd-party bundle binaries...
@@ -110,7 +110,7 @@ test_setup() {
Warning: The update has a new file /bar/file_4 with dangerous permissions
Warning: The update sets dangerous permissions to file /foo/file_1
Warning: The 3rd-party update you are about to install contains files with dangerous permission
Do you want to continue with the update? (y/N): N
Do you want to continue? (y/N):$SPACE
Aborting update...
Update failed
EOM
@@ -118,3 +118,81 @@ test_setup() {
assert_is_output "$expected_output"
}
@test "TPR064: Try updating a system from a 3rd-party repo when the update has files with dangerous flags using --assume to run non interactively" {
# the --non-interactive flag can be used to avoid getting prompots
# from swupd
run sudo sh -c "$SWUPD 3rd-party update $SWUPD_OPTS --assume=no"
assert_status_is "$SWUPD_INVALID_FILE"
expected_output=$(cat <<-EOM
_______________________
3rd-Party Repo: repo1
_______________________
Updates from a 3rd-party repository are forced to run with the --no-scripts flag for security reasons
Update started
Preparing to update from 10 to 20
Downloading packs for:
- test-bundle1
Finishing packs extraction...
Statistics for going from version 10 to version 20:
changed bundles : 1
new bundles : 0
deleted bundles : 0
changed files : 3
new files : 2
deleted files : 0
Validate downloaded files
No extra files need to be downloaded
Validating 3rd-party bundle file permissions...
Warning: The update has a new file /bar/file_4 with dangerous permissions
Warning: The update sets dangerous permissions to file /foo/file_1
Warning: The 3rd-party update you are about to install contains files with dangerous permission
Do you want to continue? (y/N): N
The "--assume=no" option was used
Aborting update...
Update failed
EOM
)
assert_is_output "$expected_output"
run sudo sh -c "$SWUPD 3rd-party update $SWUPD_OPTS --yes"
assert_status_is "$SWUPD_OK"
expected_output=$(cat <<-EOM
_______________________
3rd-Party Repo: repo1
_______________________
Updates from a 3rd-party repository are forced to run with the --no-scripts flag for security reasons
Update started
Preparing to update from 10 to 20
Downloading packs for:
- test-bundle1
Finishing packs extraction...
Statistics for going from version 10 to version 20:
changed bundles : 1
new bundles : 0
deleted bundles : 0
changed files : 3
new files : 2
deleted files : 0
Validate downloaded files
No extra files need to be downloaded
Validating 3rd-party bundle file permissions...
Warning: The update has a new file /bar/file_4 with dangerous permissions
Warning: The update sets dangerous permissions to file /foo/file_1
Warning: The 3rd-party update you are about to install contains files with dangerous permission
Do you want to continue? (y/N): y
The "--assume=yes" option was used
Installing files...
Update was applied
Updating 3rd-party bundle binaries...
Warning: post-update helper scripts skipped due to --no-scripts argument
Update successful - System updated from version 10 to version 20
EOM
)
assert_is_output "$expected_output"
}
+4 -2
View File
@@ -1,7 +1,5 @@
#!/usr/bin/bash
set -e
FUNC_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
TEST_ROOT_DIR="$(pwd)"
TEST_FILENAME=$(basename "$BATS_TEST_FILENAME")
@@ -9,6 +7,8 @@ TEST_NAME=${TEST_FILENAME%.bats}
THEME_DIRNAME="$BATS_TEST_DIRNAME"
THIRD_PARTY_BUNDLES_DIR="opt/3rd-party/bundles"
THIRD_PARTY_BIN_DIR="opt/3rd-party/bin"
SPACE=" "
TAB=" "
export TEST_NAME
export TEST_NAME_SHORT="$TEST_NAME"
@@ -17,6 +17,8 @@ export FUNC_DIR
export SWUPD_DIR="$FUNC_DIR/../.."
export THIRD_PARTY_BUNDLES_DIR
export THIRD_PARTY_BIN_DIR
export SPACE
export TAB
# detect where the swupd binary is
if [ -e "$SWUPD" ]; then