Skip to content

Commit

Permalink
Merge pull request #195 from towercomputers/dev
Browse files Browse the repository at this point in the history
v0.3.0
  • Loading branch information
ouziel-slama authored Dec 2, 2023
2 parents ee413de + 3187d83 commit 63f5523
Show file tree
Hide file tree
Showing 40 changed files with 978 additions and 233 deletions.
49 changes: 49 additions & 0 deletions .github/workflows/bandit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.

# Bandit is a security linter designed to find common security issues in Python code.
# This action will run Bandit on your codebase.
# The results of the scan will be found under the Security tab of your repository.

# https://github.com/marketplace/actions/bandit-scan is ISC licensed, by abirismyname
# https://pypi.org/project/bandit/ is Apache v2.0 licensed, by PyCQA

name: Bandit
on:
push:
branches: [ "master", "dev" ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ "master" ]

jobs:
bandit:
permissions:
contents: read # for actions/checkout to fetch code
security-events: write # for github/codeql-action/upload-sarif to upload SARIF results
actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status

runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Bandit Scan
uses: shundor/python-bandit-scan@9cc5aa4a006482b8a7f91134412df6772dbda22c
with: # optional arguments
# exit with 0, even with results found
exit_zero: true # optional, default is DEFAULT
# Github token of the repository (automatically created by Github)
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information.
# File or directory to run bandit on
# path: # optional, default is .
# Report only issues of a given severity level or higher. Can be LOW, MEDIUM or HIGH. Default is UNDEFINED (everything)
# level: # optional, default is UNDEFINED
# Report only issues of a given confidence level or higher. Can be LOW, MEDIUM or HIGH. Default is UNDEFINED (everything)
# confidence: # optional, default is UNDEFINED
# comma-separated list of paths (glob patterns supported) to exclude from scan (note that these are in addition to the excluded paths provided in the config file) (default: .svn,CVS,.bzr,.hg,.git,__pycache__,.tox,.eggs,*.egg)
# excluded_paths: # optional, default is DEFAULT
# comma-separated list of test IDs to skip
# skips: # optional, default is DEFAULT
# path to a .bandit file that supplies command line arguments
# ini_path: # optional, default is DEFAULT
80 changes: 80 additions & 0 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"

on:
push:
branches: [ "master", "dev" ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ "master" ]

jobs:
analyze:
name: Analyze
# Runner size impacts CodeQL analysis time. To learn more, please see:
# - https://gh.io/recommended-hardware-resources-for-running-codeql
# - https://gh.io/supported-runners-and-hardware-resources
# - https://gh.io/using-larger-runners
# Consider using larger runners for possible analysis time improvements.
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }}
permissions:
actions: read
contents: read
security-events: write

strategy:
fail-fast: false
matrix:
language: [ 'python' ]
# CodeQL supports [ 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift' ]
# Use only 'java-kotlin' to analyze code written in Java, Kotlin or both
# Use only 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support

steps:
- name: Checkout repository
uses: actions/checkout@v3

# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.

# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality


# Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2

# ℹ️ Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun

# If the Autobuild fails above, remove it and uncomment the following three lines.
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.

# - run: |
# echo "Run, Build Application using script"
# ./location_of_script_within_repo/buildscript.sh

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
with:
category: "/language:${{matrix.language}}"
33 changes: 33 additions & 0 deletions .github/workflows/license_scanner.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: License Scanner

on:
push:
branches: [ "master", "dev" ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ "master" ]

jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.11"]
steps:
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v3
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install license_scanner
pip install -e tower-lib
- name: Analysing dependencies with licence_scanner
run: |
python tower-lib/towerlib/utils/checklicences.py
- name: Upload SARIF
uses: github/codeql-action/upload-sarif/@v2
with:
sarif_file: license_scanner.sarif
34 changes: 34 additions & 0 deletions .github/workflows/pylint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: Pylint

on:
push:
branches: [ "master", "dev" ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ "master" ]

jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.11"]
steps:
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v3
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install pylint
pip install pylint-sarif-unofficial
pip install -e tower-lib
- name: Analysing the code with pylint
run: |
pylint2sarif $(git ls-files '*.py') || true
- name: Upload SARIF
uses: github/codeql-action/upload-sarif/@v2
with:
sarif_file: pylint.sarif
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
**TowerOS** is a high-assurance operating system for paranoid individuals and high-value targets. TowerOS has an unusual architecture: it combines *multiple, independent computers* into a single virtual system with a composited user interface. Each security domain is regelated to a separate *host* (e.g. a Raspberry Pi), and the user runs their applications from a *thin client* (e.g. a laptop) over a LAN using standard network protocols (SSH and NX). It's sort of like [Qubes OS](https://qubes-os.org), but inside-out—instead of dividing a single computer up into multiple security domains at the level of the hypervisor, TowerOS combines multiple computers together with the smallest trusted computing base possible while still providing a user-friendly system. For more information, please refer to the **[official project documentation](https://towercomputers.github.io/toweros/)**.
**TowerOS** is a high-assurance operating system for paranoid individuals and high-value targets. TowerOS has an unusual architecture: it combines *multiple, independent computers* into a single virtual system with a composited user interface. Each security domain is relegated to a separate *host* (e.g. a Raspberry Pi), and the user runs their applications from a *thin client* (e.g. a laptop) over a LAN using standard network protocols (SSH and NX). It's sort of like [Qubes OS](https://qubes-os.org), but inside-out—instead of dividing a single computer up into multiple security domains at the level of the hypervisor, TowerOS combines multiple computers together with the smallest trusted computing base possible while still providing a user-friendly system. For more information, please refer to the **[official project documentation](https://towercomputers.github.io/toweros/)**.
84 changes: 67 additions & 17 deletions tower-cli/towercli/commands/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,37 +69,87 @@ def add_args(argparser):
choices=['0', '1'],
required=False
)
run_parser.add_argument(
'--waypipe',
help="""Use `waypipe` instead `nx`. (Default: False)""",
required=False,
action='store_true',
default=False
)
run_parser.add_argument(
'--wp-compress',
help="""Select the compression method applied to data transfers. Options are none (for high-bandwidth networks), lz4 (intermediate), zstd (slow connection). The default compression is none. The compression level can be chosen by appending = followed by a number. For example, if C is zstd=7, waypipe will use level 7 Zstd compression.""",
required=False,
)
run_parser.add_argument(
'--wp-threads',
help="""Set the number of total threads (including the main thread) which a waypipe instance will create. These threads will be used to parallelize compression operations. This flag is passed on to waypipe server when given to waypipe ssh. The flag also controls the thread count for waypipe bench. The default behavior (choosable by setting T to 0) is to use half as many threads as the computer has hardware threads available.""",
type=int,
required=False
)
run_parser.add_argument(
'--wp-video',
help="""Compress specific DMABUF formats using a lossy video codec. Opaque, 10-bit, and multiplanar formats, among others, are not supported. V is a comma separated list of options to control the video encoding. Using the --video flag without setting any options is equivalent to using the default setting of: --video=sw,bpf=120000,h264. Later options supersede earlier ones (see `man waypipe` for more options).""",
required=False
)


def check_nx_args(args, parser_error):
links = ['modem', 'isdn', 'adsl', 'wan', 'lan', 'local']
regex = r'^[0-9]+[kmgKMG]{1}$'
if not re.match(regex, args.nx_link) and args.nx_link not in links:
if args.nx_link and not re.match(regex, args.nx_link) and args.nx_link not in links:
parser_error("Invalid link name")
if not re.match(regex, args.nx_images) and not args.nx_images.isdigit():
if args.nx_images and not re.match(regex, args.nx_images) and not args.nx_images.isdigit():
parser_error("Invalid images size")
if not re.match(regex, args.nx_cache) and not args.nx_cache.isdigit():
if args.nx_cache and not re.match(regex, args.nx_cache) and not args.nx_cache.isdigit():
parser_error("Invalid cache size")

