Comment 67 for bug 1854362

Revision history for this message
Chris Coulson (chrisccoulson) wrote :

I reviewed ceph-iscsi 3.4-0ubuntu2 as checked into focal. This shouldn't
be considered a full audit but rather a quick gauge of maintainability.

ceph-iscsi is a set of tools for managing LIO gateways for Ceph. It
consists of 2 services providing REST APIs - one for obtaining gateway
node statistics and another for providing the gateway API, restoring
gateway state and keeping gateway nodes in sync. Under the hood, it uses
rtslib for configuring the gateway via the LIO interfaces, and Ceph
backstores are implemented in userspace (in tcmu). A command line tool is
provided for managing the gateway nodes, which communicates with the
gateway node's API.

- No CVE history.
- All build-depends in main except for: python3-configshell-fb,
  python3-mock, python3-pytest, python3-rtslib-fb. Only
  python3-configshell-fb and python3-rtslib-fb are required at runtime
  (this MIR).
- Depends on python3-openssl (crypto), python3-requests (HTTP) and
  python-flask (werkzeug based web framework).
- Maintainer scripts just contain some debhelper snippets from dh_python3,
  dh_installinit and dh_installsystemd.
- Provides 2 services:
 - rbd-target-gw:
  - This is a simple flask app that provides a REST API with 2 endpoints
    on port 9287 (configurable) to obtain gateway statistics.
  - The /metrics endpoint just provides a formatted summary of a bunch of
    properties from configfs (via rtslib).
 - rbd-target-api:
  - This is a flask app that provides a REST API on port 5000
    (configurable) for configuring the gateways and restoring their state.
  - Some of the API is used by gwcli, and some of it is considered
    "internal" for the purposes of syncrhonizing configuration on gateway
    nodes.
 - Both services run as root.
 - The APIs are publicly available by default, although this is
   configurable.
 - The APIs are exported using HTTP by default. They can be configured to
   use HTTPS.
- Contains 2 systemd units for starting the 2 REST services as part of
  multi-user.target. Both run as root, but do specify the
  PrivateDevices=yes, ProtectHome=true, ProtectSystem=full,
  PrivateTmp=true options.
- No D-Bus services.
- No setuid binaries.
- 3 binaries in PATH: the 2 services (rbd-target-api, rbd-target-gw) and a CLI
  tool (gwcli) for managing the Ceph iSCSI gateway.
- No sudo fragments.
- No policykit.
- No udev rules.
- Some limited unit tests that test a few classes in the ceph_iscsi_config
  python package. These run as part of the build and all pass. No
  autopkgtests.
- No cronjobs.
- Build logs are clean - just some deprecation warnings that seem to come
  from pyudev. Only lintian warnings are a couple of
  binary-without-manpage warnings for the 2 services.

- Spawns subprocesses using subprocess.check_output.
 - gwcli uses the default shell=False
 - rbd-target-api uses shell=True, but doesn't seem to be using it with
   arguments from untrusted sources.
 - There is a subprocess.check_output helper in ceph_iscsi_config/utils.py
   (shellcommand) that appears to be unused.
- Opens files for reading in a few places using a mixture of hard-coded
  paths and paths specified in the config file
  (/etc/ceph/iscsi-gateway.cfg).
  - One API endpoint (/api/_targetinfo/<target_iqn>), opens a file in
    configfs for reading and returns the contents using a path derived
    from the received target IQN. There is a check that the IQN
    corresponds to target in the gateway configuration though.
- It's not reading from untrusted files (just /etc and configfs).
- No files opened for writing.
- Plenty of logging using python's logging module. Services log to
  syslog at level logging.INFO and a rotating file handler in /var/log at
  a custom level (configured in /etc/ceph/iscsi-gateway.cfg) which
  defaults to logging.DEBUG.
- The default log level for gwcli seems to be logging.DEBUG, and it
  appears to log to ~/gwcli.log by default. I'm suspicious that it is
  logging passwords in a couple of places (gwcli/client.py:Client.set_auth
  and gwcli/gateway.py:Target.ui_command_auth).
- Only use of environment is by gwcli to read PATH in order to determine
  if the ceph binary exists.
- No evidence of privileged operations.
- Makes use of python-cryptography using the default backend (openssl?)
  for encrypting target passwords with RSA-OAEP using SHA-256 hashing
  (see class CHAP in ceph_iscsi_config/client.py).
- No tempfile usage.
- Uses python-flask for providing 2 REST APIs.
 - Internal exceptions are caught by flask and result in a generic 500
   response without exposing debug information by default.
 - All APIs that accept arguments require authentication as the gateway
   API user.
 - No paths are provided as arguments, although arguments are used to
   derive configfs paths in some API endpoints.
  - ceph_iscsi_config/target.py:GWTarget._exists tests if a configfs path
    exists and derives the path from an argument that looks like it can be
    provided via the /api/_targetauth/<target_iqn> endpoint. This may be
    susceptible to path traversal, despite the argument being sanitized
    via rtslib_fb.utils.normalize_wwn (as the regexp there won't reject
    an IQN that might start with a valid name but then contain other path
    components, such as "iqn.0123-12.foo.bar/../../../../../.."). However,
    I don't think there's a way to actually leak information here as the
    particular API endpoint always returns success and the lack of
    presence of a path doesn't appear to trigger any exceptions. Still,
    this could be a bit more defensive.
- No webkit.
- All gateway REST API endpoints other than /api require authentication
  as the gateway API user using HTTP basic auth. The username and
  password are specified in the gateway configuration file
  (/etc/ceph/iscsi-gateway.cfg).
 - Note that the password for the gateway API user is stored in plaintext.
   Is there a reason not to salt and hash this?
 - Some API endpoints also use source IP filtering on top of the basic
   auth.

Security team ACK for promoting ceph-iscsi to main, although I'd like
someone to confirm or not whether gwcli is writing passwords to a logfile
and get that fixed if it is. (I don't have a setup in which I was able to
test this).