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

K8SSAND-962 ⁃ Investigate making the root file system in cassandra container read-only #199

Closed
1 task done
jsanda opened this issue Oct 11, 2021 · 7 comments · Fixed by #661
Closed
1 task done
Assignees
Labels
done Issues in the state 'done' enhancement New feature or request security

Comments

@jsanda
Copy link
Contributor

jsanda commented Oct 11, 2021

Why do we need it?
The root file system should be read-only for improved security. This is considered a best practice for security.

#196 was created specifically for DSE. The goal for this ticket is to address both OSS Cassandra and DSE. If it turns out that there are substantially different changes required for Cassandra vs DSE, then they should be addressed in separate PRs.

Here is an example manifest that configures the cassandra container with a read-only root file system:

apiVersion: cassandra.datastax.com/v1beta1
kind: CassandraDatacenter
metadata:
  name: dc1
spec:
  clusterName: test
  serverType: cassandra
  serverVersion: "4.0.0"
  systemLoggerImage:
  serverImage:
  size: 1
  storageConfig:
    cassandraDataVolumeClaimSpec:
      storageClassName: standard
      accessModes:
        - ReadWriteOnce
      resources:
        requests:
          storage: 5Gi
  podTemplateSpec:
    spec:
      containers:
        - name: "cassandra"
          securityContext:
            readOnlyRootFilesystem: true
            runAsNonRoot: true
        config:
    jvm-server-options:
      initial_heap_size: "800M"
      max_heap_size: "800M"

The cassandra goes into a crash loop with this in the log:

Starting Management API
cp: cannot create regular file '/opt/cassandra/conf/cassandra-env.sh': Read-only file system
cp: cannot create regular file '/opt/cassandra/conf/cassandra-rackdc.properties': Read-only file system
cp: cannot create regular file '/opt/cassandra/conf/cassandra.yaml': Read-only file system
cp: cannot create regular file '/opt/cassandra/conf/jvm11-server.options': Read-only file system
cp: cannot create regular file '/opt/cassandra/conf/jvm8-server.options': Read-only file system
cp: cannot create regular file '/opt/cassandra/conf/jvm.options': Read-only file system
cp: cannot create regular file '/opt/cassandra/conf/jvm-server.options': Read-only file system
cp: cannot create regular file '/opt/cassandra/conf/logback.xml': Read-only file system

Environment

  • Cass Operator version:
    v1.8.0

Anything else we need to know?:
We have already implemented a solution (or at least partial) in the k8ssandra Helm chart. Look at the cassdc.yaml template here. Here are the highlights:

  • Add a cassandra-config volume to be used to /etc/cassandra
  • The base-config-init init container copies out of box configs to cassandra-config
  • The server-config-init init container (i.e., config builder) runs and writes files to the server-config volume
  • The cassandra container mounts server-config at /config
  • The cassandra container mounts cassandra-config at /etc/cassandra
  • The entry point script of the cassandra container copies files from /config to /etc/cassandra

Again this what is already done in k8ssandra. We basically need to backport it.

Fixes

Preview Give feedback
  1. bug done

┆Issue is synchronized with this Jira Task by Unito
┆epic: Security Phase II
┆friendlyId: K8SSAND-962
┆priority: Medium

@jsanda jsanda added enhancement New feature or request security labels Oct 11, 2021
@jsanda jsanda self-assigned this Oct 11, 2021
jsanda added a commit to jsanda/management-api-for-apache-cassandra that referenced this issue Oct 12, 2021
emerkle826 pushed a commit to k8ssandra/management-api-for-apache-cassandra that referenced this issue Oct 13, 2021
@jsanda
Copy link
Contributor Author

jsanda commented Oct 15, 2021

There are additional changes needed. The management-api writes to /opt. Logs are written to /var/log/cassandra.

This makes a number of places where we need to introduce volume mounts. This begs the question of whether we want to continue using init containers to copy things around as we are currently doing or make changes in the images themselves.

I did some prototyping for this earlier in the week. I pushed it here https://github.com/jsanda/cass-operator-1/tree/non-root-fs-cassandra.

I do not think that the current solution with copying stuff with init containers is a scalable and maintainable solution. I think we would we better off in the long run to update the images with the necessary changes. Note that investigation is still required to determined what all is necessary.

