Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Secure communication standard for IaaS infastructure #547

Open
5 of 8 tasks
markus-hentsch opened this issue Apr 3, 2024 · 15 comments · May be fixed by #548
Open
5 of 8 tasks

Secure communication standard for IaaS infastructure #547

markus-hentsch opened this issue Apr 3, 2024 · 15 comments · May be fixed by #548
Assignees
Labels
SCS-VP10 Related to tender lot SCS-VP10

Comments

@markus-hentsch
Copy link
Contributor

markus-hentsch commented Apr 3, 2024

As a customer I expect the communication channels to and between infrastructure components of an SCS cloud to be secured appropriately, so that in-transit data is protected.
As a CSP I want to establish secure communication channels adhering to the corresponding SCS standard the users can rely on.

Contents

  • Overview and classification of communication channels
  • References to the OpenStack Security Guide where applicable
  • TLS version and cipher restrictions

Definition of Done:

Please refer to scs-0001-v1 for details.

  • Proposal has been written with name of the form scs-xxxx-v1-slug.md (only substitute slug)
  • Proposal has the fields status, type, track set
  • Proposal has been voted upon in the corresponding team
  • Status has been changed into Draft, file renamed: xxxx replaced by document number
  • If applicable: test script has been written (this item may be moved into a separate issue so long as the state is Draft)
@markus-hentsch markus-hentsch self-assigned this Apr 3, 2024
@markus-hentsch markus-hentsch added the SCS-VP10 Related to tender lot SCS-VP10 label Apr 3, 2024
@markus-hentsch
Copy link
Contributor Author

Major communication channels that need to be secured:

# Classification Details Solution
1 Database backend traffic Replication and sync between database instances SSL/TLS
2 Database frontend traffic Communication between OpenStack services and databases SSL/TLS
3 Message queue traffic Message queue communication between OpenStack components as provided by oslo.messaging SSL/TLS
4 Internal API communication HTTP traffic to services registered as internal endpoints in the Keystone service catalog SSL/TLS
5 External API communication HTTP traffic to services registered as external endpoints in the Keystone service catalog SSL/TLS
6 Nova VM migration Nova VM migration data transfer traffic between compute nodes QEMU-native TLS

Resources:

@markus-hentsch
Copy link
Contributor Author

Most of the configuration adjustments proposed here cannot be verified via external tests unfortunately. Only the public-facing APIs can be checked for TLS by inspecting Keystone's service catalog, contacting each public endpoint and verifying its TLS handshake.

All the internal stuff would be up to dedicated audits with access to the infrastructure.

Speaking of TLS handshakes, I think we should also forbid using older/weak TLS versions and ciphers in the standard.

@markus-hentsch markus-hentsch linked a pull request Apr 4, 2024 that will close this issue
@markus-hentsch
Copy link
Contributor Author

I began adding TLS specifics to the standard based on the official guidelines on ssl.com1.

I think we should align this to the most commonly and broadly accepted current recommendations around TLS.

Footnotes

  1. https://www.ssl.com/guide/tls-standards-compliance/

@artificial-intelligence
Copy link
Contributor

I began adding TLS specifics to the standard based on the official guidelines on ssl.com1.

I think we should align this to the most commonly and broadly accepted current recommendations around TLS.

Footnotes

1. https://www.ssl.com/guide/tls-standards-compliance/ [↩](#user-content-fnref-1-cfaa4efba83e4b7037c3fc3cf637ce1e)

Might I ask why you choose this specific guide?

E.g. I think this guide is better: https://ssl-config.mozilla.org/ because it does not focus on compliance but on security.

@markus-hentsch
Copy link
Contributor Author

Might I ask why you choose this specific guide?

E.g. I think this guide is better: https://ssl-config.mozilla.org/ because it does not focus on compliance but on security.

No particular reason. I was just looking for some form of official consensus on current SSL/TLS recommendations to base the standard on. I guess the Mozilla ones12 would be a good alternative.

@martinmo had the same thought apparently: #548 (comment) :)

I will have a look.

Footnotes

  1. https://infosec.mozilla.org/guidelines/web_security.html#transport-layer-security-tlsssl

  2. https://wiki.mozilla.org/Security/Server_Side_TLS

@anjastrunk anjastrunk moved this from Backlog to Doing in Sovereign Cloud Stack Apr 15, 2024
@markus-hentsch
Copy link
Contributor Author

