-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' into feat/cluster-hardening-tests
- Loading branch information
Showing
17 changed files
with
1,033 additions
and
48 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
htmlcov/ | ||
.coverage | ||
.secret |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
#!/usr/bin/env python3 | ||
# vim: set ts=4 sw=4 et: | ||
# | ||
# add_subject.py | ||
# | ||
# (c) Matthias Büchse <[email protected]> | ||
# SPDX-License-Identifier: Apache-2.0 | ||
import base64 | ||
import getpass | ||
import os | ||
import os.path | ||
import re | ||
import shutil | ||
import signal | ||
import subprocess | ||
import sys | ||
|
||
try: | ||
from passlib.context import CryptContext | ||
import argon2 # noqa:F401 | ||
except ImportError: | ||
print('Missing passlib and/or argon2. Please do:\npip install passlib argon2_cffi', file=sys.stderr) | ||
sys.exit(1) | ||
|
||
# see ../compliance-monitor/monitor.py | ||
CRYPTCTX = CryptContext(schemes=('argon2', 'bcrypt'), deprecated='auto') | ||
SSH_KEYGEN = shutil.which('ssh-keygen') | ||
SUBJECT_RE = re.compile(r"[a-zA-Z0-9_\-]+") | ||
|
||
|
||
def main(argv, cwd): | ||
if len(argv) != 1: | ||
raise RuntimeError("Need to supply precisely one argument: name of subject") | ||
subject = argv[0] | ||
print(f"Attempt to add subject {subject!r}") | ||
keyfile_path = os.path.join(cwd, '.secret', 'keyfile') | ||
tokenfile_path = os.path.join(cwd, '.secret', 'tokenfile') | ||
if os.path.exists(keyfile_path): | ||
raise RuntimeError(f"Keyfile {keyfile_path} already present. Please proceed manually") | ||
if os.path.exists(tokenfile_path): | ||
raise RuntimeError(f"Tokenfile {tokenfile_path} already present. Please proceed manually") | ||
if not SUBJECT_RE.fullmatch(subject): | ||
raise RuntimeError(f"Subject name {subject!r} using disallowed characters") | ||
sanitized_subject = subject.replace('-', '_') | ||
print("Creating API key...") | ||
while True: | ||
password = getpass.getpass("Enter passphrase: ") | ||
if password == getpass.getpass("Repeat passphrase: "): | ||
break | ||
print("No match. Try again...") | ||
token = base64.b64encode(f"{subject}:{password}".encode('utf-8')) | ||
hash_ = CRYPTCTX.hash(password) | ||
with open(tokenfile_path, "wb") as fileobj: | ||
os.fchmod(fileobj.fileno(), 0o600) | ||
fileobj.write(token) | ||
print("Creating key file using `ssh-keygen`...") | ||
subprocess.check_call([SSH_KEYGEN, '-t', 'ed25519', '-C', sanitized_subject, '-f', keyfile_path, '-N', '', '-q']) | ||
with open(keyfile_path + '.pub', "r") as fileobj: | ||
pubkey_components = fileobj.readline().split() | ||
print(f''' | ||
The following SECRET files have been created: | ||
- {keyfile_path} | ||
- {tokenfile_path} | ||
They are required for submitting test reports. You MUST keep them secure and safe. | ||
Insert the following snippet into compliance-monitor/bootstrap.yaml: | ||
- subject: {subject} | ||
api_keys: | ||
- "{hash_}" | ||
keys: | ||
- public_key: "{pubkey_components[1]}" | ||
public_key_type: "{pubkey_components[0]}" | ||
public_key_name: "primary" | ||
Make sure to submit a pull request with the changed file. Otherwise, the reports cannot be submitted. | ||
''', end='') | ||
|
||
|
||
if __name__ == "__main__": | ||
try: | ||
sys.exit(main(sys.argv[1:], cwd=os.path.dirname(sys.argv[0]) or os.getcwd()) or 0) | ||
except RuntimeError as e: | ||
print(str(e), file=sys.stderr) | ||
sys.exit(1) | ||
except KeyboardInterrupt: | ||
print("Interrupted", file=sys.stderr) | ||
sys.exit(128 + signal.SIGINT) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
# Secure Connections Standard Test Suite | ||
|
||
## Test Environment Setup | ||
|
||
> **NOTE:** The test execution procedure does not require cloud admin rights. | ||
A valid cloud configuration for the OpenStack SDK in the shape of "`clouds.yaml`" is mandatory[^1]. | ||
**This file is expected to be located in the current working directory where the test script is executed unless configured otherwise.** | ||
|
||
[^1]: [OpenStack Documentation: Configuring OpenStack SDK Applications](https://docs.openstack.org/openstacksdk/latest/user/config/configuration.html) | ||
|
||
The test execution environment can be located on any system outside of the cloud infrastructure that has OpenStack API access. | ||
Make sure that the API access is configured properly in "`clouds.yaml`". | ||
|
||
It is recommended to use a Python virtual environment[^2]. | ||
Next, install the libraries required by the test suite: | ||
|
||
```bash | ||
pip3 install openstacksdk sslyze | ||
``` | ||
|
||
> Note: the version of the sslyze library determines the [version of the Mozilla TLS recommendation JSON](https://wiki.mozilla.org/Security/Server_Side_TLS#JSON_version_of_the_recommendations) that it checks against. | ||
Within this environment execute the test suite. | ||
|
||
[^2]: [Python 3 Documentation: Virtual Environments and Packages](https://docs.python.org/3/tutorial/venv.html) | ||
|
||
## Test Execution | ||
|
||
The test suite is executed as follows: | ||
|
||
```bash | ||
python3 tls-checker.py --os-cloud mycloud | ||
``` | ||
|
||
As an alternative to "`--os-cloud`", the "`OS_CLOUD`" environment variable may be specified instead. | ||
The parameter is used to look up the correct cloud configuration in "`clouds.yaml`". | ||
For the example command above, this file should contain a `clouds.mycloud` section like this: | ||
|
||
```yaml | ||
--- | ||
clouds: | ||
mycloud: | ||
auth: | ||
auth_url: ... | ||
... | ||
... | ||
``` | ||
|
||
For any further options consult the output of "`python3 tls-checker.py --help`". | ||
|
||
### Script Behavior & Test Results | ||
|
||
The script will print all actions and passed tests to `stdout`. | ||
|
||
If all tests pass, the script will return with an exit code of `0`. | ||
|
||
If any test fails, the script will halt, print the exact error to `stderr` and return with a non-zero exit code. | ||
|
||
Any tests that indicate a recommendation of the standard is not met, will print a warning message under the corresponding endpoint output. | ||
However, unmet recommendations will not count as errors. |
Oops, something went wrong.