Skip to content

Commit 8890caa

Browse files
Merge pull request #1177 from matejak/oscap-ssh-opts
Allow oscap-ssh to use custom SSH options
2 parents 3fae916 + 78215f6 commit 8890caa

File tree

2 files changed

+115
-71
lines changed

2 files changed

+115
-71
lines changed

utils/oscap-ssh

Lines changed: 108 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -80,61 +80,99 @@ function usage()
8080
echo "specific option for oscap-ssh (must be first argument):"
8181
echo " --sudo"
8282
echo
83+
echo "To supply additional options to ssh/scp, define the SSH_ADDITIONAL_OPTIONS variable"
84+
echo "For instance, to ignore known hosts records, define SSH_ADDITIONAL_OPTIONS='-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null'"
85+
echo
86+
echo "specific option for oscap-ssh (must be first argument):"
87+
echo
8388
echo "See \`man oscap\` to learn more about semantics of these options."
8489
}
8590

8691
OSCAP_SUDO=""
87-
SSH_ADDITIONAL_ARGS=""
88-
if [ $# -lt 1 ]; then
89-
echo "No arguments provided."
90-
usage
91-
die
92-
elif [ "$1" == "-h" ] || [ "$1" == "--help" ]; then
93-
usage
94-
die
95-
elif [ "$1" == "sudo" ] || [ "$1" == "--sudo" ]; then
96-
OSCAP_SUDO="sudo"
97-
# force pseudo-tty allocation so that users can type their password if necessary
98-
SSH_ADDITIONAL_ARGS="-t"
99-
shift
100-
fi
101-
if [ $# -lt 2 ]; then
102-
echo "Missing ssh host and ssh port."
103-
usage
104-
die
105-
fi
92+
# SSH_ADDITIONAL_OPTIONS may be defined in the calling shell
93+
SSH_TTY_ALLOCATION_OPTION=""
94+
95+
# $1, $2, ... SSH options (pass them as separate arguments)
96+
function ssh_execute_with_options {
97+
ssh -o ControlPath="$MASTER_SOCKET" $SSH_ADDITIONAL_OPTIONS "$@" -p "$SSH_PORT" "$SSH_HOST"
98+
}
99+
100+
# $1: The SSH command.
101+
# $2: More of additional options (optional, pass one space-separated string)
102+
function ssh_execute_with_command_and_options {
103+
ssh -o ControlPath="$MASTER_SOCKET" $SSH_ADDITIONAL_OPTIONS $2 -p "$SSH_PORT" "$SSH_HOST" "$1"
104+
}
105+
106+
# $1: Local filename to copy
107+
# $2: Remote destination
108+
function scp_copy_to_temp_dir {
109+
scp -o ControlPath="$MASTER_SOCKET" -P "$SSH_PORT" $SSH_ADDITIONAL_OPTIONS "$1" "$SSH_HOST:$REMOTE_TEMP_DIR/$2"
110+
}
111+
112+
# $1: Remote filename to get
113+
# $2: Local destination
114+
function scp_retreive_from_temp_dir {
115+
scp -o ControlPath="$MASTER_SOCKET" -P "$SSH_PORT" $SSH_ADDITIONAL_OPTIONS "$SSH_HOST:$REMOTE_TEMP_DIR/$1" "$2"
116+
}
117+
118+
function sanity_check_arguments {
119+
if [ $# -lt 1 ]; then
120+
echo "No arguments provided."
121+
usage
122+
die
123+
elif [ "$1" == "-h" ] || [ "$1" == "--help" ]; then
124+
usage
125+
die
126+
elif [ "$1" == "sudo" ] || [ "$1" == "--sudo" ]; then
127+
OSCAP_SUDO="sudo"
128+
# force pseudo-tty allocation so that users can type their password if necessary
129+
SSH_TTY_ALLOCATION_OPTION="-t"
130+
shift
131+
fi
132+
if [ $# -lt 2 ]; then
133+
echo "Missing ssh host and ssh port."
134+
usage
135+
die
136+
fi
137+
}
138+
139+
function check_oscap_arguments {
140+
if [ "$1" == "--v" ] || [ "$1" == "--version" ]; then
141+
true
142+
elif [ "$1" == "-h" ] || [ "$1" == "--help" ]; then
143+
true
144+
elif [ "$1" == "info" ]; then
145+
true
146+
elif [ "$1 $2" == "xccdf eval" ]; then
147+
true
148+
elif [ "$1 $2" == "oval eval" ]; then
149+
true
150+
elif [ "$1 $2" == "oval collect" ]; then
151+
true
152+
else
153+
die "This script only supports 'sudo' as first argument, '-h', '--help', '--v', '--version', 'info', 'xccdf eval', 'oval eval' and 'oval collect'."
154+
fi
155+
}
156+
157+
sanity_check_arguments "$@"
106158

107159
SSH_HOST="$1"
108160
SSH_PORT="$2"
109161

110-
if [ "$3" == "--v" ] || [ "$3" == "--version" ]; then
111-
true
112-
elif [ "$3" == "-h" ] || [ "$3" == "--help" ]; then
113-
true
114-
elif [ "$3" == "info" ]; then
115-
true
116-
elif [ "$3 $4" == "xccdf eval" ]; then
117-
true
118-
elif [ "$3 $4" == "oval eval" ]; then
119-
true
120-
elif [ "$3 $4" == "oval collect" ]; then
121-
true
122-
else
123-
die "This script only supports '-h', '--help', '--v', '--version', 'info', 'xccdf eval', 'oval eval' and 'oval collect'."
124-
fi
125-
126162
shift 2
127163

164+
check_oscap_arguments "$@"
165+
128166
MASTER_SOCKET_DIR=$(mktemp -d)
129167
MASTER_SOCKET="$MASTER_SOCKET_DIR/ssh_socket"
130168

131169
echo "Connecting to '$SSH_HOST' on port '$SSH_PORT'..."
132-
ssh -M -f -N -o ServerAliveInterval=60 -o ControlPath="$MASTER_SOCKET" -p "$SSH_PORT" "$SSH_HOST" || die "Failed to connect!"
170+
ssh_execute_with_options -M -f -N -o ServerAliveInterval=60 || die "Failed to connect!"
133171
echo "Connected!"
134172

135-
REMOTE_TEMP_DIR=$(ssh -o ControlPath="$MASTER_SOCKET" -p "$SSH_PORT" "$SSH_HOST" mktemp -d) || die "Failed to create remote temporary directory!"
173+
REMOTE_TEMP_DIR=$(ssh_execute_with_command_and_options "mktemp -d") || die "Failed to create remote temporary directory!"
136174

137-
args=("$@")
175+
oscap_args=("$@")
138176

139177
LOCAL_CONTENT_PATH=""
140178
LOCAL_TAILORING_PATH=""
@@ -151,38 +189,38 @@ OVAL_RESULTS=""
151189
for i in $(seq 0 `expr $# - 1`); do
152190
let j=i+1
153191

154-
case "${args[i]}" in
192+
case "${oscap_args[i]}" in
155193
("--tailoring-file")
156-
LOCAL_TAILORING_PATH=${args[j]}
157-
args[j]="$REMOTE_TEMP_DIR/tailoring.xml"
194+
LOCAL_TAILORING_PATH=${oscap_args[j]}
195+
oscap_args[j]="$REMOTE_TEMP_DIR/tailoring.xml"
158196
;;
159197
("--cpe")
160-
LOCAL_CPE_PATH=${args[j]}
161-
args[j]="$REMOTE_TEMP_DIR/cpe.xml"
198+
LOCAL_CPE_PATH=${oscap_args[j]}
199+
oscap_args[j]="$REMOTE_TEMP_DIR/cpe.xml"
162200
;;
163201
("--variables")
164-
LOCAL_VARIABLES_PATH=${args[j]}
165-
args[j]="$REMOTE_TEMP_DIR/variables.xml"
202+
LOCAL_VARIABLES_PATH=${oscap_args[j]}
203+
oscap_args[j]="$REMOTE_TEMP_DIR/variables.xml"
166204
;;
167205
("--directives")
168-
LOCAL_DIRECTIVES_PATH=${args[j]}
169-
args[j]="$REMOTE_TEMP_DIR/directives.xml"
206+
LOCAL_DIRECTIVES_PATH=${oscap_args[j]}
207+
oscap_args[j]="$REMOTE_TEMP_DIR/directives.xml"
170208
;;
171209
("--results")
172-
TARGET_RESULTS=${args[j]}
173-
args[j]="$REMOTE_TEMP_DIR/results.xml"
210+
TARGET_RESULTS=${oscap_args[j]}
211+
oscap_args[j]="$REMOTE_TEMP_DIR/results.xml"
174212
;;
175213
("--results-arf")
176-
TARGET_RESULTS_ARF=${args[j]}
177-
args[j]="$REMOTE_TEMP_DIR/results-arf.xml"
214+
TARGET_RESULTS_ARF=${oscap_args[j]}
215+
oscap_args[j]="$REMOTE_TEMP_DIR/results-arf.xml"
178216
;;
179217
("--report")
180-
TARGET_REPORT=${args[j]}
181-
args[j]="$REMOTE_TEMP_DIR/report.html"
218+
TARGET_REPORT=${oscap_args[j]}
219+
oscap_args[j]="$REMOTE_TEMP_DIR/report.html"
182220
;;
183221
("--syschar")
184-
TARGET_SYSCHAR=${args[j]}
185-
args[j]="$REMOTE_TEMP_DIR/syschar.xml"
222+
TARGET_SYSCHAR=${oscap_args[j]}
223+
oscap_args[j]="$REMOTE_TEMP_DIR/syschar.xml"
186224
;;
187225
("--oval-results")
188226
OVAL_RESULTS="yes"
@@ -194,8 +232,8 @@ done
194232

195233
if [ "$1" != "--v" ] && [ "$1" != "--version" ] && [ "$1" != "-h" ] && [ "$1" != "--help" ]; then
196234
# Last argument should be the content path
197-
LOCAL_CONTENT_PATH="${args[`expr $# - 1`]}"
198-
args[`expr $# - 1`]="$REMOTE_TEMP_DIR/input.xml"
235+
LOCAL_CONTENT_PATH="${oscap_args[`expr $# - 1`]}"
236+
oscap_args[`expr $# - 1`]="$REMOTE_TEMP_DIR/input.xml"
199237
fi
200238

201239
[ "$LOCAL_CONTENT_PATH" == "" ] || [ -f "$LOCAL_CONTENT_PATH" ] || die "Expected the last argument to be an input file, '$LOCAL_CONTENT_PATH' isn't a valid file path or the file doesn't exist!"
@@ -206,54 +244,54 @@ fi
206244

207245
if [ "$LOCAL_CONTENT_PATH" != "" ]; then
208246
echo "Copying input file '$LOCAL_CONTENT_PATH' to remote working directory '$REMOTE_TEMP_DIR'..."
209-
scp -o ControlPath="$MASTER_SOCKET" -P "$SSH_PORT" "$LOCAL_CONTENT_PATH" "$SSH_HOST:$REMOTE_TEMP_DIR/input.xml" || die "Failed to copy input file to remote temporary directory!"
247+
scp_copy_to_temp_dir "$LOCAL_CONTENT_PATH" input.xml || die "Failed to copy input file to remote temporary directory!"
210248
fi
211249
if [ "$LOCAL_TAILORING_PATH" != "" ]; then
212250
echo "Copying tailoring file '$LOCAL_TAILORING_PATH' to remote working directory '$REMOTE_TEMP_DIR'..."
213-
scp -o ControlPath="$MASTER_SOCKET" -P "$SSH_PORT" "$LOCAL_TAILORING_PATH" "$SSH_HOST:$REMOTE_TEMP_DIR/tailoring.xml" || die "Failed to copy tailoring file to remote temporary directory!"
251+
scp_copy_to_temp_dir "$LOCAL_TAILORING_PATH" tailoring.xml || die "Failed to copy tailoring file to remote temporary directory!"
214252
fi
215253
if [ "$LOCAL_CPE_PATH" != "" ]; then
216254
echo "Copying CPE file '$LOCAL_CPE_PATH' to remote working directory '$REMOTE_TEMP_DIR'..."
217-
scp -o ControlPath="$MASTER_SOCKET" -P "$SSH_PORT" "$LOCAL_CPE_PATH" "$SSH_HOST:$REMOTE_TEMP_DIR/cpe.xml" || die "Failed to copy CPE file to remote temporary directory!"
255+
scp_copy_to_temp_dir "$LOCAL_CPE_PATH" cpe.xml || die "Failed to copy CPE file to remote temporary directory!"
218256
fi
219257
if [ "$LOCAL_VARIABLES_PATH" != "" ]; then
220258
echo "Copying OVAL variables file '$LOCAL_VARIABLES_PATH' to remote working directory '$REMOTE_TEMP_DIR'..."
221-
scp -o ControlPath="$MASTER_SOCKET" -P "$SSH_PORT" "$LOCAL_VARIABLES_PATH" "$SSH_HOST:$REMOTE_TEMP_DIR/variables.xml" || die "Failed to copy OVAL variables file to remote temporary directory!"
259+
scp_copy_to_temp_dir "$LOCAL_VARIABLES_PATH" variables.xml || die "Failed to copy OVAL variables file to remote temporary directory!"
222260
fi
223261
if [ "$LOCAL_DIRECTIVES_PATH" != "" ]; then
224262
echo "Copying OVAL directives file '$LOCAL_DIRECTIVES_PATH' to remote working directory '$REMOTE_TEMP_DIR'..."
225-
scp -o ControlPath="$MASTER_SOCKET" -P "$SSH_PORT" "$LOCAL_DIRECTIVES_PATH" "$SSH_HOST:$REMOTE_TEMP_DIR/directives.xml" || die "Failed to copy OVAL directives file to remote temporary directory!"
263+
scp_copy_to_temp_dir "$LOCAL_DIRECTIVES_PATH" directives.xml || die "Failed to copy OVAL directives file to remote temporary directory!"
226264
fi
227265

228266
echo "Starting the evaluation..."
229267
# changing directory because of --oval-results support. oval results files are
230268
# dumped into PWD, and we can't be sure by the file names - we need controlled
231269
# environment
232-
ssh -o ControlPath="$MASTER_SOCKET" $SSH_ADDITIONAL_ARGS -p "$SSH_PORT" "$SSH_HOST" "cd $REMOTE_TEMP_DIR; $OSCAP_SUDO oscap ${args[*]}"
270+
ssh_execute_with_command_and_options "cd $REMOTE_TEMP_DIR; $OSCAP_SUDO oscap ${oscap_args[*]}" "$SSH_TTY_ALLOCATION_OPTION"
233271
OSCAP_EXIT_CODE=$?
234272
echo "oscap exit code: $OSCAP_EXIT_CODE"
235273

236274
echo "Copying back requested files..."
237275
if [ "$TARGET_RESULTS" != "" ]; then
238-
scp -o ControlPath="$MASTER_SOCKET" -P "$SSH_PORT" "$SSH_HOST:$REMOTE_TEMP_DIR/results.xml" "$TARGET_RESULTS" || die "Failed to copy the results file back to local machine!"
276+
scp_retreive_from_temp_dir results.xml "$TARGET_RESULTS" || die "Failed to copy the results file back to local machine!"
239277
fi
240278
if [ "$TARGET_RESULTS_ARF" != "" ]; then
241-
scp -o ControlPath="$MASTER_SOCKET" -P "$SSH_PORT" "$SSH_HOST:$REMOTE_TEMP_DIR/results-arf.xml" "$TARGET_RESULTS_ARF" || die "Failed to copy the ARF file back to local machine!"
279+
scp_retreive_from_temp_dir results-arf.xml "$TARGET_RESULTS_ARF" || die "Failed to copy the ARF file back to local machine!"
242280
fi
243281
if [ "$TARGET_REPORT" != "" ]; then
244-
scp -o ControlPath="$MASTER_SOCKET" -P "$SSH_PORT" "$SSH_HOST:$REMOTE_TEMP_DIR/report.html" "$TARGET_REPORT" || die "Failed to copy the HTML report back to local machine!"
282+
scp_retreive_from_temp_dir report.html "$TARGET_REPORT" || die "Failed to copy the HTML report back to local machine!"
245283
fi
246284
if [ "$TARGET_SYSCHAR" != "" ]; then
247-
scp -o ControlPath="$MASTER_SOCKET" -P "$SSH_PORT" "$SSH_HOST:$REMOTE_TEMP_DIR/syschar.xml" "$TARGET_SYSCHAR" || die "Failed to copy the OVAL syschar file back to local machine!"
285+
scp_retreive_from_temp_dir syschar.xml "$TARGET_SYSCHAR" || die "Failed to copy the OVAL syschar file back to local machine!"
248286
fi
249287
if [ "$OVAL_RESULTS" == "yes" ]; then
250-
scp -o ControlPath="$MASTER_SOCKET" -P "$SSH_PORT" "$SSH_HOST:$REMOTE_TEMP_DIR/*.result.xml" "./" || die "Failed to copy OVAL result files back to local machine!"
288+
scp_retreive_from_temp_dir '*.result.xml' "./" || die "Failed to copy OVAL result files back to local machine!"
251289
fi
252290

253291
echo "Removing remote temporary directory..."
254-
ssh -o ControlPath="$MASTER_SOCKET" -p "$SSH_PORT" "$SSH_HOST" "rm -r $REMOTE_TEMP_DIR" || die "Failed to remove remote temporary directory!"
292+
ssh_execute_with_command_and_options "rm -r $REMOTE_TEMP_DIR" || die "Failed to remove remote temporary directory!"
255293
echo "Disconnecting ssh and removing master ssh socket directory..."
256-
ssh -o ControlPath="$MASTER_SOCKET" -p "$SSH_PORT" "$SSH_HOST" -O exit || die "Failed to disconnect!"
294+
ssh_execute_with_options -O exit || die "Failed to disconnect!"
257295
rm -r "$MASTER_SOCKET_DIR" || die "Failed to remove local master SSH socket directory!"
258296

259297
exit $OSCAP_EXIT_CODE

utils/oscap-ssh.8

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,16 @@ Supported options are:
6060
Specific option for oscap-ssh (must be first argument):
6161
--sudo
6262

63-
.SH EXEMPLARY USAGE
63+
.SS Environment variables
64+
oscap-ssh checks out the SSH_ADDITIONAL_OPTIONS environment variable, and pastes its contents into the command-line of ssh to the location where options are expected.
65+
Supply the variable in form of a string that corresponds to a section of the ssh command-line and that consists of options you want to pass.
66+
67+
.SH EXAMPLE USAGE
6468
.SS Simple XCCDF evaluation
6569
The following command evaluates a remote Fedora machine as root. HTML report is written out as report.html on the local machine. Can be executed from any machine that has ssh, scp and bash. The local machine does not need to have openscap installed.
70+
It also uses the SSH_ADDITIONAL_OPTIONS variable to configure ssh in such way that contents of the known_hosts file are ignored.
6671

72+
$ export SSH_ADDITIONAL_OPTIONS="-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null"
6773
$ oscap-ssh [email protected] 22 xccdf eval --profile xccdf_org.ssgproject.content_profile_common --report report.html /usr/share/xml/scap/ssg/content/ssg-fedora-ds.xml
6874

6975
.SS XCCDF Evaluation with tailoring file

0 commit comments

Comments
 (0)