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

Habitat on Apple Darwin #9469

Draft
wants to merge 28 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
fdad50c
support for macos
atrniv Jun 15, 2023
b02cedc
draft implementation of macos studio builder
atrniv Jun 16, 2023
02326f4
fix the sandbox environment variables
atrniv Jun 16, 2023
62f19f6
fix to find sandbox-exec
atrniv Jun 16, 2023
3011cb1
propogate output path to studio
atrniv Jun 19, 2023
25698c9
flesh out mac os studio
atrniv Jul 10, 2023
962fa76
make stat usage generic across gnu and bsd
atrniv Jul 10, 2023
3ffd50f
fix studio build
atrniv Jul 10, 2023
61a58b6
add 'build' command to macos studio
atrniv Jul 10, 2023
b6ec22e
adds missing capabilites to darwin studio
atrniv Jul 11, 2023
8c247d3
fixes for the studio to allow xcode usage inside the studio
atrniv Apr 29, 2024
85ee346
fix temporary folder access inside studio sandbox
atrniv Apr 30, 2024
5a6752a
fixes for mac studio
atrniv May 14, 2024
038eb25
fixes for standard studio
atrniv May 20, 2024
c59c65f
additional sandbox rules for macos
atrniv May 20, 2024
5d0a3f2
rework studio sandbox to be more minimal
atrniv May 28, 2024
7cd1ef1
implements dynamic plan sandboxing
atrniv May 29, 2024
1c5ea3a
native plan build fixes
atrniv May 29, 2024
facee74
add missing studio sandbox
atrniv May 30, 2024
c26b09a
correct sandbox location
atrniv May 30, 2024
88e9541
fix sandbox rule
atrniv May 30, 2024
c2db30b
fix habitat plan build script
atrniv May 30, 2024
a6a4d29
additional fixes to darwin plan build
atrniv May 30, 2024
c73b88c
adds uname to hab-plan-build sandbox
atrniv May 30, 2024
bc6c85a
fixes tdep sandbox rule resolution
atrniv May 30, 2024
3c05cd3
allow signals within sandbox
atrniv Jun 3, 2024
73d8a99
improve docs and names for plan sandboxes
atrniv Jun 3, 2024
6c1bef6
fix tar detection on macos
atrniv Jun 4, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions components/core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ build = "build.rs"
[build-dependencies]
base64 = "*"
cc = "*"
pem = "*"

