Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 7 additions & 1 deletion cmd/failsafe/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,16 @@ func run(args []string, stdin io.Reader, stdout, stderr io.Writer) int {
return subcommand.MCP(stdin, stdout, stderr)
case "explain":
cwd, _ := os.Getwd()
// Resolve the live mode the same way the hook does, so explain's
// verdict matches what the hook would actually decide.
liveMode, _, err := subcommand.ModeChainFromConfig(cfg, os.Getenv("HOME")).Resolve(subcommand.EnvFromOS())
if err != nil {
liveMode = "enabled" // fail-safe: an unresolvable mode never weakens the verdict
}
return subcommand.Explain(args[2:], stdout, subcommand.ExplainOptions{
Home: os.Getenv("HOME"),
CWD: cwd,
Mode: "enabled", // chain default is always hardcoded; no mode.default config key
Mode: liveMode,
})
case "test":
if len(args) < 3 {
Expand Down
17 changes: 17 additions & 0 deletions cmd/failsafe/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,20 @@ func TestRun_Report(t *testing.T) {
t.Errorf("report did not include the logged kubectl decision:\n%s", stdout.String())
}
}

// Regression: explain must resolve the live mode chain (env, pane files, …),
// not assume "enabled". A disabled pane must be reflected in explain's verdict,
// or the docs claim "explain shows what the hook would do" is false.
func TestRun_ExplainResolvesLiveMode(t *testing.T) {
t.Setenv("HOME", t.TempDir()) // isolate pane/config state
t.Setenv("FAILSAFE_MODE", "disabled")

var stdout, stderr bytes.Buffer
code := run([]string{"failsafe", "explain", "kubectl delete ns payments"}, nil, &stdout, &stderr)
if code != 0 && code != 1 { // 0=allow, 1=block are both valid exits; 2=usage error is not
t.Fatalf("exit code = %d; stderr=%s", code, stderr.String())
}
if !strings.Contains(stdout.String(), "Mode: disabled") {
t.Errorf("explain ignored FAILSAFE_MODE=disabled:\n%s", stdout.String())
}
}
87 changes: 58 additions & 29 deletions docs/assets/casts/audit.cast
Original file line number Diff line number Diff line change
@@ -1,29 +1,58 @@
{"version":2,"width":92,"height":22,"timestamp":1784331898}
[0.005935, "o", "\r\nThe default interactive shell is now zsh.\r\nTo update your account to use zsh, please run `chsh -s /bin/zsh`.\r\nFor more details, please visit https://support.apple.com/kb/HT208050.\r\n"]
[0.006175, "o", "\u001b[?1034h"]
[0.006191, "o", "bash-3.2$ "]
[0.013003, "i", "export PS1='$ '; cd \"/var/folders/12/mydd4m455zn9t__48syck4940000gn/T//failsafe-docs-home/project\"; clear\r"]
[0.013056, "o", "e"]
[0.013092, "o", "xport PS1='$ '; "]
[0.013099, "o", "cd"]
[0.013206, "o", " \"/var/folders/12/mydd4m455zn9t"]
[0.013214, "o", "__"]
[0.013315, "o", "48syck4940000gn/T//fa"]
[0.013368, "o", "ilsafe-do \rcs-"]
[0.013432, "o", "home/project\"; clear\r\n"]
[0.015773, "o", "\u001b[3J\u001b[H\u001b[2J"]
[0.016056, "o", "$ "]
[0.543033, "i", "failsafe audit\r"]
[0.543163, "o", "f"]
[0.543232, "o", "ailsafe audit\r\n"]
[0.557055, "o", "Policy layers in effect at /var/folders/12/mydd4m455zn9t__48syck4940000gn/T/failsafe-docs-home/project:\r\n\r\n [bundled]\r\n"]
[0.557309, "o", " bundled/aws.rego — 2 block rule(s)\r\n"]
[0.557386, "o", " bundled/failsafe.rego — 2 block rule(s)\r\n"]
[0.557536, "o", " bundled/git.rego — 0 block rule(s)\r\n"]
[0.557630, "o", " bundled/helm.rego — 2 block rule(s)\r\n"]
[0.557722, "o", " bundled/kubectl.rego — 1 block rule(s)\r\n"]
[0.557803, "o", " bundled/terraform.rego — 2 block rule(s)\r\n\r\n9 block rules total, 0 allow_override.\r\n"]
[0.558949, "o", "$ "]
[2.585943, "i", "exit\r"]
[2.586019, "o", "ex"]
[2.586093, "o", "it\r\nexit\r\n"]
{"version":2,"width":92,"height":22,"timestamp":1784334849}
[0.005793, "o", "\r\nThe default interactive shell is now zsh.\r\nTo update your account to use zsh, please run `chsh -s /bin/zsh`.\r\nFor more details, please visit https://support.apple.com/kb/HT208050.\r\n"]
[0.006007, "o", "\u001b[?1034h"]
[0.006020, "o", "bash-3.2$ "]
[0.011097, "i", "export PS1='$ '; cd \"/var/folders/12/mydd4m455zn9t__48syck4940000gn/T//failsafe-docs-home/project\"; clear\r"]
[0.011128, "o", "e"]
[0.011165, "o", "xport PS1='$ '; cd "]
[0.011213, "o", "\"/var/folders/12/my"]
[0.011260, "o", "dd4m455zn9t__4"]
[0.011267, "o", "8s"]
[0.011343, "o", "yck4940000gn/T//fai"]
[0.011386, "o", "lsafe-do \rcs-ho"]
[0.011428, "o", "me/project\"; clea"]
[0.011469, "o", "r\r\n"]
[0.013415, "o", "\u001b[3J\u001b[H\u001b[2J"]
[0.013650, "o", "$ "]
[0.536898, "i", "f"]
[0.537003, "o", "f"]
[0.612068, "i", "a"]
[0.612155, "o", "a"]
[0.683702, "i", "i"]
[0.683783, "o", "i"]
[0.748184, "i", "l"]
[0.748229, "o", "l"]
[0.815811, "i", "s"]
[0.815869, "o", "s"]
[0.884732, "i", "a"]
[0.884803, "o", "a"]
[0.951374, "i", "f"]
[0.951433, "o", "f"]
[1.025238, "i", "e"]
[1.025380, "o", "e"]
[1.090788, "i", " "]
[1.090838, "o", " "]
[1.159001, "i", "a"]
[1.159063, "o", "a"]
[1.226645, "i", "u"]
[1.226720, "o", "u"]
[1.296252, "i", "d"]
[1.296308, "o", "d"]
[1.367866, "i", "i"]
[1.367924, "o", "i"]
[1.437083, "i", "t"]
[1.437144, "o", "t"]
[1.507146, "i", "\r"]
[1.507203, "o", "\r\n"]
[1.516153, "o", "Policy layers in effect at /var/folders/12/mydd4m455zn9t__48syck4940000gn/T/failsafe-docs-home/project:\r\n\r\n [bundled]\r\n"]
[1.516374, "o", " bundled/aws.rego — 2 block rule(s)\r\n"]
[1.516422, "o", " bundled/failsafe.rego — 2 block rule(s)\r\n"]
[1.516444, "o", " bundled/git.rego — 0 block rule(s)\r\n"]
[1.516514, "o", " bundled/helm.rego — 2 block rule(s)\r\n"]
[1.516592, "o", " bundled/kubectl.rego — 1 block rule(s)\r\n"]
[1.516675, "o", " bundled/terraform.rego — 2 block rule(s)\r\n\r\n9 block rules total, 0 allow_override.\r\n"]
[1.517401, "o", "$ "]
[3.536809, "i", "exit\r"]
[3.536926, "o", "e"]
[3.536943, "o", "xit\r\n"]
[3.536986, "o", "exit\r\n"]
2 changes: 1 addition & 1 deletion docs/assets/casts/audit.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
264 changes: 231 additions & 33 deletions docs/assets/casts/explain-block.cast
Original file line number Diff line number Diff line change
@@ -1,33 +1,231 @@
{"version":2,"width":92,"height":22,"timestamp":1784331884}
[0.007669, "o", "\r\nThe default interactive shell is now zsh.\r\nTo update your account to use zsh, please run `chsh -s /bin/zsh`.\r\nFor more details, please visit https://support.apple.com/kb/HT208050.\r\n"]
[0.010914, "o", "\u001b[?1034h"]
[0.011090, "o", "bash-3.2$ "]
[0.016704, "i", "export PS1='$ '; cd \"/var/folders/12/mydd4m455zn9t__48syck4940000gn/T//failsafe-docs-home/project\"; clear\r"]
[0.016757, "o", "e"]
[0.016839, "o", "xport PS1='$ '; cd \"/var/fol"]
[0.016850, "o", "de"]
[0.016962, "o", "rs/12/mydd4m455zn9t__48sy"]
[0.017024, "o", "ck4940000gn/"]
[0.017032, "o", "T"]
[0.017127, "o", "//failsafe-do \rcs-hom"]
[0.017198, "o", "e/project\"; clear\r\n"]
[0.021285, "o", "\u001b[3J\u001b[H\u001b[2J"]
[0.021574, "o", "$ "]
[0.544513, "i", "failsafe explain \"kubectl --context arn:aws:eks:us-east-1:123456789012:cluster/prod delete ns payments\"\r"]
[0.544583, "o", "f"]
[0.544639, "o", "ailsafe explain \"k"]
[0.544713, "o", "ubectl --context "]
[0.544726, "o", "ar"]
[0.544847, "o", "n:aws:eks:us-east-1:"]
[0.544859, "o", "12"]
[0.544984, "o", "3456789012:cluste"]
[0.545062, "o", "r/prod de"]
[0.545137, "o", "lete \r ns pa"]
[0.545211, "o", "yments\"\r\n"]
[0.848167, "o", "── call 1: kubectl ──\r\nVerb: delete\r\nFlags:\r\n"]
[0.848216, "o", " context = arn:aws:eks:us-east-1:123456789012:cluster/prod\r\nPositional: ns payments\r\nEffective cwd: /var/folders/12/mydd4m455zn9t__48syck4940000gn/T/failsafe-docs-home/project\r\nMode: enabled\r\nPolicy chain (6 modules at this cwd):\r\n [bundled] bundled/aws.rego\r\n [bundled] bundled/failsafe.rego\r\n [bundled] bundled/git.rego\r\n [bundled] bundled/helm.rego\r\n [bundled] bundled/kubectl.rego\r\n [bundled] bundled/terraform.rego\r\nDecision: BLOCK\r\nReason : kubectl delete blocked while failsafe is enabled\r\n"]
[0.849408, "o", "$ "]
[2.882566, "i", "exit\r"]
[2.882745, "o", "e"]
[2.882788, "o", "xit\r\n"]
[2.882877, "o", "exit\r\n"]
{"version":2,"width":92,"height":22,"timestamp":1784334823}
[0.004300, "o", "\r\nThe default interactive shell is now zsh.\r\nTo update your account to use zsh, please run `chsh -s /bin/zsh`.\r\nFor more details, please visit https://support.apple.com/kb/HT208050.\r\n"]
[0.004605, "o", "\u001b[?1034hbash-3.2$ "]
[0.008887, "i", "export PS1='$ '; cd \"/var/folders/12/mydd4m455zn9t__48syck4940000gn/T//failsafe-docs-home/project\"; clear\r"]
[0.008944, "o", "e"]
[0.008984, "o", "xport PS1='$ '; cd \"/var/f"]
[0.008993, "o", "olde"]
[0.009079, "o", "rs/12/mydd4m455zn9t__48syck494000"]
[0.009084, "o", "0"]
[0.009086, "o", "g"]
[0.009089, "o", "n"]
[0.009151, "o", "/T//failsafe-do \rcs-hom"]
[0.009185, "o", "e/project\"; clea"]
[0.009218, "o", "r\r\n"]
[0.011101, "o", "\u001b[3J\u001b[H\u001b[2J"]
[0.011305, "o", "$ "]
[0.524566, "i", "f"]
[0.524653, "o", "f"]
[0.591133, "i", "a"]
[0.591185, "o", "a"]
[0.656933, "i", "i"]
[0.656977, "o", "i"]
[0.722965, "i", "l"]
[0.723013, "o", "l"]
[0.790270, "i", "s"]
[0.790322, "o", "s"]
[0.856334, "i", "a"]
[0.856379, "o", "a"]
[0.923842, "i", "f"]
[0.923894, "o", "f"]
[0.991235, "i", "e"]
[0.991287, "o", "e"]
[1.059449, "i", " "]
[1.059506, "o", " "]
[1.127136, "i", "e"]
[1.127196, "o", "e"]
[1.193988, "i", "x"]
[1.194055, "o", "x"]
[1.262359, "i", "p"]
[1.262430, "o", "p"]
[1.326483, "i", "l"]
[1.326541, "o", "l"]
[1.389784, "i", "a"]
[1.389837, "o", "a"]
[1.454047, "i", "i"]
[1.454088, "o", "i"]
[1.519117, "i", "n"]
[1.519183, "o", "n"]
[1.583495, "i", " "]
[1.583541, "o", " "]
[1.652557, "i", "\""]
[1.652629, "o", "\""]
[1.716813, "i", "k"]
[1.716867, "o", "k"]
[1.784570, "i", "u"]
[1.784624, "o", "u"]
[1.851673, "i", "b"]
[1.851730, "o", "b"]
[1.918567, "i", "e"]
[1.918627, "o", "e"]
[1.985452, "i", "c"]
[1.985498, "o", "c"]
[2.052410, "i", "t"]
[2.052458, "o", "t"]
[2.122370, "i", "l"]
[2.122432, "o", "l"]
[2.195485, "i", " "]
[2.195563, "o", " "]
[2.264328, "i", "-"]
[2.264417, "o", "-"]
[2.331462, "i", "-"]
[2.331506, "o", "-"]
[2.399034, "i", "c"]
[2.399087, "o", "c"]
[2.467399, "i", "o"]
[2.467456, "o", "o"]
[2.537710, "i", "n"]
[2.537804, "o", "n"]
[2.605700, "i", "t"]
[2.605770, "o", "t"]
[2.672689, "i", "e"]
[2.672768, "o", "e"]
[2.739452, "i", "x"]
[2.739503, "o", "x"]
[2.803879, "i", "t"]
[2.803934, "o", "t"]
[2.869406, "i", " "]
[2.869495, "o", " "]
[2.935837, "i", "a"]
[2.935885, "o", "a"]
[2.997366, "i", "r"]
[2.997416, "o", "r"]
[3.061840, "i", "n"]
[3.061893, "o", "n"]
[3.129341, "i", ":"]
[3.129401, "o", ":"]
[3.193124, "i", "a"]
[3.193181, "o", "a"]
[3.261219, "i", "w"]
[3.261268, "o", "w"]
[3.327434, "i", "s"]
[3.327482, "o", "s"]
[3.393364, "i", ":"]
[3.393411, "o", ":"]
[3.461350, "i", "e"]
[3.461409, "o", "e"]
[3.532832, "i", "k"]
[3.532901, "o", "k"]
[3.606090, "i", "s"]
[3.606175, "o", "s"]
[3.679299, "i", ":"]
[3.679369, "o", ":"]
[3.747239, "i", "u"]
[3.747334, "o", "u"]
[3.814713, "i", "s"]
[3.814752, "o", "s"]
[3.880518, "i", "-"]
[3.880563, "o", "-"]
[3.947592, "i", "e"]
[3.947646, "o", "e"]
[4.017352, "i", "a"]
[4.017422, "o", "a"]
[4.089702, "i", "s"]
[4.089797, "o", "s"]
[4.161091, "i", "t"]
[4.161155, "o", "t"]
[4.228802, "i", "-"]
[4.228885, "o", "-"]
[4.293712, "i", "1"]
[4.293764, "o", "1"]
[4.359526, "i", ":"]
[4.359571, "o", ":"]
[4.425429, "i", "1"]
[4.425486, "o", "1"]
[4.491568, "i", "2"]
[4.491625, "o", "2"]
[4.558319, "i", "3"]
[4.558377, "o", "3"]
[4.625343, "i", "4"]
[4.625400, "o", "4"]
[4.694108, "i", "5"]
[4.694167, "o", "5"]
[4.759564, "i", "6"]
[4.759628, "o", "6"]
[4.826793, "i", "7"]
[4.826856, "o", "7"]
[4.893609, "i", "8"]
[4.893661, "o", "8"]
[4.960664, "i", "9"]
[4.960722, "o", "9"]
[5.028871, "i", "0"]
[5.028926, "o", "0"]
[5.092111, "i", "1"]
[5.092171, "o", "1"]
[5.160811, "i", "2"]
[5.160867, "o", "2"]
[5.228150, "i", ":"]
[5.228215, "o", ":"]
[5.293785, "i", "c"]
[5.293837, "o", "c"]
[5.360933, "i", "l"]
[5.360987, "o", "l"]
[5.428940, "i", "u"]
[5.428997, "o", "u"]
[5.497721, "i", "s"]
[5.497793, "o", "s"]
[5.569537, "i", "t"]
[5.569617, "o", "t"]
[5.642320, "i", "e"]
[5.642397, "o", "e"]
[5.709363, "i", "r"]
[5.709454, "o", "r"]
[5.780519, "i", "/"]
[5.780602, "o", "/"]
[5.846083, "i", "p"]
[5.846127, "o", "p"]
[5.913533, "i", "r"]
[5.913647, "o", "r"]
[5.982615, "i", "o"]
[5.982689, "o", "o"]
[6.049044, "i", "d"]
[6.049102, "o", "d"]
[6.115504, "i", " "]
[6.115558, "o", " "]
[6.184849, "i", "d"]
[6.184899, "o", "d"]
[6.248980, "i", "e"]
[6.249038, "o", "e"]
[6.315944, "i", "l"]
[6.316003, "o", "l"]
[6.383705, "i", "e"]
[6.383810, "o", "e"]
[6.449221, "i", "t"]
[6.449295, "o", "t"]
[6.512343, "i", "e"]
[6.512405, "o", "e \r"]
[6.575826, "i", " "]
[6.575866, "o", " "]
[6.640099, "i", "n"]
[6.640141, "o", "n"]
[6.704344, "i", "s"]
[6.704387, "o", "s"]
[6.771080, "i", " "]
[6.771125, "o", " "]
[6.838123, "i", "p"]
[6.838198, "o", "p"]
[6.902998, "i", "a"]
[6.903051, "o", "a"]
[6.967990, "i", "y"]
[6.968050, "o", "y"]
[7.030989, "i", "m"]
[7.031029, "o", "m"]
[7.094314, "i", "e"]
[7.094368, "o", "e"]
[7.157317, "i", "n"]
[7.157362, "o", "n"]
[7.222577, "i", "t"]
[7.222625, "o", "t"]
[7.288976, "i", "s"]
[7.289036, "o", "s"]
[7.352101, "i", "\""]
[7.352148, "o", "\""]
[7.413834, "i", "\r"]
[7.413885, "o", "\r\n"]
[7.703114, "o", "── call 1: kubectl ──\r\nVerb: delete\r\nFlags:\r\n"]
[7.703163, "o", " context = arn:aws:eks:us-east-1:123456789012:cluster/prod\r\nPositional: ns payments\r\nEffective cwd: /var/folders/12/mydd4m455zn9t__48syck4940000gn/T/failsafe-docs-home/project\r\nMode: enabled\r\nPolicy chain (6 modules at this cwd):\r\n [bundled] bundled/aws.rego\r\n [bundled] bundled/failsafe.rego\r\n [bundled] bundled/git.rego\r\n [bundled] bundled/helm.rego\r\n [bundled] bundled/kubectl.rego\r\n [bundled] bundled/terraform.rego\r\nDecision: BLOCK\r\nReason : kubectl delete blocked while failsafe is enabled\r\n"]
[7.703842, "o", "$ "]
[9.727401, "i", "exit\r"]
[9.727520, "o", "e"]
[9.727581, "o", "xit\r\n"]
[9.727634, "o", "exit\r\n"]
2 changes: 1 addition & 1 deletion docs/assets/casts/explain-block.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading