Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions framework/python/src/api/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -706,6 +706,12 @@ async def update_profile(self, request: Request, response: Response):

LOGGER.debug("Received profile update request")

# Check if the profiles format was loaded correctly
if self.get_session().get_profiles_format() is None:
response.status_code = status.HTTP_501_NOT_IMPLEMENTED
return self._generate_msg(False,
"Risk profiles are not available right now")

try:
req_raw = (await request.body()).decode("UTF-8")
req_json = json.loads(req_raw)
Expand All @@ -726,6 +732,7 @@ async def update_profile(self, request: Request, response: Response):
profile = self.get_session().get_profile(profile_name)

if profile is None:

# Create new profile
profile = self.get_session().update_profile(req_json)

Expand Down
1 change: 1 addition & 0 deletions framework/python/src/common/mqtt.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class MQTT:
def __init__(self) -> None:
self._host = WEBSOCKETS_HOST
self._client = mqtt_client.Client(mqtt_client.CallbackAPIVersion.VERSION2)
LOGGER.setLevel(logger.logging.INFO)
self._client.enable_logger(LOGGER)

def _connect(self):
Expand Down
5 changes: 4 additions & 1 deletion framework/python/src/common/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,6 @@ def add_test_result(self, result):
updated = True

if not updated:
result.result = 'In Progress'
self._results.append(result)

def set_test_result_error(self, result):
Expand Down Expand Up @@ -434,6 +433,10 @@ def _load_profiles(self):
'An error occurred whilst loading the risk assessment format')
LOGGER.debug(e)

# If the format JSON fails to load, skip loading profiles
LOGGER.error('Profiles will not be loaded')
return

profile_format_array = []

# Remove internal properties
Expand Down
9 changes: 9 additions & 0 deletions framework/python/src/net_orc/ip_control.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from common import logger
from common import util
import re
import socket

LOGGER = logger.get_logger('ip_ctrl')

Expand Down Expand Up @@ -96,6 +97,14 @@ def get_iface_port_stats(self, iface):
else:
return None

def get_ip_address(self, iface):
addrs = psutil.net_if_addrs()
if iface in addrs:
for addr in addrs[iface]:
if addr.family == socket.AF_INET:
return addr.address
return None

def get_namespaces(self):
result = util.run_command('ip netns list')
# Strip ID's from the namespace results
Expand Down
5 changes: 4 additions & 1 deletion framework/python/src/net_orc/network_orchestrator.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,9 @@ def start_network(self):
# Get network ready (via Network orchestrator)
LOGGER.debug('Network is ready')

def get_ip_address(self, iface):
return self._ip_ctrl.get_ip_address(iface)

def get_listener(self):
return self._listener

Expand Down Expand Up @@ -468,7 +471,7 @@ def _get_network_module(self, name):
def _start_network_service(self, net_module):

LOGGER.debug('Starting network service ' + net_module.display_name)
network = 'host' if net_module.net_config.host else PRIVATE_DOCKER_NET
network = 'host' if net_module.net_config.host else 'bridge'
LOGGER.debug(f"""Network: {network}, image name: {net_module.image_name},
container name: {net_module.container_name}""")

Expand Down
22 changes: 21 additions & 1 deletion framework/python/src/test_orc/test_orchestrator.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,23 @@ def run_test_modules(self):
continue

test_modules.append(module)

for test in module.tests:

# Duplicate test obj so we don't alter the source
test_copy = copy.deepcopy(test)

# Set result to Not Started
test_copy.result = "Not Started"

# We don't want steps to resolve for not started tests
if hasattr(test_copy, "recommendations"):
test_copy.recommendations = None

# Add test result to the session
self.get_session().add_test_result(test_copy)

# Increment number of tests that will be run
self.get_session().add_total_tests(len(module.tests))

