Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
speed47 committed Dec 19, 2024
1 parent 3534f10 commit 861ec9f
Show file tree
Hide file tree
Showing 11 changed files with 72 additions and 102 deletions.
4 changes: 3 additions & 1 deletion bin/shell/osh.pl
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,9 @@ sub main_exit {
uniqid => $log_uniq_id
) if (not defined $log_db_name or not defined $log_insert_id);

my $R = R($retcode eq OVH::Bastion::EXIT_OK ? 'OK' : 'KO_' . uc($comment), msg => $msg);
my $exitcode = uc($comment);
$exitcode =~ tr/-/_/;
my $R = R($retcode eq OVH::Bastion::EXIT_OK ? 'OK' : "KO_$exitcode", msg => $msg);

OVH::Bastion::osh_crit($R->msg) if not $R;
OVH::Bastion::json_output($R) if $ENV{'PLUGIN_JSON'};
Expand Down
2 changes: 1 addition & 1 deletion lib/perl/OVH/Bastion.pm
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,7 @@ sub json_output { ## no critic (ArgUnpacking)
$JsonObject->pretty(1);
}
my $encoded_json =
$JsonObject->encode({error_code => $R->err, error_message => $R->msg, command => $command, value => $R->value});
$JsonObject->encode({error_code => $R->err, error_message => $R->msg, command => $command, value => $R->value, session_id => $ENV{'UNIQID'}});

# rename forbidden strings
$encoded_json =~ s/JSON_(START|OUTPUT|END)/JSON__$1/g;
Expand Down
2 changes: 1 addition & 1 deletion lib/perl/OVH/Bastion/ssh.inc
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ sub get_ssh_pub_key_info {
($prefix, $typecode, $base64, $comment) = ($2, $3, $4, $6);
}
else {
return R('KO_NOT_A_KEY', value => {line => $pubKey});
return R('KO_NOT_A_KEY');
}
my $line = "$typecode $base64";
$prefix = '' if not defined $prefix;
Expand Down
1 change: 1 addition & 0 deletions lib/perl/OVH/Result.pm
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ sub TO_JSON {
error_code => $self->err,
value => $self->value,
error_message => $self->msg,
session_id => $ENV{'UNIQID'},
}
if (ref $self eq 'OVH::Result');
return {};
Expand Down
65 changes: 4 additions & 61 deletions selfListPasswords.jsonschema
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,6 @@
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://www.ovhcloud.com/the-bastion/schemas/plugins/selfListPasswords",
"$defs": {
"command": {
"description": "Command name",
"type": "string",
"pattern": "^[a-z][a-zA-Z]+$",
"minLength": 4
},
"error_message": {
"type": "string",
"minLength": 2
},
"value_arrayitem_object": {
"type": "object",
"additionalProperties": false,
Expand Down Expand Up @@ -90,55 +80,8 @@
}
}
},
"type": "object",
"additionalProperties": true,
"minProperties": 4,
"maxProperties": 4,
"oneOf": [
{
"additionalProperties": false,
"properties": {
"command": {
"$ref": "#/$defs/command"
},
"error_message": {
"$ref": "#/$defs/error_message"
},
"error_code": {
"type": "string",
"pattern": "^(KO|ERR)(_[A-Z_]+)?$"
},
"value": {
"type": "null"
}
}
},
{
"additionalProperties": false,
"properties": {
"command": {
"$ref": "#/$defs/command"
},
"error_message": {
"$ref": "#/$defs/error_message"
},
"error_code": {
"type": "string",
"pattern": "^OK(_[A-Z_]+)?$"
},
"value": {
"type": "array",
"items": {
"$ref": "#/$defs/value_arrayitem_object"
}
}
}
}
],
"required": [
"command",
"error_code",
"error_message",
"value"
]
"type": "array",
"items": {
"$ref": "#/$defs/value_arrayitem_object"
}
}
6 changes: 3 additions & 3 deletions tests/functional/docker/docker_build_and_run_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -125,11 +125,11 @@ if docker inspect "bastion-$target" >/dev/null 2>&1; then
fi

