mirror of
https://github.com/usestrix/firewall.git
synced 2026-11-09 05:19:35 -10:00
Compare commits
10
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0ef90c0fb6 | ||
|
|
f6a1730fa6 | ||
|
|
ff2e43d9bb | ||
|
|
353a15bc20 | ||
|
|
43106da6b8 | ||
|
|
da9935ad61 | ||
|
|
18d8a0dd93 | ||
|
|
d551b115c4 | ||
|
|
f88f6a9d8b | ||
|
|
1b43b9ba16 |
No files matched your search
Binary file not shown.
|
After Width: | Height: | Size: 3.3 KiB |
@@ -59,8 +59,8 @@ impl Default for FirewallConfig {
|
||||
impl Default for DenylistSource {
|
||||
fn default() -> Self {
|
||||
DenylistSource {
|
||||
base: "https://raw.githubusercontent.com/usestrix/malicious-packages/packages".into(),
|
||||
revision: "https://api.github.com/repos/usestrix/malicious-packages/commits/packages"
|
||||
base: "https://raw.githubusercontent.com/usestrix/firewall-blocklist/main".into(),
|
||||
revision: "https://api.github.com/repos/usestrix/firewall-blocklist/commits/main"
|
||||
.into(),
|
||||
poll_secs: 10,
|
||||
}
|
||||
|
||||
@@ -12,6 +12,10 @@ fn main() {
|
||||
firewall::init_logging("info");
|
||||
serve()
|
||||
}
|
||||
if matches.subcommand_matches("uninstall").is_some() {
|
||||
firewall::init_logging("info");
|
||||
uninstall()
|
||||
}
|
||||
let mut command = matches.get_many::<String>("COMMAND").unwrap().cloned();
|
||||
let program = command.next().unwrap();
|
||||
firewall::init_logging("warn");
|
||||
@@ -40,6 +44,8 @@ fn options() -> Command {
|
||||
Command::new("serve")
|
||||
.about("Serve a local registry for package managers configured to use it"),
|
||||
)
|
||||
// Run as root by the macOS app's uninstall.
|
||||
.subcommand(Command::new("uninstall").hide(true))
|
||||
.arg(
|
||||
Arg::new("COMMAND")
|
||||
.help("A command to run with its package downloads screened")
|
||||
@@ -69,6 +75,13 @@ fn serve() -> ! {
|
||||
}
|
||||
}
|
||||
|
||||
fn uninstall() -> ! {
|
||||
match firewall::os::uninstall() {
|
||||
Ok(()) => exit(0),
|
||||
Err(e) => fail("uninstall", &format!("could not uninstall: {e}")),
|
||||
}
|
||||
}
|
||||
|
||||
fn run(invocation: Invocation) -> ! {
|
||||
let command = &invocation.program;
|
||||
let port = match aliasing::spawn(0, load()) {
|
||||
|
||||
+3
-1
@@ -60,10 +60,12 @@ pub fn crl(hosts: &[&str], signer: &dyn SigningKey) -> Result<Vec<u8>, BoxError>
|
||||
Ok(list.signed_by(&Issuer::from_params(&ca, signer))?.der().to_vec())
|
||||
}
|
||||
|
||||
pub const COMMON_NAME: &str = "Strix Firewall";
|
||||
|
||||
/// Also used by the issuer, whose issuer name must match the CA's subject.
|
||||
pub fn params(hosts: &[&str]) -> CertificateParams {
|
||||
let mut name = DistinguishedName::new();
|
||||
name.push(DnType::CommonName, "Strix Firewall");
|
||||
name.push(DnType::CommonName, COMMON_NAME);
|
||||
name.push(DnType::OrganizationName, "Strix");
|
||||
|
||||
let mut params = CertificateParams::default();
|
||||
|
||||
@@ -3,7 +3,7 @@ mod issuer;
|
||||
mod route;
|
||||
mod screen;
|
||||
|
||||
pub use ca::{crl, CaSigner, CertificateAuthority};
|
||||
pub use ca::{crl, CaSigner, CertificateAuthority, COMMON_NAME};
|
||||
|
||||
use crate::Firewall;
|
||||
use issuer::ConstrainedCertIssuer;
|
||||
|
||||
@@ -2,6 +2,8 @@ mod enclave;
|
||||
mod install;
|
||||
mod uninstall;
|
||||
|
||||
pub use uninstall::uninstall;
|
||||
|
||||
use crate::config::FirewallConfig;
|
||||
use crate::{mitm, telemetry};
|
||||
use crate::Firewall;
|
||||
@@ -49,15 +51,11 @@ impl TransparentProxyHandler for Handler {
|
||||
TransparentProxyConfig::new().with_rules(vec![tcp_rule(80), tcp_rule(443)])
|
||||
}
|
||||
|
||||
/// Setup requests from the installer. Never empty: Swift cannot tell that from no reply.
|
||||
/// Setup requests from the app. Never empty: Swift cannot tell that from no reply.
|
||||
async fn handle_app_message(&self, _exec: Executor, message: Bytes) -> Option<Bytes> {
|
||||
let message = String::from_utf8_lossy(&message).into_owned();
|
||||
Some(Bytes::from(match message.as_str() {
|
||||
"ca" => self.ca.pem.clone(),
|
||||
"uninstall" => match uninstall::certificate_authority(&self.ca) {
|
||||
Ok(()) => "ok".to_owned(),
|
||||
Err(error) => format!("error: {error}"),
|
||||
},
|
||||
other => format!("error: unknown message {other}"),
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -1,26 +1,47 @@
|
||||
use super::enclave::EnclaveKey;
|
||||
use super::{CA_FILE, KEYCHAIN_ACCOUNT, KEYCHAIN_SERVICE};
|
||||
use crate::mitm::CertificateAuthority;
|
||||
use crate::mitm::COMMON_NAME;
|
||||
use rama::error::BoxError;
|
||||
use rama::net::apple::networkextension::system_keychain;
|
||||
use security_framework::item::{ItemClass, ItemSearchOptions, Limit};
|
||||
use security_framework::os::macos::keychain::SecKeychain;
|
||||
use security_framework_sys::base::errSecItemNotFound;
|
||||
use std::io::ErrorKind;
|
||||
use tracing::info;
|
||||
|
||||
/// Installed by the pkg.
|
||||
const ENV_AGENT: &str = "/Library/LaunchAgents/com.usestrix.firewall.env.plist";
|
||||
|
||||
/// Removes what only root can: the CA, its enclave key and exported copy, and the env
|
||||
/// agent. Trust settings need an authorization dialog, so the installer drops those itself.
|
||||
pub fn certificate_authority(ca: &CertificateAuthority) -> Result<(), BoxError> {
|
||||
system_keychain::uninstall_system_ca(&ca.crt.to_der()?)?;
|
||||
system_keychain::delete_secret(KEYCHAIN_SERVICE, KEYCHAIN_ACCOUNT)?;
|
||||
/// Removes what only root can: every CA the extension minted, its enclave key and exported
|
||||
/// copy, and the env agent. Trust settings need an authorization dialog, so the app drops those.
|
||||
pub fn uninstall() -> Result<(), BoxError> {
|
||||
let deleted = ItemSearchOptions::new()
|
||||
.class(ItemClass::certificate())
|
||||
.keychains(&[SecKeychain::open("/Library/Keychains/System.keychain")?])
|
||||
.label(COMMON_NAME)
|
||||
.limit(Limit::All)
|
||||
.delete();
|
||||
let mut removed = match deleted {
|
||||
Ok(()) => true,
|
||||
Err(error) if error.code() == errSecItemNotFound => false,
|
||||
Err(error) => return Err(error.into()),
|
||||
};
|
||||
if system_keychain::load_secret(KEYCHAIN_SERVICE, KEYCHAIN_ACCOUNT)?.is_some() {
|
||||
system_keychain::delete_secret(KEYCHAIN_SERVICE, KEYCHAIN_ACCOUNT)?;
|
||||
removed = true;
|
||||
}
|
||||
EnclaveKey::delete()?;
|
||||
for path in [CA_FILE, ENV_AGENT] {
|
||||
match std::fs::remove_file(path) {
|
||||
Err(error) if error.kind() != ErrorKind::NotFound => return Err(error.into()),
|
||||
_ => {}
|
||||
Ok(()) => removed = true,
|
||||
Err(error) if error.kind() == ErrorKind::NotFound => {}
|
||||
Err(error) => return Err(error.into()),
|
||||
}
|
||||
}
|
||||
info!("removed the CA from the system keychain");
|
||||
if removed {
|
||||
info!("removed the CA from the system keychain");
|
||||
} else {
|
||||
info!("nothing to uninstall");
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,2 +1,11 @@
|
||||
#[cfg(target_os = "macos")]
|
||||
pub mod macos;
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
pub use macos::uninstall;
|
||||
|
||||
/// Elsewhere nothing is installed system-wide.
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
pub fn uninstall() -> Result<(), rama::error::BoxError> {
|
||||
Ok(())
|
||||
}
|
||||
+2
-2
@@ -3,5 +3,5 @@ Firewall.xcodeproj
|
||||
.env
|
||||
Extension/Extension.entitlements
|
||||
Extension/Info.plist
|
||||
Installer/Installer.entitlements
|
||||
Installer/Info.plist
|
||||
App/App.entitlements
|
||||
App/Info.plist
|
||||
File renamed without changes.
@@ -1,7 +1,7 @@
|
||||
import SwiftUI
|
||||
|
||||
struct ContentView: View {
|
||||
@ObservedObject var model: InstallerModel
|
||||
@ObservedObject var model: FirewallModel
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
|
||||
var body: some View {
|
||||
@@ -1,8 +1,8 @@
|
||||
import SwiftUI
|
||||
|
||||
@main
|
||||
struct InstallerApp: App {
|
||||
@StateObject private var model = InstallerModel()
|
||||
struct FirewallApp: App {
|
||||
@StateObject private var model = FirewallModel()
|
||||
|
||||
var body: some Scene {
|
||||
MenuBarExtra {
|
||||
@@ -31,7 +31,7 @@ enum SetupWindow {
|
||||
|
||||
/// An accessory app restores no windows, so setup is raised from the label, the one view built at launch.
|
||||
private struct MenuBarLabel: View {
|
||||
@ObservedObject var model: InstallerModel
|
||||
@ObservedObject var model: FirewallModel
|
||||
@Environment(\.openWindow) private var openWindow
|
||||
@State private var raised = false
|
||||
|
||||
File renamed without changes.
@@ -23,22 +23,20 @@ enum StepStatus: Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
enum InstallerError: Error, LocalizedError {
|
||||
enum FirewallError: Error, LocalizedError {
|
||||
case extensionUnavailable
|
||||
case extensionRefused(String)
|
||||
case screeningDidNotStart(NEVPNStatus)
|
||||
|
||||
var errorDescription: String? {
|
||||
switch self {
|
||||
case .extensionUnavailable: return "The extension is not running"
|
||||
case let .extensionRefused(reply): return "The extension replied \(reply)"
|
||||
case let .screeningDidNotStart(status): return "Screening did not start (\(status.label))"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@MainActor
|
||||
final class InstallerModel: NSObject, ObservableObject {
|
||||
final class FirewallModel: NSObject, ObservableObject {
|
||||
@Published private(set) var extensionStep = StepStatus.pending
|
||||
@Published private(set) var screeningStep = StepStatus.pending
|
||||
@Published private(set) var trustStep = StepStatus.pending
|
||||
@@ -124,9 +122,9 @@ final class InstallerModel: NSObject, ObservableObject {
|
||||
log("Uninstall cancelled")
|
||||
return
|
||||
}
|
||||
// The extension owns the private key, so ask it before tearing down the session that carries the request.
|
||||
let strandedKey = await removeStoredCA()
|
||||
// Stop screening first so the extension cannot mint a fresh CA after it is removed.
|
||||
await removeConfiguration()
|
||||
let strandedKey = removeStoredCA()
|
||||
await deactivate()
|
||||
if let strandedKey { trustStep = .failed(strandedKey) }
|
||||
|
||||
@@ -167,7 +165,7 @@ final class InstallerModel: NSObject, ObservableObject {
|
||||
}
|
||||
}
|
||||
|
||||
private func stage(_ step: ReferenceWritableKeyPath<InstallerModel, StepStatus>,
|
||||
private func stage(_ step: ReferenceWritableKeyPath<FirewallModel, StepStatus>,
|
||||
running: String,
|
||||
work: @MainActor () async throws -> String) async -> Bool {
|
||||
self[keyPath: step] = .running(running)
|
||||
@@ -245,17 +243,18 @@ final class InstallerModel: NSObject, ObservableObject {
|
||||
return true
|
||||
}
|
||||
|
||||
/// Only root can delete the key, so the extension does it; returns what to report if it survived.
|
||||
private func removeStoredCA() async -> String? {
|
||||
do {
|
||||
let reply = try await providerMessage("uninstall")
|
||||
guard reply == "ok" else { throw InstallerError.extensionRefused(reply) }
|
||||
log("Removed the CA, its exported copy and the env agent")
|
||||
return nil
|
||||
} catch {
|
||||
log("Could not remove the CA: \(error.localizedDescription)")
|
||||
/// The extension wrote these as root, so the bundled CLI removes them behind an admin prompt; returns what to report if it failed.
|
||||
private func removeStoredCA() -> String? {
|
||||
let cli = Bundle.main.path(forAuxiliaryExecutable: "firewall") ?? ""
|
||||
let script = "do shell script quoted form of \"\(cli)\" & \" uninstall\" with administrator privileges"
|
||||
var error: NSDictionary?
|
||||
NSAppleScript(source: script)?.executeAndReturnError(&error)
|
||||
if let error {
|
||||
log("Could not remove the CA: \(error[NSAppleScript.errorMessage] ?? error)")
|
||||
return "The CA private key is still in the System keychain"
|
||||
}
|
||||
log("Removed the CA, its exported copy and the env agent")
|
||||
return nil
|
||||
}
|
||||
|
||||
// MARK: - System extension
|
||||
@@ -297,14 +296,14 @@ final class InstallerModel: NSObject, ObservableObject {
|
||||
|
||||
try manager.connection.startVPNTunnel()
|
||||
guard try await wait(for: .connected, on: manager.connection) else {
|
||||
throw InstallerError.screeningDidNotStart(manager.connection.status)
|
||||
throw FirewallError.screeningDidNotStart(manager.connection.status)
|
||||
}
|
||||
return "Screening package downloads"
|
||||
}
|
||||
|
||||
private func restartScreening() async throws -> String {
|
||||
guard let manager = try await loadManager() else {
|
||||
throw InstallerError.extensionUnavailable
|
||||
throw FirewallError.extensionUnavailable
|
||||
}
|
||||
manager.connection.stopVPNTunnel()
|
||||
_ = try await wait(for: .disconnected, on: manager.connection)
|
||||
@@ -312,7 +311,7 @@ final class InstallerModel: NSObject, ObservableObject {
|
||||
}
|
||||
|
||||
private func stopScreening() async throws -> String {
|
||||
guard let manager = try await loadManager() else { throw InstallerError.extensionUnavailable }
|
||||
guard let manager = try await loadManager() else { throw FirewallError.extensionUnavailable }
|
||||
manager.isEnabled = false
|
||||
try await manager.saveToPreferences()
|
||||
manager.connection.stopVPNTunnel()
|
||||
@@ -358,13 +357,13 @@ final class InstallerModel: NSObject, ObservableObject {
|
||||
|
||||
private func providerMessage(_ message: String) async throws -> String {
|
||||
guard let session = watched?.connection as? NETunnelProviderSession else {
|
||||
throw InstallerError.extensionUnavailable
|
||||
throw FirewallError.extensionUnavailable
|
||||
}
|
||||
return try await withCheckedThrowingContinuation { continuation in
|
||||
do {
|
||||
try session.sendProviderMessage(Data(message.utf8)) { response in
|
||||
guard let response, let reply = String(data: response, encoding: .utf8) else {
|
||||
continuation.resume(throwing: InstallerError.extensionUnavailable)
|
||||
continuation.resume(throwing: FirewallError.extensionUnavailable)
|
||||
return
|
||||
}
|
||||
continuation.resume(returning: reply)
|
||||
@@ -381,7 +380,7 @@ final class InstallerModel: NSObject, ObservableObject {
|
||||
}
|
||||
}
|
||||
|
||||
extension InstallerModel: OSSystemExtensionRequestDelegate {
|
||||
extension FirewallModel: OSSystemExtensionRequestDelegate {
|
||||
nonisolated func request(_ request: OSSystemExtensionRequest,
|
||||
actionForReplacingExtension existing: OSSystemExtensionProperties,
|
||||
withExtension replacement: OSSystemExtensionProperties) -> OSSystemExtensionRequest.ReplacementAction {
|
||||
@@ -1,7 +1,7 @@
|
||||
import SwiftUI
|
||||
|
||||
struct MenuBarView: View {
|
||||
@ObservedObject var model: InstallerModel
|
||||
@ObservedObject var model: FirewallModel
|
||||
@Environment(\.openWindow) private var openWindow
|
||||
|
||||
var body: some View {
|
||||
@@ -9,7 +9,7 @@ struct MenuBarView: View {
|
||||
|
||||
Divider()
|
||||
|
||||
Button("Installer") {
|
||||
Button("Setup") {
|
||||
SetupWindow.open(openWindow)
|
||||
}
|
||||
|
||||
File renamed without changes.
+16
-10
@@ -1,6 +1,7 @@
|
||||
#!/bin/bash
|
||||
# Builds and signs Firewall.app, installs it to /Applications, and packages it as build/Firewall.pkg.
|
||||
# Set NOTARY_PROFILE in macos/.env to a notarytool keychain profile to notarize the package.
|
||||
# Builds and signs StrixFirewall.app, installs it to /Applications, and packages it as build/Firewall.pkg.
|
||||
# The package is notarized with the notarytool keychain profile in NOTARY_PROFILE; `build.sh debug`
|
||||
# makes a Debug build and skips notarization.
|
||||
#
|
||||
# Xcode builds the bundles unsigned; they are signed here with Developer ID.
|
||||
set -euo pipefail
|
||||
@@ -10,6 +11,10 @@ cd "$(dirname "$0")"
|
||||
: "${TEAM:?set TEAM in macos/.env}"
|
||||
export TEAM
|
||||
|
||||
CONFIGURATION=Release
|
||||
if [ "${1:-}" = debug ]; then CONFIGURATION=Debug; fi
|
||||
[ $CONFIGURATION = Debug ] || : "${NOTARY_PROFILE:?set NOTARY_PROFILE in macos/.env}"
|
||||
|
||||
APP_ID=com.usestrix.firewall
|
||||
EXT_ID=com.usestrix.firewall.extension
|
||||
VERSION=0.1
|
||||
@@ -18,7 +23,7 @@ IDENTITY=${IDENTITY:-Developer ID Application}
|
||||
INSTALLER_IDENTITY=${INSTALLER_IDENTITY:-Developer ID Installer}
|
||||
PROFILES="$HOME/Library/Developer/Xcode/UserData/Provisioning Profiles"
|
||||
|
||||
APP=build/Build/Products/Release/Installer.app
|
||||
APP=build/Build/Products/$CONFIGURATION/StrixFirewall.app
|
||||
EXT=$APP/Contents/Library/SystemExtensions/$EXT_ID.systemextension
|
||||
PKG_ROOT=build/pkg-root
|
||||
|
||||
@@ -27,13 +32,13 @@ main() {
|
||||
sign
|
||||
install_app
|
||||
package
|
||||
[ -z "${NOTARY_PROFILE:-}" ] || notarize
|
||||
[ $CONFIGURATION = Debug ] || notarize
|
||||
}
|
||||
|
||||
build() {
|
||||
echo "==> Building"
|
||||
xcodegen generate >/dev/null
|
||||
xcodebuild -project Firewall.xcodeproj -scheme Installer -configuration Release \
|
||||
xcodebuild -project Firewall.xcodeproj -scheme StrixFirewall -configuration $CONFIGURATION \
|
||||
-derivedDataPath build CODE_SIGNING_ALLOWED=NO CODE_SIGNING_REQUIRED=NO \
|
||||
CODE_SIGN_IDENTITY="" CODE_SIGN_ENTITLEMENTS="" build >/dev/null
|
||||
}
|
||||
@@ -42,18 +47,19 @@ sign() {
|
||||
echo "==> Signing with $IDENTITY"
|
||||
cp "$(profile_for $APP_ID)" "$APP/Contents/embedded.provisionprofile"
|
||||
cp "$(profile_for $EXT_ID)" "$EXT/Contents/embedded.provisionprofile"
|
||||
codesign --force --options runtime --timestamp -s "$IDENTITY" "$APP/Contents/MacOS/firewall"
|
||||
codesign --force --options runtime --timestamp \
|
||||
--entitlements Extension/Extension.entitlements -s "$IDENTITY" "$EXT"
|
||||
codesign --force --options runtime --timestamp \
|
||||
--entitlements Installer/Installer.entitlements -s "$IDENTITY" "$APP"
|
||||
--entitlements App/App.entitlements -s "$IDENTITY" "$APP"
|
||||
codesign --verify --deep --strict "$APP"
|
||||
}
|
||||
|
||||
# The extension can only be activated from /Applications.
|
||||
install_app() {
|
||||
echo "==> Installing /Applications/Firewall.app"
|
||||
rm -rf /Applications/Firewall.app
|
||||
cp -R "$APP" /Applications/Firewall.app
|
||||
echo "==> Installing /Applications/StrixFirewall.app"
|
||||
rm -rf /Applications/StrixFirewall.app
|
||||
cp -R "$APP" /Applications/StrixFirewall.app
|
||||
}
|
||||
|
||||
# Marked non-relocatable so the installer never updates another copy with the same bundle id.
|
||||
@@ -61,7 +67,7 @@ package() {
|
||||
echo "==> Packaging build/Firewall.pkg"
|
||||
rm -rf "$PKG_ROOT"
|
||||
mkdir -p "$PKG_ROOT/Applications" "$PKG_ROOT/Library/LaunchAgents"
|
||||
cp -R "$APP" "$PKG_ROOT/Applications/Firewall.app"
|
||||
cp -R "$APP" "$PKG_ROOT/Applications/StrixFirewall.app"
|
||||
cp LaunchAgents/com.usestrix.firewall.env.plist "$PKG_ROOT/Library/LaunchAgents/"
|
||||
|
||||
pkgbuild --analyze --root "$PKG_ROOT" build/components.plist >/dev/null
|
||||
|
||||
@@ -6,5 +6,5 @@ uid=$(id -u "$user")
|
||||
agent=/Library/LaunchAgents/com.usestrix.firewall.env.plist
|
||||
launchctl bootout "gui/$uid" "$agent" 2>/dev/null
|
||||
launchctl bootstrap "gui/$uid" "$agent"
|
||||
launchctl asuser "$uid" sudo -u "$user" open -a /Applications/Firewall.app --args --install
|
||||
launchctl asuser "$uid" sudo -u "$user" open -a /Applications/StrixFirewall.app --args --install
|
||||
exit 0
|
||||
+15
-4
@@ -87,25 +87,25 @@ targets:
|
||||
$([ "$CONFIGURATION" = Debug ] || echo --release)
|
||||
done
|
||||
|
||||
Installer:
|
||||
StrixFirewall:
|
||||
type: application
|
||||
platform: macOS
|
||||
sources:
|
||||
- Installer
|
||||
- App
|
||||
- path: ../assets/logo-transparent.png
|
||||
buildPhase: resources
|
||||
settings:
|
||||
base:
|
||||
PRODUCT_BUNDLE_IDENTIFIER: com.usestrix.firewall
|
||||
info:
|
||||
path: Installer/Info.plist
|
||||
path: App/Info.plist
|
||||
properties:
|
||||
CFBundleShortVersionString: "0.1"
|
||||
LSMinimumSystemVersion: $(MACOSX_DEPLOYMENT_TARGET)
|
||||
NSSystemExtensionUsageDescription: Firewall uses a network extension to screen package downloads before they install.
|
||||
LSUIElement: true
|
||||
entitlements:
|
||||
path: Installer/Installer.entitlements
|
||||
path: App/App.entitlements
|
||||
properties:
|
||||
com.apple.application-identifier: ${TEAM}.com.usestrix.firewall
|
||||
com.apple.developer.team-identifier: ${TEAM}
|
||||
@@ -117,3 +117,14 @@ targets:
|
||||
- target: Extension
|
||||
embed: true
|
||||
codeSign: true
|
||||
# Uninstall runs the CLI as root to remove what the extension left.
|
||||
postBuildScripts:
|
||||
- name: Embed the CLI
|
||||
basedOnDependencyAnalysis: false
|
||||
script: |
|
||||
export PATH="$HOME/.cargo/bin:$PATH"
|
||||
unset CC CXX CFLAGS CXXFLAGS
|
||||
export SDKROOT="$(xcrun --sdk macosx --show-sdk-path)"
|
||||
cd "$SRCROOT/../core"
|
||||
cargo build --bin firewall --target aarch64-apple-darwin $([ "$CONFIGURATION" = Debug ] || echo --release)
|
||||
cp "target/aarch64-apple-darwin/$CARGO_PROFILE/firewall" "$TARGET_BUILD_DIR/$EXECUTABLE_FOLDER_PATH/"
|
||||
Reference in new issue
Block a user