# Store enabled test modules in the TestsOrchectrator object
Expand Down Expand Up @@ -187,7 +204,10 @@ def _calculate_result(self):
for test_result in self._session.get_test_results():
# Check Required tests
if (test_result.required_result.lower() == "required"
and test_result.result.lower() != "compliant"):
and test_result.result.lower() not in [
"compliant",
"error"
]):
result = "Non-Compliant"
# Check Required if Applicable tests
elif (test_result.required_result.lower() == "required if applicable"
Expand Down
2 changes: 1 addition & 1 deletion make/DEBIAN/control
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Package: Testrun
Version: 1.4-a
Version: 1.4.1-a
Architecture: amd64
Maintainer: Google <boddey@google.com>
Homepage: https://github.com/google/testrun
Expand Down
202 changes: 104 additions & 98 deletions modules/network/base/bin/start_module
Original file line number Diff line number Diff line change
@@ -1,99 +1,105 @@
#!/bin/bash

# Copyright 2023 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
#
# https://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.

# Directory where all binaries will be loaded
BIN_DIR="/testrun/bin"

# Default interface should be veth0 for all containers
DEFAULT_IFACE=veth0

# Create a local user that matches the same as the host
# to be used for correct file ownership for various logs
# HOST_USER mapped in via docker container environemnt variables
useradd $HOST_USER

# Enable IPv6 for all containers
sysctl net.ipv6.conf.all.disable_ipv6=0
sysctl -p

# Read in the config file
CONF_FILE="/testrun/conf/module_config.json"
CONF=`cat $CONF_FILE`

if [[ -z $CONF ]]
then
echo "No config file present at $CONF_FILE. Exiting startup."
exit 1
fi

# Extract the necessary config parameters
MODULE_NAME=$(echo "$CONF" | jq -r '.config.meta.name')
DEFINED_IFACE=$(echo "$CONF" | jq -r '.config.network.interface')
GRPC=$(echo "$CONF" | jq -r '.config.grpc')

# Validate the module name is present
if [[ -z "$MODULE_NAME" || "$MODULE_NAME" == "null" ]]
then
echo "No module name present in $CONF_FILE. Exiting startup."
exit 1
fi

# Select which interace to use
if [[ -z $DEFINED_IFACE || "$DEFINED_IFACE" == "null" ]]
then
echo "No Interface Defined, defaulting to veth0"
INTF=$DEFAULT_IFACE
else
INTF=$DEFINED_IFACE
fi

# Setup the PYTHONPATH so all imports work as expected
echo "Setting up PYTHONPATH..."
export PYTHONPATH=$($BIN_DIR/setup_python_path)
echo "PYTHONPATH: $PYTHONPATH"

echo "Configuring binary files..."
$BIN_DIR/setup_binaries $BIN_DIR

echo "Starting module $MODULE_NAME on local interface $INTF..."

# Wait for interface to become ready
$BIN_DIR/wait_for_interface $INTF

# Small pause to let the interface stabalize before starting the capture
#sleep 1

# Start network capture
$BIN_DIR/capture $MODULE_NAME $INTF

# Start the grpc server
if [[ ! -z $GRPC && ! $GRPC == "null" ]]
then
GRPC_PORT=$(echo "$GRPC" | jq -r '.port')
if [[ ! -z $GRPC_PORT && ! $GRPC_PORT == "null" ]]
then
echo "gRPC port resolved from config: $GRPC_PORT"
$BIN_DIR/start_grpc "-p $GRPC_PORT"
else
$BIN_DIR/start_grpc
fi
fi

# Small pause to let all core services stabalize
sleep 3

# Start the networking service
#!/bin/bash

# Copyright 2023 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
#
# https://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.

# Directory where all binaries will be loaded
BIN_DIR="/testrun/bin"

# Default interface should be veth0 for all containers
DEFAULT_IFACE=veth0

# Create a local user that matches the same as the host
# to be used for correct file ownership for various logs
# HOST_USER mapped in via docker container environemnt variables
useradd $HOST_USER

# Enable IPv6 for all containers
sysctl net.ipv6.conf.all.disable_ipv6=0
sysctl -p

# Read in the config file
CONF_FILE="/testrun/conf/module_config.json"
CONF=`cat $CONF_FILE`

if [[ -z $CONF ]]
then
echo "No config file present at $CONF_FILE. Exiting startup."
exit 1
fi

# Extract the necessary config parameters
MODULE_NAME=$(echo "$CONF" | jq -r '.config.meta.name')
DEFINED_IFACE=$(echo "$CONF" | jq -r '.config.network.interface')
HOST=$(echo "$CONF" | jq -r '.config.network.host')
GRPC=$(echo "$CONF" | jq -r '.config.grpc')

# Validate the module name is present
if [[ -z "$MODULE_NAME" || "$MODULE_NAME" == "null" ]]
then
echo "No module name present in $CONF_FILE. Exiting startup."
exit 1
fi

# Select which interace to use
if [[ -z $DEFINED_IFACE || "$DEFINED_IFACE" == "null" ]]
then
echo "No Interface Defined, defaulting to veth0"
INTF=$DEFAULT_IFACE
else
INTF=$DEFINED_IFACE
fi

# Setup the PYTHONPATH so all imports work as expected
echo "Setting up PYTHONPATH..."
export PYTHONPATH=$($BIN_DIR/setup_python_path)
echo "PYTHONPATH: $PYTHONPATH"

echo "Configuring binary files..."
$BIN_DIR/setup_binaries $BIN_DIR

echo "Starting module $MODULE_NAME on local interface $INTF..."

# Only non-host containers will have a specific
# interface for capturing
if [[ "$HOST" != "true" ]]; then

# Wait for interface to become ready
$BIN_DIR/wait_for_interface $INTF

# Small pause to let the interface stabalize before starting the capture
#sleep 1

# Start network capture
$BIN_DIR/capture $MODULE_NAME $INTF
fi

# Start the grpc server
if [[ ! -z $GRPC && ! $GRPC == "null" ]]
then
GRPC_PORT=$(echo "$GRPC" | jq -r '.port')
if [[ ! -z $GRPC_PORT && ! $GRPC_PORT == "null" ]]
then
echo "gRPC port resolved from config: $GRPC_PORT"
$BIN_DIR/start_grpc "-p $GRPC_PORT"
else
$BIN_DIR/start_grpc
fi
fi

# Small pause to let all core services stabalize
sleep 3

# Start the networking service
$BIN_DIR/start_network_service $MODULE_NAME $INTF
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,5 @@ def run():
print('gRPC server starting on port ' + port)
serve(port)


if __name__ == '__main__':
run()
23 changes: 23 additions & 0 deletions modules/network/host/bin/start_network_service
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/bin/bash

# Copyright 2023 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
#
# https://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.

echo "Starting Host Service..."


# Keep host container running until stopped
while true; do
sleep 3
done
24 changes: 24 additions & 0 deletions modules/network/host/conf/module_config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"config": {
"meta": {
"name": "host",
"display_name": "Host",
"description": "Used to access host level networking operations"
},
"network": {
"host": true
},
"grpc":{
"port": 5001
},
"docker": {
"depends_on": "base",
"mounts": [
{
"source": "runtime/network",
"target": "/runtime/network"
}
]
}
}
}
Loading