# trying with IPv6
if ! docker network create --ipv6 --subnet fd42:cafe:efac:"$(printf "%x" $RANDOM)"::/64 "bastion-$target" >/dev/null; then
#if true || ! docker network create --ipv6 --subnet fd42:cafe:efac:"$(printf "%x" $RANDOM)"::/64 "bastion-$target" >/dev/null; then
# didn't work... retry without IPv6
echo "... IPv6 is not enabled in docker daemon, falling back to IPv4-only network"
# echo "... IPv6 is not enabled in docker daemon, falling back to IPv4-only network"
docker network create "bastion-$target" >/dev/null
fi
#fi

# run target but force entrypoint to test one, and add some keys in env (will be shared with tester)
echo "Starting target instance"
Expand Down
78 changes: 48 additions & 30 deletions tests/functional/launch_tests_on_instance.sh
Original file line number Diff line number Diff line change
Expand Up @@ -394,8 +394,10 @@ run()
cat "$outdir/$basename.log"
printf "%b%b%b\\n" "$WHITE_ON_BLUE" "[INFO] returned json follows" "$NOC"
grep "^JSON_OUTPUT=" -- $outdir/$basename.log | cut -d= -f2- | jq --sort-keys .
printf "%b%b%b\\n" "$WHITE_ON_BLUE" "[INFO] json validation information follows" "$NOC"
cat "$outdir/$basename.jv"
if [ -s "$outdir/$basename.jv" ]; then
printf "%b%b%b\\n" "$WHITE_ON_BLUE" "[INFO] json validation information follows" "$NOC"
cat "$outdir/$basename.jv"
fi
if [ "$opt_consistency_check" = 1 ]; then
printf "%b%b%b\\n" "$WHITE_ON_BLUE" "[INFO] consistency check follows" "$NOC"
cat "$outdir/$basename.cc"
Expand Down Expand Up @@ -445,30 +447,46 @@ run()
fi