I've had a look and it seems that sslyze does indeed support checking against the Mozilla recommendations directly. We could simplify the maintenance effort for this standard by referencing Mozilla's recommendations. However, this would mean referencing recommendations which are also a moving target themselves potentially (how often does Mozilla update this?).
Also not sure how this would relate to the standard versioning and what a CSP has to test against at a given point in time exactly (version-pin sslyze? always upgrade sslyze before execution? etc.).

I've put it on the agenda for the next IaaS call.

@markus-hentsch
Copy link
Contributor Author

I've put it on the agenda for the next IaaS call.

We discussed this on the SIG Standardization / Certification call: SovereignCloudStack/minutes/sig-standardization/20240516.md#tracking-moving-targets-tls-recommendations-from-mozilla


I updated the standard and test script to use the Mozilla TLS recommendations instead after figuring out how that works with the SSLyze library.

Sadly, the library only ships the single most recent Mozilla TLS preset version at the time of the library version release1. So, when executing, you cannot choose between the versions of the recommendations. This means the recommendation version is coupled to the library version in a non-obvious way (different version numbers, requiring manual lookup).

We should pin the SSLyze library version for the test together with the JSON of the recommendation.

Footnotes

  1. https://github.com/nabla-c0d3/sslyze/tree/761892bf6a613726f272eb4e19b33faee2272b6f/sslyze/mozilla_tls_profile/

@markus-hentsch
Copy link
Contributor Author

Problem with parameterizing the SSLyze version using /pull/595

I looked at the implementation of #595 and tried to adjust the PR of this issue accordingly but it seems that the problem is not properly addressed yet.

Due to

Sadly, the library only ships the single most recent Mozilla TLS preset version at the time of the library version release.

... as stated above, parameterization is necessary when implementing the standard and executing tests.

This had been mentioned in #592 which was implemented in #595. However this did not consider the requirements.txt dilemma:

As a result, specifying the SSLyze library version in the scs-compatible-iaas.yaml would be "too late" in the process, as the SSLyze library will already have been installed during the Docker image build.

There seem to be dirty hacks to install pip packages from within Python code but I'm not a fan.

@mbuechse
Copy link
Contributor

That's unfortunate. I'm not sure there's a good solution for that, because we need to have a requirements.txt that works for all tests, so it should not be dependent on the parameter. Therefore, I would assume that this test needs to create a new virtual environment, install the correct library, and then run python in a subprocess with some script, or something similar.

@mbuechse
Copy link
Contributor

Another idea would be to vendor sslyze somehow and do so for multiple versions at a time, so we could select the version that we want at runtime (import time) and import that one.

@markus-hentsch
Copy link
Contributor Author

Solution ideas for the SSLyze versioning dilemma

Context: #547 (comment)

a) Modifying the call to the SSLyze library to change version

  • does not seem possible: since the JSON is pretty much hardcoded12 the library calls are unable to be modified sufficiently

b) Changing the virtualenv from within the script

  • idea: from within the virtualenv, overwrite the installed SSLyze package with the desired version
  • there seem to be possible pip calls that can be made from within a Python script
  • problem: this requires internet connection from within the execution environment which is currently not a requirement for the tests afaict as they seem self-contained so far

c) Vendoring the necessary package versions

  • as suggested by Matthias
  • idea:
    • at built time crawl the YAMLs for SSLyze versions and package them into the Docker image
      • alternative to simplify the process: simply vendor the last N versions of SSLyze (removes need for YAML parsing)
    • at runtime: install the desired SSLyze version by using method b explained above
  • problems:
    • the SSLyze library has dependencies; to properly install a specific version, we would need to vendor all dependencies in the correct version as well
    • SSLyze version is decoupled from the Mozilla TLS JSON versioning; this means that we would also need to record a mapping between both to select the correct SSLyze version3

d) Monkey patching a different Mozilla JSON in

  • idea:
    • at built time: only vendor the last N JSON files of the Mozilla TLS recommendations
    • at runtime: monkey patch the MozillaTlsConfigurationChecker.get_default() method to point to the desired JSON or replace the hardcoded JSON file's contents directly
  • problems:
    • when the version pin of the SSLyze library is updated, checks need to be done to ensure that the monkey patching still works and the SSLyze implementation has not changed at this part

