in internal/scanners/aks/rules.go [15:174]
func (a *AKSScanner) GetRecommendations() map[string]models.AzqrRecommendation {
return map[string]models.AzqrRecommendation{
"aks-001": {
RecommendationID: "aks-001",
ResourceType: "Microsoft.ContainerService/managedClusters",
Category: models.CategoryMonitoringAndAlerting,
Recommendation: "AKS Cluster should have diagnostic settings enabled",
Impact: models.ImpactLow,
Eval: func(target interface{}, scanContext *models.ScanContext) (bool, string) {
service := target.(*armcontainerservice.ManagedCluster)
_, ok := scanContext.DiagnosticsSettings[strings.ToLower(*service.ID)]
return !ok, ""
},
LearnMoreUrl: "https://learn.microsoft.com/en-us/azure/aks/monitor-aks#collect-resource-logs",
},
"aks-003": {
RecommendationID: "aks-003",
ResourceType: "Microsoft.ContainerService/managedClusters",
Category: models.CategoryHighAvailability,
Recommendation: "AKS Cluster should have an SLA",
RecommendationType: models.TypeSLA,
Impact: models.ImpactHigh,
Eval: func(target interface{}, scanContext *models.ScanContext) (bool, string) {
c := target.(*armcontainerservice.ManagedCluster)
zones := true
for _, profile := range c.Properties.AgentPoolProfiles {
if profile.AvailabilityZones == nil || (profile.AvailabilityZones != nil && len(profile.AvailabilityZones) <= 1) {
zones = false
break
}
}
sku := "Free"
if c.SKU != nil && c.SKU.Tier != nil {
sku = string(*c.SKU.Tier)
}
sla := "None"
if !strings.Contains(sku, "Free") {
sla = "99.9%"
if zones {
sla = "99.95%"
}
}
return sla == "None", sla
},
LearnMoreUrl: "https://learn.microsoft.com/en-us/azure/aks/free-standard-pricing-tiers#uptime-sla-terms-and-conditions",
},
"aks-004": {
RecommendationID: "aks-004",
ResourceType: "Microsoft.ContainerService/managedClusters",
Category: models.CategorySecurity,
Recommendation: "AKS Cluster should be private",
Impact: models.ImpactHigh,
Eval: func(target interface{}, scanContext *models.ScanContext) (bool, string) {
c := target.(*armcontainerservice.ManagedCluster)
pe := c.Properties.APIServerAccessProfile != nil && c.Properties.APIServerAccessProfile.EnablePrivateCluster != nil && *c.Properties.APIServerAccessProfile.EnablePrivateCluster
return !pe, ""
},
LearnMoreUrl: "https://learn.microsoft.com/en-us/azure/aks/private-clusters",
},
"aks-006": {
RecommendationID: "aks-006",
ResourceType: "Microsoft.ContainerService/managedClusters",
Category: models.CategoryGovernance,
Recommendation: "AKS Name should comply with naming conventions",
Impact: models.ImpactLow,
Eval: func(target interface{}, scanContext *models.ScanContext) (bool, string) {
c := target.(*armcontainerservice.ManagedCluster)
caf := strings.HasPrefix(*c.Name, "aks")
return !caf, ""
},
LearnMoreUrl: "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/azure-best-practices/resource-abbreviations",
},
"aks-007": {
RecommendationID: "aks-007",
ResourceType: "Microsoft.ContainerService/managedClusters",
Category: models.CategorySecurity,
Recommendation: "AKS should integrate authentication with AAD (Managed)",
Impact: models.ImpactMedium,
Eval: func(target interface{}, scanContext *models.ScanContext) (bool, string) {
c := target.(*armcontainerservice.ManagedCluster)
aad := c.Properties.AADProfile != nil && c.Properties.AADProfile.Managed != nil && *c.Properties.AADProfile.Managed
return !aad, ""
},
LearnMoreUrl: "https://learn.microsoft.com/en-us/azure/aks/managed-azure-ad",
},
"aks-008": {
RecommendationID: "aks-008",
ResourceType: "Microsoft.ContainerService/managedClusters",
Category: models.CategorySecurity,
Recommendation: "AKS should be RBAC enabled.",
Impact: models.ImpactMedium,
Eval: func(target interface{}, scanContext *models.ScanContext) (bool, string) {
c := target.(*armcontainerservice.ManagedCluster)
rbac := *c.Properties.EnableRBAC
return !rbac, ""
},
LearnMoreUrl: "https://learn.microsoft.com/azure/aks/manage-azure-rbac",
},
"aks-010": {
RecommendationID: "aks-010",
ResourceType: "Microsoft.ContainerService/managedClusters",
Category: models.CategorySecurity,
Recommendation: "AKS should have httpApplicationRouting disabled",
Impact: models.ImpactMedium,
Eval: func(target interface{}, scanContext *models.ScanContext) (bool, string) {
c := target.(*armcontainerservice.ManagedCluster)
p, exists := c.Properties.AddonProfiles["httpApplicationRouting"]
broken := exists && *p.Enabled
return broken, ""
},
LearnMoreUrl: "https://learn.microsoft.com/azure/aks/http-application-routing",
},
"aks-012": {
RecommendationID: "aks-012",
ResourceType: "Microsoft.ContainerService/managedClusters",
Category: models.CategorySecurity,
Recommendation: "AKS should have outbound type set to user defined routing",
Impact: models.ImpactHigh,
Eval: func(target interface{}, scanContext *models.ScanContext) (bool, string) {
c := target.(*armcontainerservice.ManagedCluster)
broken := c.Properties.NetworkProfile.OutboundType == nil || *c.Properties.NetworkProfile.OutboundType != armcontainerservice.OutboundTypeUserDefinedRouting
return broken, ""
},
LearnMoreUrl: "https://learn.microsoft.com/azure/aks/limit-egress-traffic",
},
"aks-015": {
RecommendationID: "aks-015",
ResourceType: "Microsoft.ContainerService/managedClusters",
Category: models.CategoryGovernance,
Recommendation: "AKS should have tags",
Impact: models.ImpactLow,
Eval: func(target interface{}, scanContext *models.ScanContext) (bool, string) {
c := target.(*armcontainerservice.ManagedCluster)
return len(c.Tags) == 0, ""
},
LearnMoreUrl: "https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/tag-resources?tabs=json",
},
"aks-016": {
RecommendationID: "aks-016",
ResourceType: "Microsoft.ContainerService/managedClusters",
Category: models.CategoryScalability,
Recommendation: "AKS Node Pools should have MaxSurge set",
Impact: models.ImpactLow,
Eval: func(target interface{}, scanContext *models.ScanContext) (bool, string) {
c := target.(*armcontainerservice.ManagedCluster)
defaultMaxSurge := false
for _, profile := range c.Properties.AgentPoolProfiles {
if profile.UpgradeSettings == nil || profile.UpgradeSettings.MaxSurge == nil || (profile.UpgradeSettings.MaxSurge == to.Ptr("1")) {
defaultMaxSurge = true
break
}
}
return defaultMaxSurge, ""
},
LearnMoreUrl: "https://learn.microsoft.com/en-us/azure/aks/operator-best-practices-run-at-scale#cluster-upgrade-considerations-and-best-practices",
},
}
}