Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

updated AKS monitoring rule and added system and user node pool min count rules #243

Merged
merged 1 commit into from
May 27, 2024
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
73 changes: 70 additions & 3 deletions internal/scanners/aks/rules.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,12 +169,13 @@ func (a *AKSScanner) GetRules() map[string]scanners.AzureRule {
"aks-011": {
Id: "aks-011",
Category: scanners.RulesCategoryMonitoringAndAlerting,
Recommendation: "AKS should have Container Insights enabled",
Recommendation: "AKS should have Monitoring enabled",
Impact: scanners.ImpactHigh,
Eval: func(target interface{}, scanContext *scanners.ScanContext) (bool, string) {
c := target.(*armcontainerservice.ManagedCluster)
p, exists := c.Properties.AddonProfiles["omsagent"]
broken := !exists || !*p.Enabled
m := c.Properties.AzureMonitorProfile != nil && c.Properties.AzureMonitorProfile.Metrics != nil && c.Properties.AzureMonitorProfile.Metrics.Enabled != nil && *c.Properties.AzureMonitorProfile.Metrics.Enabled
i, exists := c.Properties.AddonProfiles["omsagent"]
broken := !exists || !*i.Enabled || !m
return broken, ""
},
Url: "https://learn.microsoft.com/azure/azure-monitor/insights/container-insights-overview",
Expand Down Expand Up @@ -252,5 +253,71 @@ func (a *AKSScanner) GetRules() map[string]scanners.AzureRule {
},
Url: "https://learn.microsoft.com/en-us/azure/aks/operator-best-practices-run-at-scale#cluster-upgrade-considerations-and-best-practices",
},
"aks-017": {
Id: "aks-017",
Category: scanners.RulesCategoryOtherBestPractices,
Recommendation: "AKS: Enable GitOps when using DevOps frameworks",
Impact: scanners.ImpactLow,
Eval: func(target interface{}, scanContext *scanners.ScanContext) (bool, string) {
c := target.(*armcontainerservice.ManagedCluster)
g, exists := c.Properties.AddonProfiles["gitops"]
broken := !exists || !*g.Enabled
return broken, ""
},
Url: "https://learn.microsoft.com/en-us/azure/architecture/guide/aks/aks-cicd-github-actions-and-gitops",
},
"aks-018": {
Id: "aks-018",
Category: scanners.RulesCategoryHighAvailability,
Recommendation: "AKS: Configure system nodepool count",
Impact: scanners.ImpactHigh,
Eval: func(target interface{}, scanContext *scanners.ScanContext) (bool, string) {
c := target.(*armcontainerservice.ManagedCluster)
for _, profile := range c.Properties.AgentPoolProfiles {
if profile.Mode != nil && *profile.Mode == armcontainerservice.AgentPoolModeSystem && (profile.MinCount == nil || *profile.MinCount < 2) {
return true, ""
}
}
return false, ""
},
Url: "https://learn.microsoft.com/azure/aks/use-system-pools?tabs=azure-cli",
},
"aks-019": {
Id: "aks-019",
Category: scanners.RulesCategoryHighAvailability,
Recommendation: "AKS: Configure user nodepool count",
Impact: scanners.ImpactHigh,
Eval: func(target interface{}, scanContext *scanners.ScanContext) (bool, string) {
c := target.(*armcontainerservice.ManagedCluster)
for _, profile := range c.Properties.AgentPoolProfiles {
if profile.Mode != nil && *profile.Mode == armcontainerservice.AgentPoolModeUser && (profile.MinCount == nil || *profile.MinCount < 2) {
return true, ""
}
}
return false, ""
},
Url: "https://learn.microsoft.com/azure/well-architected/service-guides/azure-kubernetes-service#design-checklist",
},
"aks-020": {
Id: "aks-020",
Category: scanners.RulesCategoryHighAvailability,
Recommendation: "AKS: system node pool should have taint: CriticalAddonsOnly=true:NoSchedule",
Impact: scanners.ImpactHigh,
Eval: func(target interface{}, scanContext *scanners.ScanContext) (bool, string) {
c := target.(*armcontainerservice.ManagedCluster)
for _, profile := range c.Properties.AgentPoolProfiles {
if profile.Mode != nil && *profile.Mode == armcontainerservice.AgentPoolModeSystem {
for _, taint := range profile.NodeTaints {
if strings.Contains(*taint, "CriticalAddonsOnly=true:NoSchedule") {
return false, ""
}
}
break
}
}
return true, ""
},
Url: "https://learn.microsoft.com/en-us/azure/aks/use-system-pools?tabs=azure-cli#system-and-user-node-pools",
},
}
}
185 changes: 183 additions & 2 deletions internal/scanners/aks/rules_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -327,11 +327,16 @@ func TestAKSScanner_Rules(t *testing.T) {
},
},
{
name: "AKSScanner omsAgent enabled",
name: "AKSScanner Monitoring enabled",
fields: fields{
rule: "aks-011",
target: &armcontainerservice.ManagedCluster{
Properties: &armcontainerservice.ManagedClusterProperties{
AzureMonitorProfile: &armcontainerservice.ManagedClusterAzureMonitorProfile{
Metrics: &armcontainerservice.ManagedClusterAzureMonitorProfileMetrics{
Enabled: to.Ptr(true),
},
},
AddonProfiles: map[string]*armcontainerservice.ManagedClusterAddonProfile{
"omsagent": {
Enabled: to.Ptr(true),
Expand All @@ -347,7 +352,7 @@ func TestAKSScanner_Rules(t *testing.T) {
},
},
{
name: "AKSScanner omsAgent disabled",
name: "AKSScanner Monitoring disabled",
fields: fields{
rule: "aks-011",
target: &armcontainerservice.ManagedCluster{
Expand Down Expand Up @@ -584,6 +589,182 @@ func TestAKSScanner_Rules(t *testing.T) {
result: "",
},
},
{
name: "AKSScanner GitOps disabled",
fields: fields{
rule: "aks-017",
target: &armcontainerservice.ManagedCluster{
Properties: &armcontainerservice.ManagedClusterProperties{
AddonProfiles: map[string]*armcontainerservice.ManagedClusterAddonProfile{
"gitops": {
Enabled: to.Ptr(false),
},
},
},
},
scanContext: &scanners.ScanContext{},
},
want: want{
broken: true,
result: "",
},
},
{
name: "AKSScanner GitOps enabled",
fields: fields{
rule: "aks-017",
target: &armcontainerservice.ManagedCluster{
Properties: &armcontainerservice.ManagedClusterProperties{
AddonProfiles: map[string]*armcontainerservice.ManagedClusterAddonProfile{
"gitops": {
Enabled: to.Ptr(true),
},
},
},
},
scanContext: &scanners.ScanContext{},
},
want: want{
broken: false,
result: "",
},
},
{
name: "AKSScanner Configure system nodepool count < 2",
fields: fields{
rule: "aks-018",
target: &armcontainerservice.ManagedCluster{
Properties: &armcontainerservice.ManagedClusterProperties{
AgentPoolProfiles: []*armcontainerservice.ManagedClusterAgentPoolProfile{
{
Mode: to.Ptr(armcontainerservice.AgentPoolModeSystem),
MinCount: to.Ptr(int32(1)),
},
},
},
},
scanContext: &scanners.ScanContext{},
},
want: want{
broken: true,
result: "",
},
},
{
name: "AKSScanner Configure system nodepool count == 2",
fields: fields{
rule: "aks-018",
target: &armcontainerservice.ManagedCluster{
Properties: &armcontainerservice.ManagedClusterProperties{
AgentPoolProfiles: []*armcontainerservice.ManagedClusterAgentPoolProfile{
{
Mode: to.Ptr(armcontainerservice.AgentPoolModeSystem),
MinCount: to.Ptr(int32(2)),
},
},
},
},
scanContext: &scanners.ScanContext{},
},
want: want{
broken: false,
result: "",
},
},
{
name: "AKSScanner Configure user node pool count < 2",
fields: fields{
rule: "aks-019",
target: &armcontainerservice.ManagedCluster{
Properties: &armcontainerservice.ManagedClusterProperties{
AgentPoolProfiles: []*armcontainerservice.ManagedClusterAgentPoolProfile{
{
Mode: to.Ptr(armcontainerservice.AgentPoolModeSystem),
MinCount: to.Ptr(int32(2)),
},
{
Mode: to.Ptr(armcontainerservice.AgentPoolModeUser),
MinCount: to.Ptr(int32(1)),
},
},
},
},
scanContext: &scanners.ScanContext{},
},
want: want{
broken: true,
result: "",
},
},
{
name: "AKSScanner Configure user node pool count == 2",
fields: fields{
rule: "aks-019",
target: &armcontainerservice.ManagedCluster{
Properties: &armcontainerservice.ManagedClusterProperties{
AgentPoolProfiles: []*armcontainerservice.ManagedClusterAgentPoolProfile{
{
Mode: to.Ptr(armcontainerservice.AgentPoolModeSystem),
MinCount: to.Ptr(int32(2)),
},
{
Mode: to.Ptr(armcontainerservice.AgentPoolModeUser),
MinCount: to.Ptr(int32(2)),
},
},
},
},
scanContext: &scanners.ScanContext{},
},
want: want{
broken: false,
result: "",
},
},
{
name: "AKSScanner system node pool tainted",
fields: fields{
rule: "aks-020",
target: &armcontainerservice.ManagedCluster{
Properties: &armcontainerservice.ManagedClusterProperties{
AgentPoolProfiles: []*armcontainerservice.ManagedClusterAgentPoolProfile{
{
Mode: to.Ptr(armcontainerservice.AgentPoolModeSystem),
NodeTaints: []*string{
to.Ptr("CriticalAddonsOnly=true:NoSchedule"),
},
},
},
},
},
scanContext: &scanners.ScanContext{},
},
want: want{
broken: false,
result: "",
},
},
{
name: "AKSScanner system node pool not tainted",
fields: fields{
rule: "aks-020",
target: &armcontainerservice.ManagedCluster{
Properties: &armcontainerservice.ManagedClusterProperties{
AgentPoolProfiles: []*armcontainerservice.ManagedClusterAgentPoolProfile{
{
Mode: to.Ptr(armcontainerservice.AgentPoolModeSystem),
NodeTaints: []*string{},
},
},
},
},
scanContext: &scanners.ScanContext{},
},
want: want{
broken: true,
result: "",
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand Down
1 change: 1 addition & 0 deletions internal/scanners/scanner.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,4 +214,5 @@ const (
RulesCategoryDisasterRecovery RulesCategory = "Disaster Recovery"
RulesCategorySecurity RulesCategory = "Security"
RulesCategoryGovernance RulesCategory = "Governance"
RulesCategoryOtherBestPractices RulesCategory = "Other Best Practices"
)
Loading