e) Upstream contribution or fork

  • idea:
    • as in method d, vendor the Mozilla JSONs at built time
    • instead of monkey patching the JSON path in like described in method d, fork or contribute to SSLyze to introduce an optional call argument which allows changing the path to the JSON
  • problems:
    • fork maintainership is hard long-term
    • success/acceptance of upstream contribution is not guaranteed

Thoughts

  • options a, b and c seem too brittle
  • option d could provide a short-term solution while we attempt an upstream contribution as per e
    • if the upstream contribution is unsuccessful, option d could also be kept long-term as a compromise
  • a SSLyze fork maintainership is out of the question I think

Footnotes

  1. https://github.com/nabla-c0d3/sslyze/blob/761892bf6a613726f272eb4e19b33faee2272b6f/setup.py#L49

  2. https://github.com/nabla-c0d3/sslyze/blob/761892bf6a613726f272eb4e19b33faee2272b6f/sslyze/mozilla_tls_profile/mozilla_config_checker.py#L104

  3. when parameterizing the Secure Connections standard in the YAML, we want to specify the Mozilla JSON version first and foremost because this is the crucial information for the CSP, the SSLyze version is only relevant for testing purposes

@mbuechse
Copy link
Contributor

mbuechse commented Jun 28, 2024

this requires internet connection from within the execution environment which is currently not a requirement for the tests afaict as they seem self-contained so far

Good point!

I think we can work around the following problem mentioned in c:

the SSLyze library has dependencies; to properly install a specific version, we would need to vendor all dependencies in the correct version as well

as follows:

We could indeed prepare one venv per sslyze version that we want to have (maybe prepare during build time, but it could also happen during "dev time"). Then we use subprocess to run something like /bin/bash -c ". venv-sslyze-vX && python3 check.py"

The script check.py would use sslyze (and not much more, if possible) and produce some output on stdout or stderr that the actual test script can then parse and turn into a verdict.

@markus-hentsch
Copy link
Contributor Author

markus-hentsch commented Jun 28, 2024

a) Modifying the call to the SSLyze library to change version

  • does not seem possible: since the JSON is pretty much hardcoded the library calls are unable to be modified sufficiently

Au contraire! After digging and experimenting a bit more, the following has proven to work:

from sslyze.mozilla_tls_profile.mozilla_config_checker import (
    MozillaTlsConfigurationChecker,
    _MozillaTlsProfileAsJson)

json_file = open(...)
mozilla_json_preset = json.load(json_file)
parsed_profile = _MozillaTlsProfileAsJson(**mozilla_json_preset)
mozilla_checker = MozillaTlsConfigurationChecker(parsed_profile)
mozilla_checker.check_server(...)

It is the custom alternative to:

mozilla_checker = MozillaTlsConfigurationChecker.get_default()

and mimicks its behavior regarding loading the JSON file.

We don't need to fiddle with the SSLyze version at all (as long as the implementation does not change the imported classes and functions) and only need to ship and reference the Mozilla JSONs.

I vastly prefer this over the other alternatives now. EDIT: implemented changes in the test script.

@martinmo
Copy link
Member

martinmo commented Jul 2, 2024

+1 from me for solution (a) from #547 (comment)

I think this is a good compromise, even if _MozillaTlsProfileAsJson doesn't seem to be intended as public API (mind the _ prefix). At least in the past three years there haven't been too many or drastic changes to the mozilla_tls_profile (sub)package (see https://github.com/nabla-c0d3/sslyze/commits/release/sslyze/mozilla_tls_profile).

Just as a side note, for the venv per sslyze approach you could also use pipx to install several versions in parallel and avoid having to manage the venv stuff manually. Something like this (not really tested, but in principle this worked as I have used this --suffix machinery to test multiple poetry versions in parallel):

pipx install --suffix 6.0 sslyze==6.0.0  # installs as sslyze6.0
pipx install --suffix 5.2 sslyze==5.2.0  # installs as sslyze5.2

@artificial-intelligence
Copy link
Contributor

fwiw my patch to unify the haproxy TLS settings and to update them to a modern standard was finally merged today :https://review.opendev.org/c/openstack/kolla-ansible/+/915403

so on new openstack releases you should only see properly secured TLS API endpoints (if TLS is enabled).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
SCS-VP10 Related to tender lot SCS-VP10
Projects
Status: Doing
Development

Successfully merging a pull request may close this issue.

4 participants