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).
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. configshell- fb, configshell- fb and python3-rtslib-fb are required at runtime user.target. Both run as root, but do specify the s=yes, ProtectHome=true, ProtectSystem=full, without- manpage warnings for the 2 services.
- All build-depends in main except for: python3-
python3-mock, python3-pytest, python3-rtslib-fb. Only
python3-
(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-
PrivateDevice
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-
- Spawns subprocesses using subprocess. check_output. check_output helper in ceph_iscsi_ config/ utils.py ceph/iscsi- gateway. cfg). targetinfo/ <target_ iqn>), opens a file in iscsi-gateway. cfg) which client. py:Client. set_auth py:Target. ui_command_ auth). config/ client. py). config/ target. py:GWTarget. _exists tests if a configfs path h/<target_ iqn> endpoint. This may be fb.utils. normalize_ wwn (as the regexp there won't reject 12.foo. bar/../ ../../. ./../.. "). However, ceph/iscsi- gateway. cfg).
- 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.
(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/
- One API endpoint (/api/_
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/
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/
and gwcli/gateway.
- 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_
- 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_
exists and derives the path from an argument that looks like it can be
provided via the /api/_targetaut
susceptible to path traversal, despite the argument being sanitized
via rtslib_
an IQN that might start with a valid name but then contain other path
components, such as "iqn.0123-
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/
- 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).