[dependencies]
base64 = "*"
Expand Down
6 changes: 6 additions & 0 deletions components/core/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ fn main() { populate_cacert(); }
pub fn populate_cacert() {
if let Ok(src) = env::var("SSL_CERT_FILE") {
let dst = Path::new(&env::var("OUT_DIR").unwrap()).join("cacert.pem");
// Verify the certificate data
let cert_data =
fs::read(&src).expect(format!("Failed to read SSL_CERT_FILE at {}", src).as_str());
pem::parse_many(cert_data).expect(format!("The SSL_CERT_FILE {} contains one or more \
invalid certificates",
src).as_str());
if !dst.exists() {
fs::copy(&src, &dst).unwrap_or_else(|_| {
panic!("Failed to copy CA certificates from '{}' to '{}' for \
Expand Down
4 changes: 0 additions & 4 deletions components/core/src/tls/native_tls_wrapper/readers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,10 +126,6 @@ fn certs_from_pem_file(buf: &[u8]) -> Result<Vec<Certificate>> {
if buf.is_empty() {
return Ok(Vec::new());
}
// Try to decode the first certificate as a pem file. This is necessary because
// `pem::parse_many` does not return an error. It simply parses what it can and ignores the
// rest.
Certificate::from_pem(buf)?;
pem::parse_many(buf)?.iter()
.map(|cert| Ok(Certificate::from_der(cert.contents())?))
.collect()
Expand Down
2 changes: 1 addition & 1 deletion components/hab/src/cli/hab/pkg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ pub struct PkgBuild {
#[structopt(flatten)]
cache_key_path: CacheKeyPath,
/// Build a native package on the host system without a studio
#[cfg(target_os = "linux")]
#[cfg(any(target_os = "linux", target_os = "macos"))]
#[structopt(name = "NATIVE_PACKAGE", short = "N", long = "native-package", conflicts_with_all = &["REUSE", "DOCKER"])]
native_package: bool,
#[cfg(any(target_os = "linux", target_os = "windows"))]
Expand Down
4 changes: 2 additions & 2 deletions components/hab/src/command/studio/enter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ pub async fn start(ui: &mut UI, args: &[OsString]) -> Result<()> {
inner::start(ui, args).await
}

#[cfg(target_os = "linux")]
#[cfg(any(target_os = "linux", target_os = "macos"))]
mod inner {
use crate::{command::studio::{docker,
native},
Expand Down Expand Up @@ -277,7 +277,7 @@ mod inner {
}
}

#[cfg(any(target_os = "macos", target_os = "windows"))]
#[cfg(target_os = "windows")]
mod inner {
use crate::{command::studio::docker,
common::ui::UI,
Expand Down
12 changes: 11 additions & 1 deletion components/hab/src/command/studio/native.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,21 @@ use std::{env,
io::Write,
process::Command};

#[cfg(target_os = "linux")]
const HAB_PLAN_BUILD_SOURCE_FILES: [(&str, &[u8]); 4] =
[("environment.bash", include_bytes!("../../../../plan-build/bin/environment.bash")),
("shared.bash", include_bytes!("../../../../plan-build/bin/shared.bash")),
("public.bash", include_bytes!("../../../../plan-build/bin/public.bash")),
("hab-plan-build.sh", include_bytes!("../../../../plan-build/bin/hab-plan-build.sh"))];
("hab-plan-build.sh", include_bytes!("../../../../plan-build/bin/hab-plan-build-linux.sh"))];

#[cfg(target_os = "macos")]
const HAB_PLAN_BUILD_SOURCE_FILES: [(&str, &[u8]); 5] =
[("environment.bash", include_bytes!("../../../../plan-build/bin/environment.bash")),
("shared.bash", include_bytes!("../../../../plan-build/bin/shared.bash")),
("public.bash", include_bytes!("../../../../plan-build/bin/public.bash")),
("hab-plan-build.sh", include_bytes!("../../../../plan-build/bin/hab-plan-build-darwin.sh")),
("hab-plan-build-darwin-internal.bash",
include_bytes!("../../../../plan-build/bin/hab-plan-build-darwin-internal.bash"))];

pub fn start_native_studio(ui: &mut UI, args: &[OsString]) -> Result<()> {
start_native_studio_impl(ui, args).map_err(Error::NativeStudioError)
Expand Down
171 changes: 171 additions & 0 deletions components/plan-build/bin/darwin-sandbox.sb
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
(version 1)

;; Support for dynamic linker from the base system
(import "dyld-support.sb")

(define STUDIO_DIR (param "STUDIO_DIR"))
(define STUDIO_HAB (param "STUDIO_HAB"))
(define PLAN_CONTEXT_DIR (param "PLAN_CONTEXT_DIR"))
(define PKG_OUTPUT_PATH (param "PKG_OUTPUT_PATH"))

(deny default)

;; These are some things we actively disallow inside the sandbox.
;; We do this, as they would otherwise tend to interfere with the build process.
;; - /etc/localtime, /private/etc/localtime : This will leak the host machine's timezone into the build process
;; - /hab/etc/cli.toml : This will leak the host's default Habitat CLI configuration into the studio

;; Allow processes to fork
(allow process-fork)

;; Allow processes to read system information like cpu count, etc
(allow sysctl-read)

;; Allow POSIX semaphores and shared memory.
(allow ipc-posix*)

;; Allow socket creation.
(allow system-socket)

;; Allow sending signals within the sandbox.
(allow signal (target same-sandbox))

;; Allow file access and process execution inside build, studio and plan context directories
(allow file* process-exec
(subpath STUDIO_DIR)
(subpath PLAN_CONTEXT_DIR)
(subpath PKG_OUTPUT_PATH))

;; Allow access to the studio's habitat binary
;; Also allow access to check the existence of accepted habitat licenses
(allow file* process-exec (literal STUDIO_HAB))
(allow file-read*
(literal "/hab/accepted-licenses")
(literal "/hab/accepted-licenses/habitat"))

;; Allow access to read and execute habitat packages, and cache directory
(allow file* process-exec
(literal "/hab")
(subpath "/hab/pkgs")
(subpath "/hab/cache"))

;; Allow access to env and shell system binaries that are essential
;; for proper execution of the plan build process
(allow process-exec file*
(literal "/usr/bin/env")
(literal "/usr/bin/uname")
(literal "/bin/bash")
(literal "/bin/sh")
(literal "/private/var/select/sh"))

;; Allow access to timezone database
;; This permits reading the timezone information necessary for time-related functions and operations.
(allow file-read-metadata (literal "/var"))
(allow file-read* (subpath "/private/var/db/timezone"))

;; Allow access to terminfo database
(allow file-read* (subpath "/usr/share/terminfo"))

;; Allow access to standard devices including stdin, stdout, terminals, etc.
;; This is necessary for basic input and output operations, random number generation,
;; and terminal interactions which are commonly required for various applications.
(allow file*

;; Allow access to the /dev directory, which contains device files
;; for hardware devices and system resources.
(literal "/dev")

;; Allow access to the random number generator device for generating
;; random numbers, which is often used in cryptographic operations.
(literal "/dev/random")

;; Allow access to /dev/null, a special file that discards all data written to it
;; and provides an end-of-file indicator when read.
(literal "/dev/null")

;; Allow access to standard input, which is used for reading input from the user.
(literal "/dev/stdin")

;; Allow access to standard output, which is used for writing output to the user.
(literal "/dev/stdout")

;; Allow access to the non-blocking random number generator device,
;; which is similar to /dev/random but does not block if there is insufficient entropy.
(literal "/dev/urandom")

;; Allow access to the terminal device, which is used for terminal I/O operations.
(literal "/dev/tty")

;; Allow access to /dev/dtracehelper, a device used by the DTrace framework
;; for dynamic tracing and performance analysis on macOS.
(literal "/dev/dtracehelper")

;; Allow access to pseudo-terminal devices, which are used to create terminal
;; emulators and facilitate terminal multiplexing. These devices typically
;; have names like /dev/pty[a-z]+.
(regex #"^/dev/pty[a-z]+")

;; Allow access to terminal devices with names matching the pattern /dev/tty[a-z]+[0-9]+,
;; which represent various terminal and console devices.
(regex #"^/dev/tty[a-z]+[0-9]+")

;; Allow access to the /dev/fd directory, which contains file descriptor links
;; to open files. This is used to access file descriptors via paths like /dev/fd/0
;; for standard input, /dev/fd/1 for standard output, etc.
(subpath "/dev/fd"))


;; Allow access to common IPC (Inter-Process Communication) system services
;; This is necessary for enabling communication with key system services
;; required for logging, diagnostics, notifications, and directory information.
(allow mach-lookup

;; Allow access to the logging daemon, which is responsible for system logging.
;; This service handles the collection and storage of log messages from the system and applications.
(global-name "com.apple.logd")

;; Allow access to the diagnostics daemon, which is used for collecting and reporting
;; diagnostic information about the system. This service helps in troubleshooting and system health monitoring.
(global-name "com.apple.diagnosticd")

;; Allow access to the system notification center, which manages and displays notifications
;; from the system and applications. This service handles the delivery of alerts and updates to the user.
(global-name "com.apple.system.notification_center")

;; Allow access to the Open Directory library information service, which is part of the macOS
;; directory services architecture. This service is used for retrieving information about user accounts,
;; groups, and other directory-related data.
(global-name "com.apple.system.opendirectoryd.libinfo"))

;; Allow access to user authentication information
;; This is necessary for reading system files that contain user and group authentication data,
;; which are essential for user verification and access control.
(allow file-read*
(literal "/etc")

;; Allow access to the master.passwd file, which is located in the /private/etc directory.
;; This file contains encrypted user passwords and other user account information.
(literal "/private/etc/master.passwd")

;; Allow access to the group file, which is located in the /private/etc directory.
;; This file contains group information, including group names and member user IDs.
(literal "/private/etc/group"))

;; Allow access to temporary working directories
(allow file-read-metadata (literal "/tmp"))
(allow file* process-exec (subpath "/private/tmp"))

;; Allow DNS lookups and network access
(allow network* (local ip) (local tcp) (local udp))

(allow file-read-metadata
(literal "/var")
(literal "/etc")
(literal "/etc/resolv.conf")
(literal "/private/etc/resolv.conf")
(literal "/etc/hosts"))

(allow file-read*
(literal "/private/var/run/resolv.conf")
(literal "/private/etc/hosts"))
(allow network-outbound (remote unix-socket (path-literal "/private/var/run/mDNSResponder")))
Loading
Loading