The management-api uses base images of Cassandra from https://github.com/docker-library/cassandra. We might need a different base image that is designed with a read-only root file system in mind.

Ultimately I think we have to configure the containers with read-only root file systems to discover all the changes that are necessary. I will revisit my prototype to get a better sense of what is involved and then start trying to break the work down into smaller tickes.

@jsanda
Copy link
Contributor Author

jsanda commented Oct 15, 2021

I thought some more about config files/directories, /etc/cassandra in particular. Here is what I propose we do:

Store all config files in a ConfigMap. It becomes part of the operator installation. We need a ConfigMap for each Cassandra version that the operator supports. The ConfigMap can be installed via Kustomize or Helm along with all other operator resources. To be clear, I am not suggesting we generate the ConfigMap in the operator Go code.

We add a ConfigMap volume to the StatefulSet. The ConfigMap volume should be ready only. It will have the appropriate base configuration. Each pod needs its own configuration though. We add an EmptyDir volume for /etc/cassandra.

An init container with a volume mount for the ConfigMap will copy the base configuration onto the /etc/cassandra volume. This init container should run before any other init containers.

Currently the management-api's entry point script copies files generated by config-builder over to /etc/cassandra (see here). I don't think that will be necessary any more. The config builder init container can write directly to the /etc/cassandra volume mount.

In k8ssandra I think we could get rid of the base-config-init init container as well.

@emerkle826
Copy link
Contributor

An init container with a volume mount for the ConfigMap will copy the base configuration onto the /etc/cassandra volume. This init container should run before any other init containers.

Currently the management-api's entry point script copies files generated by config-builder over to /etc/cassandra (see here). I don't think that will be necessary any more. The config builder init container can write directly to the /etc/cassandra volume mount.

This sounds good to me. My only question is if this is sufficient for the read-only root filesystem, or if this is just a part of the solution as it seems it only addresses write to /etc/cassandra? We still have to deal with writes to /opt/cassandra/logs//var/log/cassandra and potentially /opt/cassandra/data//var/lib/cassandra.

@jsanda
Copy link
Contributor Author

jsanda commented Oct 15, 2021

My idea is only focused on addressing /etc/cassandra in particular. The approach is applicable though for configs is general. For some situations it might be overkill.

@sync-by-unito sync-by-unito bot changed the title root file system in cassandra container should be read-only K8SSAND-962 ⁃ root file system in cassandra container should be read-only Oct 20, 2021
@jsanda jsanda changed the title K8SSAND-962 ⁃ root file system in cassandra container should be read-only K8SSAND-962 ⁃ Investigate making the root file system in cassandra container read-only Oct 20, 2021
@jsanda
Copy link
Contributor Author

jsanda commented Oct 20, 2021

I am doing some more work on this and wanted to point out that there is already an EmptyDir volume for /var/log/cassandra since the log directory needs to be accessible by the server-system-logger container.

There is already a PersistenVolume for /var/lib/cassandra. I think that leaves us with the following directories to worry about:

  • /tmp
  • /etc/cassandra
  • /opt/mcac/config

@adejanovski adejanovski removed the zh:Ready For Review Issues in the ZenHub pipeline 'Ready For Review' label Mar 30, 2022
@adejanovski adejanovski moved this to To Groom in K8ssandra Nov 8, 2022
@adejanovski adejanovski assigned emerkle826 and unassigned jsanda May 24, 2024
@adejanovski
Copy link
Contributor

@emerkle826 @burmanm, I think this is what we'll be discussing next week around moving more logic into the Dockerfiles and remove it from the entrypoint, right?

@burmanm
Copy link
Contributor

burmanm commented May 24, 2024

This would be one of the tickets (involving cass-operator changes for new empty mounts).

@burmanm burmanm moved this to Ready For Review in K8ssandra Jul 16, 2024
@adejanovski adejanovski added the ready-for-review Issues in the state 'ready-for-review' label Jul 16, 2024
@emerkle826 emerkle826 assigned burmanm and unassigned emerkle826 Jul 17, 2024
@github-project-automation github-project-automation bot moved this from Ready For Review to Done in K8ssandra Jul 19, 2024
@adejanovski adejanovski added done Issues in the state 'done' and removed ready-for-review Issues in the state 'ready-for-review' labels Jul 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
done Issues in the state 'done' enhancement New feature or request security
Projects
No open projects
Status: Done
4 participants