Post

Using Containers to Run MSCP

Using Containers to Run MSCP

macOS and Containers

Following the announcement of macOS 26 at WWDC this year, my friend @golby shared a link to a WWDC session on Containerization, which immediately caught my attention. During that session, we were introduced to a project from Apple that leveraged some new features in macOS 26 Beta. From the github page, container is a tool that you can use to create and run Linux containers as lightweight virtual machines on your Mac. It’s written in Swift, and optimized for Apple silicon.

One of first things I thought about is how can we leverage this to make running the macOS Security Compliance Project (MSCP) even easier for Mac admins who want to build their compliance using the command line.

One challenge of the MSCP has always been the dependencies required to run the scripts in the project. macOS does not include everything that is needed for the project. With python and ruby being two of the core components. The project has tried to leverage the pieces that Apple includes in either the shipped OS, or by way of the Xcode Command Line Tools, which give admins tools like git and python. The issue is that the tools that Apple provides are not always up to date. For example, ruby is included in macOS build, but is running version 2.6.10p210, which was released April 12… of 2022! While these versions have been functional for us over the years, we wanted to be able to modernize some of our tools which meant we need to be running newer versions of them.

One approach is that we provide the instructions to download and install all of the tools needed to run the project. While this is fine and most admins are fully capable of getting their environment setup, what if there was an easier way for us to have everything we needed with much less overhead. Something where all of the dependencies were included in a easy to deploy package… a container of sorts.

Containers are certainly not a new concept. Services like Docker and Podman have been available for quite some time on macOS. With macOS 26 Beta, Apple has brought the concept a bit closer to home. Let’s see how we can build an MSCP container to generate compliance documentation.

While all of this was made available after WWDC and the announcment of macOS Tahoe, the container tool will let you run containers on macOS Sequoia, but building them may have issues. It does require to be run directly on an Apple Silicon system and cannot be run in a virtual machine (VM).

TL;DR

Download and install the latest signed installer package for container from Apple’s GitHub release page.

1
2
3
container system start

container run -it ghcr.io/brodjieski/mscp:latest

For those who want to see the process in more detail, keep reading.

Building the MSCP container

There are just a couple of steps needed to create a Linux container running the MSCP natively on macOS.

Download and install the latest signed installer package for container from Apple’s GitHub release page.

Clone the macOS Security Compliance Project from NIST’s GitHub page to your Desktop folder.

1
git clone https://github.com/usnistgov/macos_security ~/Desktop/

git requires the Xcode Command Line Tools

Create a Dockerfile file and place it in ~/Desktop/macos_security with the following contents

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
FROM alpine:latest

# Install required packages
RUN apk update && apk add --no-cache \
  python3 \
  ruby \
  git \
  py3-pip \
  ruby-dev \
  build-base

# Set working directory
WORKDIR /mscp

# Install Python dependencies
COPY requirements.txt .
RUN pip install --break-system-packages --no-cache-dir -r requirements.txt

# Install Ruby dependencies
COPY Gemfile ./
RUN gem install bundler && bundle install

# Copy MSCP code
COPY . .

# Run a shell when container starts
CMD ["sh"]

This file tells the container engine how to build the container image and the necessary components.

Build the container image

In order for container to manage and interact with images and containers, the system service need to be started.

1
container system start

The first time you start the container system, it will install a base container filesystem and prompt you to install a default kernel. The process suggests a recommended default kernel that you can use.

Once the system has been started, you can now build the container from the Dockerfile.

1
container build -f ~/Desktop/macos_security/Dockerfile -t mscp ~/Desktop/macos_security/

That’s it! You have successfully built an MSCP container tagged mscp:latest that contains everything needed to build compliance documents from MSCP.

Using the MSCP container

Now that we have the container built, we can run the image with an interactive terminal. This will give us command line access to everything we need in the project.

1
container run -it mscp:latest

The -it flags tells container to run an interactive tty, which brings you to the shell within the container. You will notice that your command line prompt now reads:

1
/mscp # 

You can now run any of the MSCP scripts from this command line.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/mscp # ./scripts/generate_baseline.py -l
800-171
800-53r4_high
800-53r4_low
800-53r4_moderate
800-53r5_high
800-53r5_low
800-53r5_moderate
800-53r5_privacy
all_rules
arm64
cis_lvl1
cis_lvl2
cisv8
cmmc_lvl1
...

1
2
3
4
5
6
/mscp # ./scripts/generate_guidance.py baselines/800-53r5_moderate.yaml
Profile YAML: baselines/800-53r5_moderate.yaml
Output path: /mscp/build/800-53r5_moderate/800-53r5_moderate.adoc
Generating HTML file from AsciiDoc...
Generating PDF file from AsciiDoc...
/mscp #

To exit the mscp shell, just type exit at the command prompt.

Saving generated documents outside of the container

Once a container is created, the contents typically remain as-is and data that gets modified while inside the container will be erased when the container stops running. So how to we keep our generated compliance documents? When you run generate_guidance.py all of the output is sent to the ./build folder, which resides inside the container and will be lost when exiting.

With the --volume option of container run, you can share data between the host system and one or more containers, and you can persist data across multiple container runs. The volume option allows you to mount a folder on your host to a filesystem path in the container.

To share the MSCP ./build folder from the container with a mscp folder on your Desktop, run the following command:

1
2
3
4
# create host folder if needed
mkdir -p ~/Desktop/mscp

container run -it --volume ~/Desktop/mscp:/mscp/build mscp:latest

The folder used in the --volume command must exist on the host.

Now when you run any of the generate scripts from within the container, the resulting files will be made available on your Desktop.

You can do multiple volumes as well. Let’s say you also want to share your custom items used by the project:

1
container run -it --volume ~/Desktop/mscp:/mscp/build --volume ~/Desktop/mscp/custom:/mscp/custom mscp:latest

Now any customizations made will be persistent across container runs.

Using an hosted container

For those who don’t want to go through all of the process of building and maintaining their own container, you can always run a container that has been built and hosted just like any Docker container. An example can be found in my GitHub packages, and can be kicked off by telling container to use a hosted container, rather than a local.

1
container run -it --volume ~/Desktop/mscp:/mscp/build --volume ~/Desktop/mscp/custom:/mscp/custom ghcr.io/brodjieski/mscp:latest

Podman also works

1
podman run -it --volume /Users/<username>/Desktop/mscp:/mscp/build --volume /Users/<username>/Desktop/mscp/custom:/mscp/custom ghcr.io/brodjieski/mscp:latest

Using Docker has a similar command, although it requires full path names and commas in the --volume command

1
docker run -it --volume /Users/<username>/Desktop/mscp,/mscp/build --volume /Users/<username>/Desktop/mscp/custom,/mscp/custom ghcr.io/brodjieski/mscp:latest

In Conclusion

Containers are a great way to deploy applications and solutions that can run natively in a Linux environment to include all of the required dependencies and software needed to use the application as intended. This example illustrates how MSCP can be used on nearly any platform that can run containers… so now even your Windows admins have a means to generate macOS compliance documentation!

This post is licensed under CC BY 4.0 by the author.

Trending Tags