Skip to content

Commit 26dc117

Browse files
committed
Add test to ensure agent fails on dirty tables after first connection
1 parent 93d8ee4 commit 26dc117

File tree

2 files changed

+70
-2
lines changed

2 files changed

+70
-2
lines changed

Diff for: mirrord/agent/iptables/src/lib.rs

+69-1
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ where
214214
/// IP tables chain names, and they are in danger of conflicting with each-other
215215
///
216216
/// returns `true` if iptables are clean and the agent can proceed, other returns `false`
217-
pub async fn ensure_iptables_clean(ipt: IPT) -> IPTablesResult<bool> {
217+
pub async fn ensure_iptables_clean(ipt: &IPT) -> IPTablesResult<bool> {
218218
let ipt = Arc::new(ipt);
219219
tracing::trace!("checking for leftover or existing iptable chains...");
220220
for name in [IPTABLE_PREROUTING, IPTABLE_MESH, IPTABLE_STANDARD] {
@@ -524,4 +524,72 @@ mod tests {
524524

525525
assert!(ipt.cleanup().await.is_ok());
526526
}
527+
528+
/// Check that dirty ip tables fail the ['SafeIpTables::ensure_iptables_clean'] check
529+
/// If there are any chains in the IP table with names used by the agent, the check should fail.
530+
/// A fresh IP table, or one with only non-agent names, should pass the check
531+
#[tokio::test]
532+
async fn fail_on_dirty() {
533+
let mut mock = MockIPTables::new();
534+
535+
// CASE 1: check that a fresh IP table passes cleanliness check
536+
mock.expect_list_rules()
537+
.with(eq("OUTPUT"))
538+
.returning(|_| Ok(vec![]));
539+
540+
let expected_success = SafeIpTables::ensure_iptables_clean(&mock).await;
541+
assert!(
542+
expected_success.is_ok(),
543+
"Fresh IP table should pass cleanliness check"
544+
);
545+
546+
// CASE 2: check that an IP table with one of mirrord's static chain names will fail the
547+
// cleanliness check
548+
mock.expect_create_chain()
549+
.with(eq(IPTABLE_PREROUTING))
550+
.times(1)
551+
.returning(|_| Ok(()));
552+
553+
mock.expect_insert_rule()
554+
.with(
555+
eq(IPTABLE_PREROUTING),
556+
eq("-m tcp -p tcp --dport 69 -j REDIRECT --to-ports 420"),
557+
eq(1),
558+
)
559+
.times(1)
560+
.returning(|_, _, _| Ok(()));
561+
562+
let expected_failure = SafeIpTables::ensure_iptables_clean(&mock).await;
563+
assert!(expected_failure.is_err(), "IP table that contains chain with name {IPTABLE_PREROUTING} should fail cleanliness check");
564+
565+
// CASE 3: check that an IP table with only rules that were not created by mirrord will pass
566+
// the cleanliness check
567+
mock.expect_remove_chain()
568+
.with(eq(IPTABLE_PREROUTING))
569+
.times(1)
570+
.returning(|_| Ok(()));
571+
572+
// add a non-mirrord chain
573+
let non_mirrord_chain = "MY_PET_CHAIN_NAME";
574+
575+
mock.expect_create_chain()
576+
.with(eq(non_mirrord_chain))
577+
.times(1)
578+
.returning(|_| Ok(()));
579+
580+
mock.expect_insert_rule()
581+
.with(
582+
eq(non_mirrord_chain),
583+
eq("-m tcp -p tcp --dport 69 -j REDIRECT --to-ports 420"),
584+
eq(1),
585+
)
586+
.times(1)
587+
.returning(|_, _, _| Ok(()));
588+
589+
let expected_success = SafeIpTables::ensure_iptables_clean(&mock).await;
590+
assert!(
591+
expected_success.is_ok(),
592+
"IP table that contains no chains with mirrord name should pass cleanliness check"
593+
);
594+
}
527595
}

Diff for: mirrord/agent/src/entrypoint.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -587,7 +587,7 @@ async fn start_agent(args: Args) -> AgentResult<()> {
587587
} else {
588588
new_iptables()
589589
};
590-
SafeIpTables::ensure_iptables_clean(IPTablesWrapper::from(iptables))
590+
SafeIpTables::ensure_iptables_clean(&IPTablesWrapper::from(iptables))
591591
.await
592592
.map_err(|error| AgentError::IPTablesSetupError(error.into()))
593593
})

0 commit comments

Comments
 (0)