Merge idunn/isolation-credential-evidence: delivered credentials, not LoadCredential
Cut idunn-deploy-provenance:cut_spec:cut-cut-isolation-credential-evidence.r1, report h1, Soul s1 (all claims hold). systemd 257 prints LoadCredential as [unprintable]; the workload's credential directory, read from its MainPID's root, must hold exactly the delivered names. Unblocks Vili's promotion. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
commit
804ed759c9
6 changed files with 335 additions and 45 deletions
306
src/drivers.rs
306
src/drivers.rs
|
|
@ -470,6 +470,9 @@ pub struct SystemdWorkloadObservation {
|
|||
pub no_new_privileges: bool,
|
||||
pub umask: String,
|
||||
pub inaccessible_paths: String,
|
||||
/// Retired wire slot. systemd 257 displays `LoadCredential` as `[unprintable]` for
|
||||
/// every unit, so it was never evidence: written empty, never compared. Kept so
|
||||
/// compact (positional) MessagePack records of earlier Idunns still decode.
|
||||
pub load_credential: String,
|
||||
pub main_pid: u32,
|
||||
pub process_start_time: u64,
|
||||
|
|
@ -2459,7 +2462,6 @@ fn changed_systemd_workload_identity_fields(
|
|||
no_new_privileges,
|
||||
umask,
|
||||
inaccessible_paths,
|
||||
load_credential,
|
||||
main_pid,
|
||||
process_start_time,
|
||||
process_uids,
|
||||
|
|
@ -2859,7 +2861,6 @@ impl SystemdTransientWorkloadDriver {
|
|||
OsString::from("--property=NoNewPrivileges"),
|
||||
OsString::from("--property=UMask"),
|
||||
OsString::from("--property=InaccessiblePaths"),
|
||||
OsString::from("--property=LoadCredential"),
|
||||
OsString::from("--property=OpenFile"),
|
||||
OsString::from("--property=WorkingDirectory"),
|
||||
OsString::from("--property=ControlGroup"),
|
||||
|
|
@ -2971,38 +2972,7 @@ impl SystemdTransientWorkloadDriver {
|
|||
let umask = required_systemd_property(&values, "UMask")?.to_owned();
|
||||
let inaccessible_paths =
|
||||
required_systemd_property(&values, "InaccessiblePaths")?.to_owned();
|
||||
let load_credential = required_systemd_property(&values, "LoadCredential")?.to_owned();
|
||||
ensure!(
|
||||
service_type == "exec"
|
||||
&& restart_policy == "no"
|
||||
&& kill_mode == "mixed"
|
||||
// `User` is deliberately not asserted here. Idunn never emits a
|
||||
// User property, and systemd reports the identity it *allocated*
|
||||
// for a DynamicUser unit -- the unit name, or a generated `_du…`
|
||||
// when that is too long -- so the property is never empty for a
|
||||
// running workload and cannot tell an allocated identity from a
|
||||
// pinned one. The invariant it was reaching for, that the workload
|
||||
// does not run as a persistent named account, is carried by
|
||||
// `dynamic_user` below and by Idunn never passing User at all.
|
||||
&& dynamic_user
|
||||
&& supplementary_groups.is_empty()
|
||||
&& capability_bounding_set.is_empty()
|
||||
&& ambient_capabilities.is_empty()
|
||||
&& private_mounts
|
||||
&& private_pids
|
||||
&& protect_proc == "invisible"
|
||||
&& proc_subset == "all"
|
||||
&& no_new_privileges
|
||||
&& umask == "0007"
|
||||
&& inaccessible_paths == self.credential_root.display().to_string()
|
||||
&& load_credential
|
||||
== if service_credential_names.is_empty() {
|
||||
""
|
||||
} else {
|
||||
"[unprintable]"
|
||||
},
|
||||
"systemd workload isolation properties differ from the Idunn contract"
|
||||
);
|
||||
require_systemd_isolation_contract(&values, &self.credential_root)?;
|
||||
let working_directory =
|
||||
PathBuf::from(required_systemd_property(&values, "WorkingDirectory")?);
|
||||
ensure!(
|
||||
|
|
@ -3144,6 +3114,11 @@ impl SystemdTransientWorkloadDriver {
|
|||
);
|
||||
Some(path)
|
||||
};
|
||||
require_delivered_credentials(
|
||||
&process_root.join("root"),
|
||||
unit,
|
||||
service_credential_names,
|
||||
)?;
|
||||
let activation_descriptor = &parent_only_file_descriptors[0];
|
||||
ensure!(
|
||||
activation_descriptor.fd_name == IDUNN_RUNTIME_ACTIVATION_CREDENTIAL_NAME
|
||||
|
|
@ -3251,7 +3226,7 @@ impl SystemdTransientWorkloadDriver {
|
|||
no_new_privileges,
|
||||
umask,
|
||||
inaccessible_paths,
|
||||
load_credential,
|
||||
load_credential: String::new(),
|
||||
main_pid,
|
||||
process_start_time,
|
||||
process_uids: process_security.uids,
|
||||
|
|
@ -3465,12 +3440,7 @@ impl SystemdTransientWorkloadDriver {
|
|||
// workload. The same applies to `Group` when no fixed state group is
|
||||
// bound. In that case the numeric primary GID must match the allocated
|
||||
// UID; a fixed state group still requires both its exact name and GID.
|
||||
let expected_load_credential = if regular_credential_names.is_empty() {
|
||||
""
|
||||
} else {
|
||||
"[unprintable]"
|
||||
};
|
||||
let launch_contract: [(bool, &str); 27] = [
|
||||
let launch_contract: [(bool, &str); 26] = [
|
||||
(
|
||||
observation.unit_description == expected_description,
|
||||
"unit description",
|
||||
|
|
@ -3510,10 +3480,6 @@ impl SystemdTransientWorkloadDriver {
|
|||
observation.inaccessible_paths == self.credential_root.display().to_string(),
|
||||
"inaccessible paths",
|
||||
),
|
||||
(
|
||||
observation.load_credential == expected_load_credential,
|
||||
"load credential",
|
||||
),
|
||||
(
|
||||
observation.working_directory == installed,
|
||||
"working directory",
|
||||
|
|
@ -7269,6 +7235,44 @@ fn path_inside_process_root(process_root: &Path, absolute_path: &Path) -> Result
|
|||
Ok(process_root.join(absolute_path.strip_prefix(Path::new("/"))?))
|
||||
}
|
||||
|
||||
/// The workload holds exactly the credentials Idunn delivered: the entries of
|
||||
/// `/run/credentials/<unit>` in the MainPID's root (`process_root` is that root)
|
||||
/// equal `expected`, and an absent directory is the empty set. Only entry names
|
||||
/// are read; a credential is never opened here. The message names no credential.
|
||||
fn require_delivered_credentials(
|
||||
process_root: &Path,
|
||||
unit: &str,
|
||||
expected: &[String],
|
||||
) -> Result<()> {
|
||||
let directory = path_inside_process_root(
|
||||
process_root,
|
||||
&Path::new("/run/credentials").join(unit),
|
||||
)?;
|
||||
let mut delivered = Vec::new();
|
||||
match fs::read_dir(&directory) {
|
||||
Ok(entries) => {
|
||||
for entry in entries {
|
||||
let name = entry
|
||||
.context("reading a delivered credential entry")?
|
||||
.file_name()
|
||||
.into_string()
|
||||
.map_err(|_| anyhow!("delivered credential name is not UTF-8"))?;
|
||||
delivered.push(name);
|
||||
}
|
||||
}
|
||||
Err(error) if error.kind() == std::io::ErrorKind::NotFound => {}
|
||||
Err(error) => {
|
||||
return Err(error).context("reading the delivered credential directory");
|
||||
}
|
||||
}
|
||||
delivered.sort();
|
||||
ensure!(
|
||||
delivered == expected,
|
||||
"systemd delivered credentials that differ from the Idunn launch"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn linux_process_security(
|
||||
status_path: &Path,
|
||||
expected_host_pid: u32,
|
||||
|
|
@ -7484,6 +7488,56 @@ fn parse_systemd_boolean(values: &BTreeMap<String, String>, name: &str) -> Resul
|
|||
}
|
||||
}
|
||||
|
||||
/// The isolation properties of a transient workload unit, judged from `systemctl
|
||||
/// show`. `LoadCredential` is absent on purpose: systemd 257 displays it as
|
||||
/// `[unprintable]` whatever the unit holds, so what the workload was given is
|
||||
/// judged by `require_delivered_credentials` from the delivered directory.
|
||||
fn require_systemd_isolation_contract(
|
||||
values: &BTreeMap<String, String>,
|
||||
credential_root: &Path,
|
||||
) -> Result<()> {
|
||||
let service_type = required_systemd_property(values, "Type")?;
|
||||
let restart_policy = required_systemd_property(values, "Restart")?;
|
||||
let kill_mode = required_systemd_property(values, "KillMode")?;
|
||||
let dynamic_user = parse_systemd_boolean(values, "DynamicUser")?;
|
||||
let supplementary_groups = systemd_property(values, "SupplementaryGroups")?;
|
||||
let capability_bounding_set = systemd_property(values, "CapabilityBoundingSet")?;
|
||||
let ambient_capabilities = systemd_property(values, "AmbientCapabilities")?;
|
||||
let private_mounts = parse_systemd_boolean(values, "PrivateMounts")?;
|
||||
let private_pids = parse_systemd_boolean(values, "PrivatePIDs")?;
|
||||
let protect_proc = required_systemd_property(values, "ProtectProc")?;
|
||||
let proc_subset = required_systemd_property(values, "ProcSubset")?;
|
||||
let no_new_privileges = parse_systemd_boolean(values, "NoNewPrivileges")?;
|
||||
let umask = required_systemd_property(values, "UMask")?;
|
||||
let inaccessible_paths = required_systemd_property(values, "InaccessiblePaths")?;
|
||||
ensure!(
|
||||
service_type == "exec"
|
||||
&& restart_policy == "no"
|
||||
&& kill_mode == "mixed"
|
||||
// `User` is deliberately not asserted here. Idunn never emits a
|
||||
// User property, and systemd reports the identity it *allocated*
|
||||
// for a DynamicUser unit -- the unit name, or a generated `_du…`
|
||||
// when that is too long -- so the property is never empty for a
|
||||
// running workload and cannot tell an allocated identity from a
|
||||
// pinned one. The invariant it was reaching for, that the workload
|
||||
// does not run as a persistent named account, is carried by
|
||||
// `dynamic_user` below and by Idunn never passing User at all.
|
||||
&& dynamic_user
|
||||
&& supplementary_groups.is_empty()
|
||||
&& capability_bounding_set.is_empty()
|
||||
&& ambient_capabilities.is_empty()
|
||||
&& private_mounts
|
||||
&& private_pids
|
||||
&& protect_proc == "invisible"
|
||||
&& proc_subset == "all"
|
||||
&& no_new_privileges
|
||||
&& umask == "0007"
|
||||
&& inaccessible_paths == credential_root.display().to_string(),
|
||||
"systemd workload isolation properties differ from the Idunn contract"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn read_process_environment(path: &Path) -> Result<Vec<Vec<u8>>> {
|
||||
let bytes = fs::read(path)
|
||||
.with_context(|| format!("reading process environment {}", path.display()))?;
|
||||
|
|
@ -9968,6 +10022,168 @@ processes 9
|
|||
);
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn fixture_show_properties(text: &str) -> Result<BTreeMap<String, String>> {
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
|
||||
let temp = tempfile::tempdir()?;
|
||||
let shown = temp.path().join("shown");
|
||||
std::fs::write(&shown, text)?;
|
||||
let systemctl = temp.path().join("systemctl");
|
||||
std::fs::write(
|
||||
&systemctl,
|
||||
format!("#!/bin/sh\ncat '{}'\nexit 0\n", shown.display()),
|
||||
)?;
|
||||
std::fs::set_permissions(&systemctl, std::fs::Permissions::from_mode(0o755))?;
|
||||
let driver = SystemdTransientWorkloadDriver {
|
||||
systemctl_program: systemctl,
|
||||
..Default::default()
|
||||
};
|
||||
Ok(driver
|
||||
.show_unit("idunn-test.service")?
|
||||
.context("fixture unit was not found")?
|
||||
.properties)
|
||||
}
|
||||
|
||||
/// systemd 257 prints `LoadCredential=[unprintable]` for every unit, so the
|
||||
/// isolation contract must admit the real output of a unit with no service
|
||||
/// credential as well as one with one. The inputs are real captures, not a
|
||||
/// re-spelling.
|
||||
#[cfg(unix)]
|
||||
#[test]
|
||||
fn systemd_257_isolation_contract_admits_a_presence_only_target_and_one_with_service_credentials(
|
||||
) -> Result<()> {
|
||||
let root = Path::new("/run/idunn/activation-credentials");
|
||||
let vili = include_str!("../tests/fixtures/systemd-257/vili-presence-identity-only.show");
|
||||
let odin = include_str!(
|
||||
"../tests/fixtures/systemd-257/odin-presence-and-one-service-credential.show"
|
||||
);
|
||||
for text in [vili, odin] {
|
||||
assert!(text.contains("LoadCredential=[unprintable]"));
|
||||
require_systemd_isolation_contract(&fixture_show_properties(text)?, root)?;
|
||||
}
|
||||
let default_proc = vili.replace("ProtectProc=invisible", "ProtectProc=default");
|
||||
assert_ne!(default_proc, vili);
|
||||
let other_path = vili.replace(
|
||||
"/run/idunn/activation-credentials",
|
||||
"/run/idunn/elsewhere",
|
||||
);
|
||||
assert_ne!(other_path, vili);
|
||||
for text in [default_proc, other_path] {
|
||||
let error =
|
||||
require_systemd_isolation_contract(&fixture_show_properties(&text)?, root)
|
||||
.expect_err("a drifted isolation property must be refused");
|
||||
assert_eq!(
|
||||
error.to_string(),
|
||||
"systemd workload isolation properties differ from the Idunn contract"
|
||||
);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[test]
|
||||
fn delivered_credentials_are_exactly_the_launch_names() -> Result<()> {
|
||||
let unit = "idunn-test.service";
|
||||
let names = |list: &[&str]| list.iter().map(|name| name.to_string()).collect::<Vec<_>>();
|
||||
// `Some(entries)` creates the unit's directory in a fresh process root.
|
||||
let check = |delivered: Option<&[&str]>, expected: &[&str]| -> Result<()> {
|
||||
let temp = tempfile::tempdir()?;
|
||||
if let Some(entries) = delivered {
|
||||
let directory = temp.path().join("run/credentials").join(unit);
|
||||
std::fs::create_dir_all(&directory)?;
|
||||
for entry in entries {
|
||||
std::fs::write(directory.join(entry), "canary-credential-contents")?;
|
||||
}
|
||||
}
|
||||
let result = require_delivered_credentials(temp.path(), unit, &names(expected));
|
||||
if let Err(error) = &result {
|
||||
let text = format!("{error:#}");
|
||||
for canary in ["STOWAWAY", "ODIN_TOPOLOGY_IDENTITY", "canary-credential"] {
|
||||
assert!(!text.contains(canary), "error echoed {canary}");
|
||||
}
|
||||
assert!(!text.contains(&*temp.path().to_string_lossy()));
|
||||
}
|
||||
result
|
||||
};
|
||||
check(None, &[])?;
|
||||
check(Some(&[]), &[])?;
|
||||
check(Some(&["ODIN_TOPOLOGY_IDENTITY"]), &["ODIN_TOPOLOGY_IDENTITY"])?;
|
||||
check(Some(&["B", "A"]), &["A", "B"])?;
|
||||
for (delivered, expected) in [
|
||||
(None, &["ODIN_TOPOLOGY_IDENTITY"][..]),
|
||||
(Some(&[][..]), &["ODIN_TOPOLOGY_IDENTITY"][..]),
|
||||
(
|
||||
Some(&["ODIN_TOPOLOGY_IDENTITY", "STOWAWAY"][..]),
|
||||
&["ODIN_TOPOLOGY_IDENTITY"][..],
|
||||
),
|
||||
(Some(&["STOWAWAY"][..]), &[][..]),
|
||||
(Some(&["A"][..]), &["B"][..]),
|
||||
(Some(&["A"][..]), &["A", "B"][..]),
|
||||
] {
|
||||
let error = check(delivered, expected)
|
||||
.expect_err("delivered credentials differing from the launch must be refused");
|
||||
assert_eq!(
|
||||
error.to_string(),
|
||||
"systemd delivered credentials that differ from the Idunn launch"
|
||||
);
|
||||
}
|
||||
// A directory that cannot be listed is a refusal, never the empty set.
|
||||
let temp = tempfile::tempdir()?;
|
||||
let parent = temp.path().join("run/credentials");
|
||||
std::fs::create_dir_all(&parent)?;
|
||||
std::fs::write(parent.join(unit), "")?;
|
||||
let error = require_delivered_credentials(temp.path(), unit, &[])
|
||||
.expect_err("an unreadable credential directory must be refused");
|
||||
assert!(!format!("{error:#}").contains(&*temp.path().to_string_lossy()));
|
||||
// The rule reads the process root it is given, never the host's /run.
|
||||
let temp = tempfile::tempdir()?;
|
||||
let outside = tempfile::tempdir()?;
|
||||
let directory = outside.path().join("run/credentials").join(unit);
|
||||
std::fs::create_dir_all(&directory)?;
|
||||
std::fs::write(directory.join("A"), "")?;
|
||||
require_delivered_credentials(temp.path(), unit, &[])?;
|
||||
assert!(require_delivered_credentials(temp.path(), unit, &names(&["A"])).is_err());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Live Odin and StreamPixels hold records persisted by the Idunn that
|
||||
/// compared `LoadCredential`: `[unprintable]` in the retired slot. The bytes
|
||||
/// are that Idunn's own output (tests/fixtures/pre-cut-*); they must decode
|
||||
/// under both encodings and read as no drift against a new observation, or
|
||||
/// `stop` refuses to stop the incumbents.
|
||||
#[test]
|
||||
fn an_incumbent_recorded_with_the_display_form_is_not_identity_drift() -> Result<()> {
|
||||
let decode_hex = |text: &str| -> Vec<u8> {
|
||||
(0..text.trim().len())
|
||||
.step_by(2)
|
||||
.map(|at| u8::from_str_radix(&text.trim()[at..at + 2], 16).unwrap())
|
||||
.collect()
|
||||
};
|
||||
let mut recorded = systemd_audit_observation("no", 61_000);
|
||||
recorded.load_credential = "[unprintable]".into();
|
||||
let observed = systemd_audit_observation("no", 61_000);
|
||||
assert!(observed.load_credential.is_empty());
|
||||
for hex in [
|
||||
include_str!("../tests/fixtures/pre-cut-systemd-observation.compact.hex"),
|
||||
include_str!("../tests/fixtures/pre-cut-systemd-observation.named.hex"),
|
||||
] {
|
||||
let decoded: WorkloadObservation = rmp_serde::from_slice(&decode_hex(hex))?;
|
||||
assert_eq!(decoded, WorkloadObservation::Systemd(recorded.clone()));
|
||||
let WorkloadObservation::Systemd(prior) = decoded else {
|
||||
unreachable!()
|
||||
};
|
||||
assert!(changed_systemd_workload_identity_fields(&observed, &prior).is_empty());
|
||||
}
|
||||
let mut drifted = observed.clone();
|
||||
drifted.main_pid += 1;
|
||||
assert_eq!(
|
||||
changed_systemd_workload_identity_fields(&drifted, &recorded),
|
||||
vec!["main_pid"]
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn host_isolation_is_two_live_distinct_processes_on_one_host() {
|
||||
let live = |pid: u32, created: u64| {
|
||||
|
|
|
|||
16
tests/fixtures/README.md
vendored
16
tests/fixtures/README.md
vendored
|
|
@ -10,3 +10,19 @@ It is checked in because the TypeScript runtime emits a camelCase MessagePack
|
|||
map while Rust `DatabaseEntry` derives tuple payloads. Idunn must prove it can
|
||||
decode the producer's real wire shape rather than round-tripping a fixture it
|
||||
serialized itself.
|
||||
|
||||
# systemd 257 `systemctl show` captures
|
||||
|
||||
`systemd-257/*.show` are the verbatim output of systemd 257.13 for the 27
|
||||
properties `show_unit` requested at `112a7a5`, captured read-only on Yggdrasil
|
||||
on 2026-10-24: `vili-presence-identity-only.show` (a failed idunn-vili unit whose
|
||||
only credential is the presence identity) and
|
||||
`odin-presence-and-one-service-credential.show` (the live Odin unit). systemd 257
|
||||
prints `LoadCredential=[unprintable]` in both. Tests read these bytes; do not edit.
|
||||
|
||||
# Pre-cut systemd observation records
|
||||
|
||||
`pre-cut-systemd-observation.{compact,named}.hex` are the two MessagePack
|
||||
encodings of a `SystemdWorkloadObservation` with `load_credential` set to
|
||||
`[unprintable]`, produced by the code at `112a7a5` (the form live incumbents
|
||||
persisted). They pin that later Idunns still decode such records.
|
||||
|
|
|
|||
1
tests/fixtures/pre-cut-systemd-observation.compact.hex
vendored
Normal file
1
tests/fixtures/pre-cut-systemd-observation.compact.hex
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
dc0033d94e6964756e6e2d616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161612e73657276696365aa4964756e6e2074657374a3696e7601a465786563a26e6fa56d69786564c3a6753631303030a6753631303030a0a0a0c3c3a9696e76697369626c65a3616c6cc3a430303037a0ad5b756e7072696e7461626c655dcd10920194cdee48cdee48cdee48cdee4894cdee48cdee48cdee48cdee4891cdee480000000000c391010708b52f6f70742f746573742f62696e2f736572766963650101d9477368613235362d31313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131d9477368613235362d61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161a92f6f70742f74657374a92f72756e2f74657374d9477368613235362d3232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323290d9477368613235362d33333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333d9202f73797374656d2e736c6963652f6964756e6e2d746573742e73657276696365c090aa61637469766174696f6edc0020010101010101010101010101010101010101010101010101010101010101010190
|
||||
1
tests/fixtures/pre-cut-systemd-observation.named.hex
vendored
Normal file
1
tests/fixtures/pre-cut-systemd-observation.named.hex
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
de0033a4756e6974d94e6964756e6e2d616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161612e73657276696365b0756e69745f6465736372697074696f6eaa4964756e6e2074657374ad696e766f636174696f6e5f6964a3696e76d923657865635f6d61696e5f73746172745f74696d657374616d705f6d6f6e6f746f6e696301ac736572766963655f74797065a465786563ae726573746172745f706f6c696379a26e6fa96b696c6c5f6d6f6465a56d69786564ac64796e616d69635f75736572c3ac73797374656d645f75736572a6753631303030ad73797374656d645f67726f7570a6753631303030b4737570706c656d656e746172795f67726f757073a0b76361706162696c6974795f626f756e64696e675f736574a0b4616d6269656e745f6361706162696c6974696573a0ae707269766174655f6d6f756e7473c3ac707269766174655f70696473c3ac70726f746563745f70726f63a9696e76697369626c65ab70726f635f737562736574a3616c6cb16e6f5f6e65775f70726976696c65676573c3a5756d61736ba430303037b2696e61636365737369626c655f7061746873a0af6c6f61645f63726564656e7469616cad5b756e7072696e7461626c655da86d61696e5f706964cd1092b270726f636573735f73746172745f74696d6501ac70726f636573735f7569647394cdee48cdee48cdee48cdee48ac70726f636573735f6769647394cdee48cdee48cdee48cdee48ae70726f636573735f67726f75707391cdee48b770726f636573735f6361705f696e686572697461626c6500b570726f636573735f6361705f7065726d697474656400b570726f636573735f6361705f65666665637469766500b470726f636573735f6361705f626f756e64696e6700b370726f636573735f6361705f616d6269656e7400b970726f636573735f6e6f5f6e65775f70726976696c65676573c3b670726f636573735f6e616d6573706163655f706964739101b26d6f756e745f6e616d6573706163655f696407b07069645f6e616d6573706163655f696408aa65786563757461626c65b52f6f70742f746573742f62696e2f73657276696365b165786563757461626c655f64657669636501b065786563757461626c655f696e6f646501b165786563757461626c655f736861323536d9477368613235362d31313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131b372756e74696d655f696e7374616e63655f6964d9477368613235362d61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161b1776f726b696e675f6469726563746f7279a92f6f70742f74657374ae72756e74696d655f62756e646c65a92f72756e2f74657374b3636f6d6d616e645f6c696e655f736861323536d9477368613235362d32323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232b1656e7669726f6e6d656e745f6e616d657390bb656e7669726f6e6d656e745f636f6e74726163745f736861323536d9477368613235362d33333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333ad636f6e74726f6c5f67726f7570d9202f73797374656d2e736c6963652f6964756e6e2d746573742e73657276696365b563726564656e7469616c735f6469726563746f7279c0bc706172656e745f6f6e6c795f66696c655f64657363726970746f727390bd61637469766174696f6e5f7369676e65725f6964656e746974795f6964aa61637469766174696f6ebc61637469766174696f6e5f7369676e65725f7075626c69635f6b6579dc00200101010101010101010101010101010101010101010101010101010101010101b3736572766963655f63726564656e7469616c7390
|
||||
28
tests/fixtures/systemd-257/odin-presence-and-one-service-credential.show
vendored
Normal file
28
tests/fixtures/systemd-257/odin-presence-and-one-service-credential.show
vendored
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
Type=exec
|
||||
Restart=no
|
||||
MainPID=2571
|
||||
OpenFile=/run/idunn/activation-credentials/sha256-7cfe5cd1e87839e029c7425eb1b586b6b0d94dd79d7376eed3b156386f2c7af8.credential:gamecult-idunn-runtime-activation-key:read-only
|
||||
OpenFile=/etc/gamecult/odin/runtime-presence-identity.cc:gamecult-runtime-presence-identity:read-only
|
||||
ExecMainStartTimestampMonotonic=20630000
|
||||
ControlGroup=/system.slice/idunn-odin-7cfe5cd1e87839e029c7425eb1b586b6b0d94dd79d7376eed3b156386f2c7af8.service
|
||||
UMask=0007
|
||||
WorkingDirectory=/srv/odin/releases/sha256-e5c7d0b2b9c0a8ffba368aeb08abdbe37ae0d17484a785e60a66ec4a62b2f18c
|
||||
CapabilityBoundingSet=
|
||||
AmbientCapabilities=
|
||||
User=_duc23369f1b8b167db
|
||||
Group=odin
|
||||
DynamicUser=yes
|
||||
LoadCredential=[unprintable]
|
||||
SupplementaryGroups=
|
||||
InaccessiblePaths=/run/idunn/activation-credentials
|
||||
PrivateMounts=yes
|
||||
PrivatePIDs=yes
|
||||
NoNewPrivileges=yes
|
||||
ProtectProc=invisible
|
||||
ProcSubset=all
|
||||
KillMode=mixed
|
||||
Description=Idunn odin sha256-7cfe5cd1e87839e029c7425eb1b586b6b0d94dd79d7376eed3b156386f2c7af8
|
||||
LoadState=loaded
|
||||
ActiveState=active
|
||||
SubState=running
|
||||
InvocationID=ada48921043449f39dacc87b14a1bf70
|
||||
28
tests/fixtures/systemd-257/vili-presence-identity-only.show
vendored
Normal file
28
tests/fixtures/systemd-257/vili-presence-identity-only.show
vendored
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
Type=exec
|
||||
Restart=no
|
||||
MainPID=0
|
||||
OpenFile=/run/idunn/activation-credentials/sha256-b507e1705a70f8eee72f355e7db637acab8eb37880b5d25245fda68d80f63041.credential:gamecult-idunn-runtime-activation-key:read-only
|
||||
OpenFile=/etc/gamecult/vili/runtime-presence-identity.cc:gamecult-runtime-presence-identity:read-only
|
||||
ExecMainStartTimestampMonotonic=520083420000
|
||||
ControlGroup=
|
||||
UMask=0007
|
||||
WorkingDirectory=/srv/vili-idunn/releases/sha256-aeaee4e1669742572c45a3f26bc86893c44b2a4149520975eb7d8a28aa931906
|
||||
CapabilityBoundingSet=
|
||||
AmbientCapabilities=
|
||||
User=_du8c06c563aac6d205
|
||||
Group=vili-state
|
||||
DynamicUser=yes
|
||||
LoadCredential=[unprintable]
|
||||
SupplementaryGroups=
|
||||
InaccessiblePaths=/run/idunn/activation-credentials
|
||||
PrivateMounts=yes
|
||||
PrivatePIDs=yes
|
||||
NoNewPrivileges=yes
|
||||
ProtectProc=invisible
|
||||
ProcSubset=all
|
||||
KillMode=mixed
|
||||
Description=Idunn vili sha256-b507e1705a70f8eee72f355e7db637acab8eb37880b5d25245fda68d80f63041
|
||||
LoadState=loaded
|
||||
ActiveState=failed
|
||||
SubState=failed
|
||||
InvocationID=8f7a349f2f8f49fe87ac5d89239260b4
|
||||
Loading…
Reference in a new issue