133 lines
4.5 KiB
Crystal
133 lines
4.5 KiB
Crystal
# ===================
|
|
# ©AngelaMos | 2026
|
|
# policy_spec.cr
|
|
# ===================
|
|
|
|
require "../../spec_helper"
|
|
require "../../../src/cre/policy/policy"
|
|
|
|
describe CRE::Policy::Policy do
|
|
it "matches via the matcher" do
|
|
p = CRE::Policy::Policy.new(
|
|
name: "p1",
|
|
description: nil,
|
|
matcher: ->(c : CRE::Domain::Credential) { c.kind.env_file? },
|
|
max_age: 30.days,
|
|
warn_at: nil,
|
|
enforce_action: CRE::Policy::Action::NotifyOnly,
|
|
notify_channels: [] of CRE::Policy::Channel,
|
|
triggers: {} of CRE::Policy::Trigger => CRE::Policy::Action,
|
|
)
|
|
|
|
matching = CRE::Domain::Credential.new(
|
|
id: UUID.random, external_id: "x", kind: CRE::Domain::CredentialKind::EnvFile,
|
|
name: "n", tags: {} of String => String,
|
|
)
|
|
other = CRE::Domain::Credential.new(
|
|
id: UUID.random, external_id: "y", kind: CRE::Domain::CredentialKind::GithubPat,
|
|
name: "n", tags: {} of String => String,
|
|
)
|
|
|
|
p.matches?(matching).should be_true
|
|
p.matches?(other).should be_false
|
|
end
|
|
|
|
it "detects overdue based on rotation_anchor + max_age" do
|
|
p = CRE::Policy::Policy.new(
|
|
name: "p", description: nil,
|
|
matcher: ->(_c : CRE::Domain::Credential) { true },
|
|
max_age: 7.days, warn_at: nil,
|
|
enforce_action: CRE::Policy::Action::NotifyOnly,
|
|
notify_channels: [] of CRE::Policy::Channel,
|
|
triggers: {} of CRE::Policy::Trigger => CRE::Policy::Action,
|
|
)
|
|
|
|
fresh = CRE::Domain::Credential.new(
|
|
id: UUID.random, external_id: "f",
|
|
kind: CRE::Domain::CredentialKind::EnvFile,
|
|
name: "n", tags: {} of String => String,
|
|
last_rotated_at: Time.utc - 1.day,
|
|
)
|
|
stale = CRE::Domain::Credential.new(
|
|
id: UUID.random, external_id: "s",
|
|
kind: CRE::Domain::CredentialKind::EnvFile,
|
|
name: "n", tags: {} of String => String,
|
|
last_rotated_at: Time.utc - 30.days,
|
|
)
|
|
|
|
p.overdue?(fresh).should be_false
|
|
p.overdue?(stale).should be_true
|
|
end
|
|
|
|
it "treats never-rotated credentials by created_at" do
|
|
p = CRE::Policy::Policy.new(
|
|
name: "p", description: nil,
|
|
matcher: ->(_c : CRE::Domain::Credential) { true },
|
|
max_age: 7.days, warn_at: nil,
|
|
enforce_action: CRE::Policy::Action::NotifyOnly,
|
|
notify_channels: [] of CRE::Policy::Channel,
|
|
triggers: {} of CRE::Policy::Trigger => CRE::Policy::Action,
|
|
)
|
|
|
|
aged = CRE::Domain::Credential.new(
|
|
id: UUID.random, external_id: "a",
|
|
kind: CRE::Domain::CredentialKind::EnvFile,
|
|
name: "n", tags: {} of String => String,
|
|
created_at: Time.utc - 30.days,
|
|
)
|
|
p.overdue?(aged).should be_true
|
|
end
|
|
|
|
it "ignores updated_at (renaming a credential does not reset rotation clock)" do
|
|
p = CRE::Policy::Policy.new(
|
|
name: "p", description: nil,
|
|
matcher: ->(_c : CRE::Domain::Credential) { true },
|
|
max_age: 7.days, warn_at: nil,
|
|
enforce_action: CRE::Policy::Action::NotifyOnly,
|
|
notify_channels: [] of CRE::Policy::Channel,
|
|
triggers: {} of CRE::Policy::Trigger => CRE::Policy::Action,
|
|
)
|
|
|
|
just_renamed = CRE::Domain::Credential.new(
|
|
id: UUID.random, external_id: "x",
|
|
kind: CRE::Domain::CredentialKind::EnvFile,
|
|
name: "n", tags: {} of String => String,
|
|
created_at: Time.utc - 30.days,
|
|
updated_at: Time.utc, # tag/name was just edited
|
|
last_rotated_at: Time.utc - 30.days,
|
|
)
|
|
p.overdue?(just_renamed).should be_true
|
|
end
|
|
|
|
it "computes warning window" do
|
|
p = CRE::Policy::Policy.new(
|
|
name: "p", description: nil,
|
|
matcher: ->(_c : CRE::Domain::Credential) { true },
|
|
max_age: 30.days, warn_at: 25.days,
|
|
enforce_action: CRE::Policy::Action::NotifyOnly,
|
|
notify_channels: [] of CRE::Policy::Channel,
|
|
triggers: {} of CRE::Policy::Trigger => CRE::Policy::Action,
|
|
)
|
|
|
|
young = CRE::Domain::Credential.new(
|
|
id: UUID.random, external_id: "y", kind: CRE::Domain::CredentialKind::EnvFile,
|
|
name: "n", tags: {} of String => String,
|
|
last_rotated_at: Time.utc - 10.days,
|
|
)
|
|
warning = CRE::Domain::Credential.new(
|
|
id: UUID.random, external_id: "w", kind: CRE::Domain::CredentialKind::EnvFile,
|
|
name: "n", tags: {} of String => String,
|
|
last_rotated_at: Time.utc - 27.days,
|
|
)
|
|
overdue = CRE::Domain::Credential.new(
|
|
id: UUID.random, external_id: "o", kind: CRE::Domain::CredentialKind::EnvFile,
|
|
name: "n", tags: {} of String => String,
|
|
last_rotated_at: Time.utc - 31.days,
|
|
)
|
|
|
|
p.in_warning_window?(young).should be_false
|
|
p.in_warning_window?(warning).should be_true
|
|
p.in_warning_window?(overdue).should be_false
|
|
end
|
|
end
|