def check_waypipe_args(args, parser_error):
if args.wp_compress:
compressions = ['none', 'lz4', 'zstd']
regex = r'^(lz4|zstd)=[0-9]{1}$'
if not re.match(regex, args.wp_compress) and args.wp_compress not in compressions:
parser_error("Invalid compression method")
if args.wp_video:
options = args.wp_video.split(',')
regex_bpf = r'^bpf=[0-9]{1,6}$'
for option in options:
if not re.match(regex_bpf, option) and option not in ['sw', 'hw', 'h264', 'vp9']:
parser_error("Invalid video option")

def check_args(args, parser_error):
config = sshconf.get(args.host_name[0])
if config is None:
parser_error("Unknown host.")
check_nx_args(args, parser_error)
if args.waypipe:
check_waypipe_args(args, parser_error)
else:
check_nx_args(args, parser_error)

def execute(args):
if os.getenv('DISPLAY'):
nxagent_args = {
"link": args.nx_link,
"limit": args.nx_limit,
"images": args.nx_images,
"cache": args.nx_cache,
}
if args.nx_stream:
nxagent_args["stream"] = args.nx_stream
if args.nx_data:
nxagent_args["data"] = args.nx_data
if args.nx_delta:
nxagent_args["delta"] = args.nx_delta
gui.run(args.host_name[0], nxagent_args, *args.run_command)
if args.waypipe:
waypipe_args = []
if args.wp_compress:
waypipe_args += ["--compress", args.wp_compress]
if args.wp_threads:
waypipe_args += ["--threads", args.wp_threads]
if args.wp_video:
waypipe_args += ["--video", args.wp_video]
gui.run_waypipe(args.host_name[0], waypipe_args, *args.run_command)
else:
nxagent_args = {
"link": args.nx_link,
"limit": args.nx_limit,
"images": args.nx_images,
"cache": args.nx_cache,
}
if args.nx_stream:
nxagent_args["stream"] = args.nx_stream
if args.nx_data:
nxagent_args["data"] = args.nx_data
if args.nx_delta:
nxagent_args["delta"] = args.nx_delta
gui.run(args.host_name[0], nxagent_args, *args.run_command)
else:
raise TowerException("`tower run` requires a running desktop environment. Use `startx` to start X.Org.")
10 changes: 8 additions & 2 deletions tower-cli/towercli/commands/status.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,21 @@
from towerlib import sshconf

def add_args(argparser):
argparser.add_parser(
status_parser = argparser.add_parser(
'status',
help="Check the status of all hosts in the Tower system."
)
status_parser.add_argument(
'--host',
help="""Host name""",
required=False,
default=None
)

# pylint: disable=unused-argument
def check_args(args, parser_error):
pass

# pylint: disable=unused-argument
def execute(args):
print(json.dumps(sshconf.status(), indent=4))
print(json.dumps(sshconf.status(args.host), indent=4))
21 changes: 21 additions & 0 deletions tower-lib/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ name = "tower-lib"
dynamic = ["version"]
description = "Tower library"
readme = "../README.md"
licence = "Apache-2.0"
license-files = { paths = ["../LICENSE"] }
requires-python = ">=3.9"
classifiers = [
Expand Down Expand Up @@ -35,3 +36,23 @@ include = ["towerlib", "toweros-installers"]

[tool.hatch.version]
path = "towerlib/__about__.py"

[tool.license_scanner]
allowed-licences = [
'Apache license',
'Apache license 2.0',
'BSD 2-clause license',
'BSD 3-clause license',
'BSD license',
'GNU general public license v2 (gplv2)',
'GNU lesser general public license',
'GNU lesser general public license v2 (lgplv2)',
'GNU lesser general public license v3 (lgplv3)',
'ISC license (iscl)', 'MIT license',
'Mozilla public license 2.0 (mpl 2.0)',
'Python software foundation license',
'The Unlicense (Unlicense)',
]
allowed-packages = [
'tower-cli', 'tower-lib',
]
2 changes: 1 addition & 1 deletion tower-lib/towerlib/__about__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "0.2.1"
__version__ = "0.3.0"
Loading

0 comments on commit 63f5523

Please sign in to comment.