From 45df4d0d9b577fecee798d672695fe24ff57fb1b Mon Sep 17 00:00:00 2001 From: mo khan Date: Tue, 15 Jul 2025 16:37:08 -0600 Subject: feat: migrate from Cedar to SpiceDB authorization system This is a major architectural change that replaces the Cedar policy-based authorization system with SpiceDB's relation-based authorization. Key changes: - Migrate from Rust to Go implementation - Replace Cedar policies with SpiceDB schema and relationships - Switch from envoy `ext_authz` with Cedar to SpiceDB permission checks - Update build system and dependencies for Go ecosystem - Maintain Envoy integration for external authorization This change enables more flexible permission modeling through SpiceDB's Google Zanzibar inspired relation-based system, supporting complex hierarchical permissions that were difficult to express in Cedar. Breaking change: Existing Cedar policies and Rust-based configuration will no longer work and need to be migrated to SpiceDB schema. --- vendor/cc/src/target/parser.rs | 563 ----------------------------------------- 1 file changed, 563 deletions(-) delete mode 100644 vendor/cc/src/target/parser.rs (limited to 'vendor/cc/src/target/parser.rs') diff --git a/vendor/cc/src/target/parser.rs b/vendor/cc/src/target/parser.rs deleted file mode 100644 index c4cfcbbb..00000000 --- a/vendor/cc/src/target/parser.rs +++ /dev/null @@ -1,563 +0,0 @@ -use std::env; - -use crate::{target::TargetInfo, utilities::OnceLock, Error, ErrorKind}; - -#[derive(Debug)] -struct TargetInfoParserInner { - full_arch: Box, - arch: Box, - vendor: Box, - os: Box, - env: Box, - abi: Box, -} - -impl TargetInfoParserInner { - fn from_cargo_environment_variables() -> Result { - // `TARGET` must be present. - // - // No need to emit `rerun-if-env-changed` for this, - // as it is controlled by Cargo itself. - #[allow(clippy::disallowed_methods)] - let target_name = env::var("TARGET").map_err(|err| { - Error::new( - ErrorKind::EnvVarNotFound, - format!("failed reading TARGET: {err}"), - ) - })?; - - // Parse the full architecture name from the target name. - let (full_arch, _rest) = target_name.split_once('-').ok_or(Error::new( - ErrorKind::InvalidTarget, - format!("target `{target_name}` only had a single component (at least two required)"), - ))?; - - let cargo_env = |name, fallback: Option<&str>| -> Result, Error> { - // No need to emit `rerun-if-env-changed` for these, - // as they are controlled by Cargo itself. - #[allow(clippy::disallowed_methods)] - match env::var(name) { - Ok(var) => Ok(var.into_boxed_str()), - Err(err) => match fallback { - Some(fallback) => Ok(fallback.into()), - None => Err(Error::new( - ErrorKind::EnvVarNotFound, - format!("did not find fallback information for target `{target_name}`, and failed reading {name}: {err}"), - )), - }, - } - }; - - // Prefer to use `CARGO_ENV_*` if set, since these contain the most - // correct information relative to the current `rustc`, and makes it - // possible to support custom target JSON specs unknown to `rustc`. - // - // NOTE: If the user is using an older `rustc`, that data may be older - // than our pre-generated data, but we still prefer Cargo's view of - // the world, since at least `cc` won't differ from `rustc` in that - // case. - // - // These may not be set in case the user depended on being able to - // just set `TARGET` outside of build scripts; in those cases, fall - // back back to data from the known set of target names instead. - // - // See discussion in #1225 for further details. - let fallback_target = TargetInfo::from_rustc_target(&target_name).ok(); - let ft = fallback_target.as_ref(); - let arch = cargo_env("CARGO_CFG_TARGET_ARCH", ft.map(|t| t.arch))?; - let vendor = cargo_env("CARGO_CFG_TARGET_VENDOR", ft.map(|t| t.vendor))?; - let os = cargo_env("CARGO_CFG_TARGET_OS", ft.map(|t| t.os))?; - let env = cargo_env("CARGO_CFG_TARGET_ENV", ft.map(|t| t.env))?; - // `target_abi` was stabilized in Rust 1.78, which is higher than our - // MSRV, so it may not always be available; In that case, fall back to - // `""`, which is _probably_ correct for unknown target names. - let abi = cargo_env("CARGO_CFG_TARGET_ABI", ft.map(|t| t.abi)) - .unwrap_or_else(|_| String::default().into_boxed_str()); - - Ok(Self { - full_arch: full_arch.to_string().into_boxed_str(), - arch, - vendor, - os, - env, - abi, - }) - } -} - -/// Parser for [`TargetInfo`], contains cached information. -#[derive(Default, Debug)] -pub(crate) struct TargetInfoParser(OnceLock>); - -impl TargetInfoParser { - pub fn parse_from_cargo_environment_variables(&self) -> Result, Error> { - match self - .0 - .get_or_init(TargetInfoParserInner::from_cargo_environment_variables) - { - Ok(TargetInfoParserInner { - full_arch, - arch, - vendor, - os, - env, - abi, - }) => Ok(TargetInfo { - full_arch, - arch, - vendor, - os, - env, - abi, - }), - Err(e) => Err(e.clone()), - } - } -} - -/// Parse the full architecture in the target name into the simpler -/// `cfg(target_arch = "...")` that `rustc` exposes. -fn parse_arch(full_arch: &str) -> Option<&str> { - // NOTE: Some of these don't necessarily match an existing target in - // `rustc`. They're parsed anyhow to be as forward-compatible as possible, - // while still being correct. - // - // See also: - // https://docs.rs/cfg-expr/0.18.0/cfg_expr/targets/index.html - // https://docs.rs/target-lexicon/0.13.2/target_lexicon/enum.Architecture.html - // https://gcc.gnu.org/onlinedocs/gcc/Submodel-Options.html - // `clang -print-targets` - Some(match full_arch { - arch if arch.starts_with("mipsisa32r6") => "mips32r6", // mipsisa32r6 | mipsisa32r6el - arch if arch.starts_with("mipsisa64r6") => "mips64r6", // mipsisa64r6 | mipsisa64r6el - - arch if arch.starts_with("mips64") => "mips64", // mips64 | mips64el - arch if arch.starts_with("mips") => "mips", // mips | mipsel - - arch if arch.starts_with("loongarch64") => "loongarch64", - arch if arch.starts_with("loongarch32") => "loongarch32", - - arch if arch.starts_with("powerpc64") => "powerpc64", // powerpc64 | powerpc64le - arch if arch.starts_with("powerpc") => "powerpc", - arch if arch.starts_with("ppc64") => "powerpc64", - arch if arch.starts_with("ppc") => "powerpc", - - arch if arch.starts_with("x86_64") => "x86_64", // x86_64 | x86_64h - arch if arch.starts_with("i") && arch.ends_with("86") => "x86", // i386 | i586 | i686 - - "arm64ec" => "arm64ec", // https://github.com/rust-lang/rust/issues/131172 - arch if arch.starts_with("aarch64") => "aarch64", // arm64e | arm64_32 - arch if arch.starts_with("arm64") => "aarch64", // aarch64 | aarch64_be - - arch if arch.starts_with("arm") => "arm", // arm | armv7s | armeb | ... - arch if arch.starts_with("thumb") => "arm", // thumbv4t | thumbv7a | thumbv8m | ... - - arch if arch.starts_with("riscv64") => "riscv64", - arch if arch.starts_with("riscv32") => "riscv32", - - arch if arch.starts_with("wasm64") => "wasm64", - arch if arch.starts_with("wasm32") => "wasm32", // wasm32 | wasm32v1 - "asmjs" => "wasm32", - - arch if arch.starts_with("nvptx64") => "nvptx64", - arch if arch.starts_with("nvptx") => "nvptx", - - arch if arch.starts_with("bpf") => "bpf", // bpfeb | bpfel - - // https://github.com/bytecodealliance/wasmtime/tree/v30.0.1/pulley - arch if arch.starts_with("pulley64") => "pulley64", - arch if arch.starts_with("pulley32") => "pulley32", - - // https://github.com/Clever-ISA/Clever-ISA - arch if arch.starts_with("clever") => "clever", - - "sparc" | "sparcv7" | "sparcv8" => "sparc", - "sparc64" | "sparcv9" => "sparc64", - - "amdgcn" => "amdgpu", - "avr" => "avr", - "csky" => "csky", - "hexagon" => "hexagon", - "m68k" => "m68k", - "msp430" => "msp430", - "r600" => "r600", - "s390x" => "s390x", - "xtensa" => "xtensa", - - _ => return None, - }) -} - -/// Parse environment and ABI from the last component of the target name. -fn parse_envabi(last_component: &str) -> Option<(&str, &str)> { - let (env, abi) = match last_component { - // Combined environment and ABI - - // gnullvm | gnueabi | gnueabihf | gnuabiv2 | gnuabi64 | gnuspe | gnux32 | gnu_ilp32 - env_and_abi if env_and_abi.starts_with("gnu") => { - let abi = env_and_abi.strip_prefix("gnu").unwrap(); - let abi = abi.strip_prefix("_").unwrap_or(abi); - ("gnu", abi) - } - // musl | musleabi | musleabihf | muslabi64 | muslspe - env_and_abi if env_and_abi.starts_with("musl") => { - ("musl", env_and_abi.strip_prefix("musl").unwrap()) - } - // uclibc | uclibceabi | uclibceabihf - env_and_abi if env_and_abi.starts_with("uclibc") => { - ("uclibc", env_and_abi.strip_prefix("uclibc").unwrap()) - } - // newlib | newlibeabihf - env_and_abi if env_and_abi.starts_with("newlib") => { - ("newlib", env_and_abi.strip_prefix("newlib").unwrap()) - } - - // Environments - "msvc" => ("msvc", ""), - "ohos" => ("ohos", ""), - "qnx700" => ("nto70", ""), - "qnx710_iosock" => ("nto71_iosock", ""), - "qnx710" => ("nto71", ""), - "qnx800" => ("nto80", ""), - "sgx" => ("sgx", ""), - "threads" => ("threads", ""), - - // ABIs - "abi64" => ("", "abi64"), - "abiv2" => ("", "spe"), - "eabi" => ("", "eabi"), - "eabihf" => ("", "eabihf"), - "macabi" => ("", "macabi"), - "sim" => ("", "sim"), - "softfloat" => ("", "softfloat"), - "spe" => ("", "spe"), - "x32" => ("", "x32"), - - // Badly named targets, ELF is already known from target OS. - // Probably too late to fix now though. - "elf" => ("", ""), - // Undesirable to expose to user code (yet): - // https://github.com/rust-lang/rust/pull/131166#issuecomment-2389541917 - "freestanding" => ("", ""), - - _ => return None, - }; - Some((env, abi)) -} - -impl<'a> TargetInfo<'a> { - pub(crate) fn from_rustc_target(target: &'a str) -> Result { - // FIXME(madsmtm): This target should be renamed, cannot be parsed - // with the means we do below (since `none` must not be interpreted - // as an env/ABI). - if target == "x86_64-unknown-linux-none" { - return Ok(Self { - full_arch: "x86_64", - arch: "x86_64", - vendor: "unknown", - os: "linux", - env: "", - abi: "", - }); - } - - let mut components = target.split('-'); - - // Insist that the target name contains at least a valid architecture. - let full_arch = components.next().ok_or(Error::new( - ErrorKind::InvalidTarget, - "target was empty".to_string(), - ))?; - let arch = parse_arch(full_arch).ok_or_else(|| { - Error::new( - ErrorKind::UnknownTarget, - format!("target `{target}` had an unknown architecture"), - ) - })?; - - // Newer target names have begun omitting the vendor, so the only - // component we know must be there is the OS name. - let components: Vec<_> = components.collect(); - let (vendor, os, mut env, mut abi) = match &*components { - [] => { - return Err(Error::new( - ErrorKind::InvalidTarget, - format!("target `{target}` must have at least two components"), - )) - } - // Two components; format is `arch-os`. - [os] => ("unknown", *os, "", ""), - // The three-component case is a bit tricky to handle, it could - // either have the format `arch-vendor-os` or `arch-os-env+abi`. - [vendor_or_os, os_or_envabi] => { - // We differentiate between these by checking if the last - // component is an env/ABI; if it isn't, then it's probably - // an OS instead. - if let Some((env, abi)) = parse_envabi(os_or_envabi) { - ("unknown", *vendor_or_os, env, abi) - } else { - (*vendor_or_os, *os_or_envabi, "", "") - } - } - // Four components; format is `arch-vendor-os-env+abi`. - [vendor, os, envabi] => { - let (env, abi) = parse_envabi(envabi).ok_or_else(|| { - Error::new( - ErrorKind::UnknownTarget, - format!("unknown environment/ABI `{envabi}` in target `{target}`"), - ) - })?; - (*vendor, *os, env, abi) - } - _ => { - return Err(Error::new( - ErrorKind::InvalidTarget, - format!("too many components in target `{target}`"), - )) - } - }; - - // Part of the architecture name is carried over into the ABI. - match full_arch { - // https://github.com/rust-lang/compiler-team/issues/830 - arch if arch.starts_with("riscv32e") => { - abi = "ilp32e"; - } - _ => {} - } - - // Various environment/ABIs are determined based on OS name. - match os { - "3ds" | "rtems" | "espidf" => env = "newlib", - "vxworks" => env = "gnu", - "redox" => env = "relibc", - "aix" => abi = "vec-extabi", - _ => {} - } - - // Extra overrides for badly named targets. - match target { - // Actually simulator targets. - "i386-apple-ios" | "x86_64-apple-ios" | "x86_64-apple-tvos" => { - abi = "sim"; - } - // Name should've contained `muslabi64`. - "mips64-openwrt-linux-musl" => { - abi = "abi64"; - } - // Specifies abi even though not in name. - "armv6-unknown-freebsd" | "armv6k-nintendo-3ds" | "armv7-unknown-freebsd" => { - abi = "eabihf"; - } - // Specifies abi even though not in name. - "armv7-unknown-linux-ohos" | "armv7-unknown-trusty" => { - abi = "eabi"; - } - _ => {} - } - - let os = match os { - // Horizon is the common/internal OS name for 3DS and the Switch. - "3ds" | "switch" => "horizon", - // FIXME(madsmtm): macOS targets are badly named. - "darwin" => "macos", - - // WASI targets contain the preview version in them too. Should've - // been `wasi-p1`/`wasi-p2`, but that's probably too late now. - os if os.starts_with("wasi") => { - env = os.strip_prefix("wasi").unwrap(); - "wasi" - } - // FIXME(madsmtm): Badly named targets `*-linux-androideabi`, - // should be `*-android-eabi`. - "androideabi" => { - abi = "eabi"; - "android" - } - - os => os, - }; - - let vendor = match vendor { - // esp, esp32, esp32s2 etc. - vendor if vendor.starts_with("esp") => "espressif", - // FIXME(madsmtm): Badly named targets `*-linux-android*`, - // "linux" makes no sense as the vendor name. - "linux" if os == "android" || os == "androideabi" => "unknown", - // FIXME(madsmtm): Fix in `rustc` after - // https://github.com/rust-lang/compiler-team/issues/850. - "wali" => "unknown", - "lynx" => "unknown", - // Some Linux distributions set their name as the target vendor, - // so we have to assume that it can be an arbitary string. - vendor => vendor, - }; - - // Intentionally also marked as an ABI: - // https://github.com/rust-lang/rust/pull/86922 - if vendor == "fortanix" { - abi = "fortanix"; - } - if vendor == "uwp" { - abi = "uwp"; - } - - Ok(Self { - full_arch, - arch, - vendor, - os, - env, - abi, - }) - } -} - -#[cfg(test)] -#[allow(unexpected_cfgs)] -mod tests { - use std::process::Command; - - use super::TargetInfo; - use crate::ErrorKind; - - // Test tier 1 targets. - #[test] - fn tier1() { - let targets = [ - "aarch64-unknown-linux-gnu", - "aarch64-apple-darwin", - "i686-pc-windows-gnu", - "i686-pc-windows-msvc", - "i686-unknown-linux-gnu", - "x86_64-apple-darwin", - "x86_64-pc-windows-gnu", - "x86_64-pc-windows-msvc", - "x86_64-unknown-linux-gnu", - ]; - - for target in targets { - // Check that they parse. - let _ = TargetInfo::from_rustc_target(target).unwrap(); - } - } - - // Various custom target names not (or no longer) known by `rustc`. - #[test] - fn parse_extra() { - let targets = [ - "aarch64-unknown-none-gnu", - "aarch64-uwp-windows-gnu", - "arm-frc-linux-gnueabi", - "arm-unknown-netbsd-eabi", - "armv7neon-unknown-linux-gnueabihf", - "armv7neon-unknown-linux-musleabihf", - "thumbv7-unknown-linux-gnueabihf", - "thumbv7-unknown-linux-musleabihf", - "armv7-apple-ios", - "wasm32-wasi", - "x86_64-rumprun-netbsd", - "x86_64-unknown-linux", - "x86_64-alpine-linux-musl", - "x86_64-chimera-linux-musl", - "x86_64-foxkit-linux-musl", - "arm-poky-linux-gnueabi", - "x86_64-unknown-moturus", - ]; - - for target in targets { - // Check that they parse. - let _ = TargetInfo::from_rustc_target(target).unwrap(); - } - } - - fn target_from_rustc_cfgs<'a>(target: &'a str, cfgs: &'a str) -> TargetInfo<'a> { - // Cannot determine full architecture from cfgs. - let (full_arch, _rest) = target.split_once('-').expect("target to have arch"); - - let mut target = TargetInfo { - full_arch, - arch: "invalid-none-set", - vendor: "invalid-none-set", - os: "invalid-none-set", - env: "invalid-none-set", - // Not set in older Rust versions - abi: "", - }; - - for cfg in cfgs.lines() { - if let Some((name, value)) = cfg.split_once('=') { - // Remove whitespace, if `rustc` decided to insert any. - let name = name.trim(); - let value = value.trim(); - - // Remove quotes around value. - let value = value.strip_prefix('"').unwrap_or(value); - let value = value.strip_suffix('"').unwrap_or(value); - - match name { - "target_arch" => target.arch = value, - "target_vendor" => target.vendor = value, - "target_os" => target.os = value, - "target_env" => target.env = value, - "target_abi" => target.abi = value, - _ => {} - } - } else { - // Skip cfgs like `debug_assertions` and `unix`. - } - } - - target - } - - #[test] - fn unknown_env_determined_as_unknown() { - let err = TargetInfo::from_rustc_target("aarch64-unknown-linux-bogus").unwrap_err(); - assert!(matches!(err.kind, ErrorKind::UnknownTarget)); - } - - // Used in .github/workflows/test-rustc-targets.yml - #[test] - #[cfg_attr( - not(rustc_target_test), - ignore = "must enable explicitly with --cfg=rustc_target_test" - )] - fn parse_rustc_targets() { - let rustc = std::env::var("RUSTC").unwrap_or_else(|_| "rustc".to_string()); - - let target_list = Command::new(&rustc) - .arg("--print=target-list") - .output() - .unwrap() - .stdout; - let target_list = String::from_utf8(target_list).unwrap(); - - let mut has_failure = false; - for target in target_list.lines() { - let cfgs = Command::new(&rustc) - .arg("--target") - .arg(target) - .arg("--print=cfg") - .output() - .unwrap() - .stdout; - let cfgs = String::from_utf8(cfgs).unwrap(); - - let expected = target_from_rustc_cfgs(target, &cfgs); - let actual = TargetInfo::from_rustc_target(target); - - if Some(&expected) != actual.as_ref().ok() { - eprintln!("failed comparing {target}:"); - eprintln!(" expected: Ok({expected:?})"); - eprintln!(" actual: {actual:?}"); - eprintln!(); - has_failure = true; - } - } - - if has_failure { - panic!("failed comparing targets"); - } - } -} -- cgit v1.2.3