# do we have a json output and if we do, do we have a jsonschema for the command?
returned_json=$(grep "^JSON_OUTPUT=" -- $outdir/$basename.log | tail -n1 | cut -d= -f2-)
local _osh
_osh=$(get_json | $jq '.command')
if [ -n "$_osh" ] && [ "$_osh" != "null" ] && [ -e "$basedir/$_osh.jsonschema" ]; then
get_json | perl -e '
_osh=$(echo "$returned_json" | $jq '.command')
if [ -n "$_osh" ]; then
echo "$returned_json" | env basedir="$basedir" osh="$_osh" perl -e '
use strict;
use warnings;
use JSON;
use JSON::Validator;
my $jv = JSON::Validator->new()->schema("file://'"$basedir/$_osh"'.jsonschema");
my $schema = $jv->schema; # will die if file is invalid json, this is what we want
if ($schema->is_invalid) {
CORE::say $_->to_string() for @{ $schema->errors };
exit 1;
sub validate {
my ($filename, $data) = @_;
return 0 if ! defined $data;
my $file = $ENV{"basedir"}."/$filename.jsonschema";
return 0 if ! -e $file;
my $jv = JSON::Validator->new()->schema("file://$file");
my $schema = $jv->schema; # will die if file is invalid json, this is what we want
if ($schema->is_invalid) {
print "Schema is invalid:\n";
CORE::say $_->to_string() for @{ $schema->errors };
exit 1;
}
my @errors = $schema->validate($data);
CORE::say $_->to_string() for (@errors);
return 1;
}
my $data = eval { local $/; <>; };
my $json = decode_json($data); # will die if it fails, this is what we want
my @errors = $schema->validate($json);
CORE::say $_->to_string() for (@errors);
my $datastr = eval { local $/; <>; };
my $json = decode_json($datastr); # will die if it fails, this is what we want
my $count = 0;
$count += validate("_allPlugins", $json);
$count += validate($ENV{"osh"}, $json->{"value"});
die "Nothing to validate" if !$count;
' > "$outdir/$basename.jv" 2>&1
if [ -s "$outdir/$basename.jv" ]; then
nbfailedgeneric=$(( nbfailedgeneric + 1 ))
fail "JSON SCHEMA" "(json validation failed against the schema of $_osh)"
fail "JSON SCHEMA" "(json validation failed against the schema)"
elif [ -f "$outdir/$basename.jv" ]; then
ok "JSON SCHEMA" "(json data matches the schema of $_osh)"
ok "JSON SCHEMA" "(json data matches the schema)"
else
nbfailedgeneric=$(( nbfailedgeneric + 1 ))
fail "JSON SCHEMA" "(json validation didn't produce an output at all)"
Expand Down Expand Up @@ -508,6 +526,7 @@ script() {
return
fi

local tmpscript
tmpscript=$(mktemp)
echo "#! /usr/bin/env bash" > "$tmpscript"
echo "$*" >> "$tmpscript"
Expand Down Expand Up @@ -559,12 +578,6 @@ ignorecodewarn()
code_warn_exclude="$*"
}

get_json()
{
[ "$COUNTONLY" = 1 ] && return
grep "^JSON_OUTPUT=" -- $outdir/$basename.log | tail -n1 | cut -d= -f2-
}

get_stdout()
{
[ "$COUNTONLY" = 1 ] && return
Expand All @@ -574,7 +587,7 @@ get_stdout()
json()
{
[ "$COUNTONLY" = 1 ] && return
local jq1="" jq2="" jq3=""
local jq1="" jq2="" jq3="" got="" expected=""
local splitsort=0
while [ $# -ge 2 ] ; do
if [ "$1" = "--splitsort" ]; then
Expand All @@ -590,37 +603,41 @@ json()
fi
local filter="$1" expected="$2"
shift 2
json=$(get_json)
set +e
if [ -n "$jq3" ]; then
got=$($jq "$jq1" "$jq2" "$jq3" "$filter" <<< "$json")
got=$($jq "$jq1" "$jq2" "$jq3" "$filter" <<< "$returned_json")
else
got=$($jq "$filter" <<< "$json")
got=$($jq "$filter" <<< "$returned_json")
fi
if [ "$splitsort" = 1 ]; then
expected=$(echo "$expected" | tr " " "\\n" | sort)
got=$($jq ".[]" <<< "$got" | sort)
fi
set -e
if [ -z "$json" ] ; then
if [ -z "$returned_json" ] ; then
nbfailedgrep=$(( nbfailedgrep + 1 ))
fail "JSON VALUE" "(no json found in output, couldn't look for key <$filter>)"
elif [ "$expected" = "$got" ] ; then
ok "JSON VALUE" "($filter => $expected) [$jq1 $jq3 $jq3]"
ok "JSON VALUE" "($filter => $expected) [$jq1 $jq2 $jq3]"
else
nbfailedgrep=$(( nbfailedgrep + 1 ))
fail "JSON VALUE" "(for key <$filter> wanted <$expected> but got <$got>, with optional params jq1='$jq1' jq2='$jq2' jq3='$jq3')"
fi
done
}

get_json()
{
echo "${returned_json:-}"
}

json_document()
{
[ "$COUNTONLY" = 1 ] && return
local fulljson="$1"
local tmpdiff; tmpdiff=$(mktemp)
local diffret=0
diff -u0 <(echo "$fulljson" | jq -S .) <(get_json | jq -S .) > "$tmpdiff"; diffret=$?
diff -u0 <(echo "$fulljson" | jq -S .) <(echo "$returned_json" | jq -S .) > "$tmpdiff"; diffret=$?
if [ "$diffret" = 0 ]; then
ok "JSON DOCUMENT" "(fully matched)"
else
Expand Down Expand Up @@ -662,6 +679,7 @@ contain()
nocontain()
{
[ "$COUNTONLY" = 1 ] && return
local grepit
grepit="$1"
if grep -Eq "$grepit" "$outdir/$basename.log"; then
nbfailedgrep=$(( nbfailedgrep + 1 ))
Expand Down Expand Up @@ -696,7 +714,7 @@ dump_vars_and_funcs()
{
set | grep -v -E '^('\
'testno|section|code_warn_exclude|COPROC_PID|LINES|COLUMNS|PIPESTATUS|_|'\
'BASH_LINENO|basename|case|json|name|tmpscript|grepit|got|isbad|'\
'BASH_LINENO|basename|case|json|name|isbad|returned_json|'\
'nbfailedgrep|nbfailedcon|nbfailedgeneric|nbfailedlog|nbfailedret|shouldbe|modulename)='
}

Expand Down
8 changes: 7 additions & 1 deletion tests/functional/tests.d/325-accountinfo.sh
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,13 @@ testsuite_accountinfo()

# a1 should see basic info about a2
success a1_accountinfo_a2_basic $a1 --osh accountInfo --account $account2
json_document '{"error_message":"OK","command":"accountInfo","error_code":"OK","value":{"account":"'"$account2"'","always_active":1,"always_active_reason":"account local configuration","is_active":1,"allowed_commands":[],"groups":{}}}'
json .error_code OK .command accountInfo
json .value.account "$account2"
json .value.always_active 1
json .value.always_active_reason "account local configuration"
json .value.is_active 1
json .value.allowed_commands '[]'
json .value.groups '{}'

# a0 should see detailed info about a2
success a0_accountinfo_a2_detailed $a0 --osh accountInfo --account $account2 --with-mfa-password-info
Expand Down
2 changes: 1 addition & 1 deletion tests/functional/tests.d/330-selfkeys.sh
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ EOS
script bogus $a1 -osh selfAddIngressKey '<<<' "bogus"
retvalshouldbe 100
contain "look like an SSH public key"
json .command selfAddIngressKey .error_code KO_NOT_A_KEY .value.key.line bogus
json .command selfAddIngressKey .error_code KO_NOT_A_KEY .value null

script eof $a1 -osh selfAddIngressKey '</dev/null'
retvalshouldbe 100
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ testsuite_selfaccesses_force_password()

run ${mode}_connect_a4_fp_hashnotfound $a1 $account4@$remote_ip $password_switch -- --osh help
retvalshouldbe 108
json .error_code KO_FORCED-PASSWORD-NOT-FOUND
json .error_code KO_FORCED_PASSWORD_NOT_FOUND
nocontain "will use SSH with password autologin"

success ${mode}_del_a4_fp_hashnotfound $a0 --osh $del_access_plugin $target --host $remote_ip --user $account4 --port $remote_port
Expand Down
4 changes: 2 additions & 2 deletions tests/functional/tests.d/370-mfa.sh
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,7 @@ testsuite_mfa()
json .command groupList .error_code OK_EMPTY

# pubkey-auth-optional disabled: fail with pubkey but no password (timeout)
script a4_no_pubkeyauthoptional_login_pubkey_nopam $a4 --osh groupList
script a4_no_pubkeyauthoptional_login_pubkey_nopam $a4f --osh groupList
retvalshouldbe 124
contain 'Multi-Factor Authentication enabled, an additional authentication factor is required (password).'
contain 'Your password expires on'
Expand Down Expand Up @@ -478,7 +478,7 @@ testsuite_mfa()
json .command groupList .error_code OK_EMPTY

# pubkey-auth-optional enabled: fail with pubkey only
script a4_pubkeyauthoptional_login_pubkey_nopam $a4 --osh groupList
script a4_pubkeyauthoptional_login_pubkey_nopam $a4f --osh groupList
retvalshouldbe 124
contain 'Multi-Factor Authentication enabled, an additional authentication factor is required (password).'
contain 'Your password expires on'
Expand Down

0 comments on commit 861ec9f

Please sign in to comment.