Skip to content

Commit

Permalink
Move v1.4.1 into dev (#686)
Browse files Browse the repository at this point in the history
* Update NTP report (#666)

* Update NTP report

* cleanup imports

* pylint  updates

* Add not started and disabled as test statuses

* Fix disabled test

* Check if profiles format has loaded (#665)

* Feature/dhcp disconnect (#626)

* Initial work on giving host access to test containers

* Change external ip resolving method to use docker0

* Resolve device interface for test containers

* Add gRPC methods to control the interface state
Implement dhcp disconnect test

* Fix host network module option

* Misc cleanup

* Move ip resolving method to IPControl class

* pylint fixes

* refactor func to handle case when network interface not exists

* set test result "Error"

* check device connected

* thread for monitoring device connection

* Minor changes

* check the device connection only before each test

* send testrun status using mqtt

* remove duplicatied line

* refactor setting remaining tests to error

* Pylint fixes

* pylint

* Use mqtt service instead of calling GET /status every 5 seconds. (#644)

* Use mqtt service instead of calling GET /status every 5 seconds.

* Adds tooltip (#638)

Adds tooltip

* Fix focus after profile delete - track by name (#640)

Fix focus after profile delete - track by name

* Update the requests dependency (#643)

* Update requests dependency

* Update requests dependency

* Update dependency in TLS test

* Update docker dependency

---------

Signed-off-by: J Boddey <boddey@google.com>

* remove unused output

* encode mqtt message to json

* Revert "Expired profile (#619)" (#645)

Prevent opening of Expired risk profile

* Improve documentation (#639)

* Improve docs

* Remove paragraph

* Text changes

* Fix text for the BE error

* Change tooltip (#650)

* Change tooltip

* Allows draft profiles to become expired (#636)

* Allow draft profiles to expire

* Move status method into risk profile class

* Use existing method

* Check for expiry in validate method

* Remove unused variable

* Build UI during package instead of install (#621)

* Build UI during package

* Fix local build

* Install npm

* Remove duplicate build message

* Fix ESLint

* Fix script

* Modify scripts

* Improve scripts

* Fix copy command

* Try installing package

* Depend on package job

* Add sudo

* Add sudo

* Troubleshoot

* Fix workflow

* Checkout source for prepare command

* Built ui within a container

* Mount src files for build instead of static copy in build image

* Attempt to fix actions

* Remove manual build container cleanup methods

* undo failed attempts to fix actions

* Fix path

* Remove -it flag

---------

Signed-off-by: J Boddey <boddey@google.com>
Co-authored-by: kurilova <sonnycactus@gmail.com>
Co-authored-by: jhughesbiot <jonathan.hughes@buildingsiot.com>

* Feature/risk in selected (#654)

* Adds risk to selected value

* Adds risk to selected value

---------

Co-authored-by: J Boddey <boddey@google.com>

* Show risk for each question in the Risk profile (#647)

* Show risk for each question in the Risk profile

* set top position to 0

---------

Co-authored-by: J Boddey <boddey@google.com>

* Use mqtt service instead of calling GET /status every 5 seconds.

* Use mqtt service instead of calling GET /status every 5 seconds.

* Use mqtt service instead of calling GET /status every 5 seconds.

* pylint

---------

Signed-off-by: J Boddey <boddey@google.com>
Co-authored-by: J Boddey <boddey@google.com>
Co-authored-by: Aliaksandr Nikitsin <aliaksandrn@google.com>
Co-authored-by: jhughesbiot <jonathan.hughes@buildingsiot.com>

* Allow ICMP response to DHCP messages in DHCP snooping test (#608)

* Allow ICMP response to DHCP messages

* Bug/unit test runtime (#655)

* Change base test module startup to allow setup script to run independent of module startup process
Update connection_module to allow for unit testing
Update unit test run script to use new process

* enable all unit tests
update google cert

* Remove binary fix lines from docker files
pylint updates

* pylint updates

---------

Co-authored-by: jhughesbiot <jonathan.hughes@buildingsiot.com>

* The risk profile saved with old format is shown improperly  while loading based on a new format (#664)

* Fill only fields that are present in profile

* GAR : The alt text for the expired risk profile should be communicated on Enter key (#662)

* Change Expired profile title on Enter; announce Expired profile title on Enter

* Update wording of tls cipher results (#671)

* Show error message if provided; show default message if no (#680)

* Test install on supported operating systems (#675)

* Test install on multiple versions

* Update step names

* Do not give Non-Compliant if error given

---------

Signed-off-by: J Boddey <boddey@google.com>
Co-authored-by: J Boddey <boddey@google.com>
Co-authored-by: Aliaksandr Nikitsin <aliaksandrn@google.com>
Co-authored-by: Sofia Kurilova <kurilova@google.com>

* Fix host module docker name

---------

Signed-off-by: J Boddey <boddey@google.com>
Co-authored-by: jhughesbiot <jonathan.hughes@buildingsiot.com>
Co-authored-by: Aliaksandr Nikitsin <aliaksandrn@google.com>
Co-authored-by: Sofia Kurilova <kurilova@google.com>
  • Loading branch information
4 people authored Aug 15, 2024
1 parent 6bbb803 commit dba2636
Show file tree
Hide file tree
Showing 20 changed files with 586 additions and 110 deletions.
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

0 comments on commit dba2636

Please sign in to comment.