Skip to content
Open
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
2 changes: 2 additions & 0 deletions internal/module/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,7 @@ func mapTemplatesRules(linterSettings *pkg.LintersSettings, configSettings *conf
rules.EnabledModulesRule.SetLevel(globalRules.EnabledModulesRule.Impact, fallbackImpact)
rules.MountPointsRule.SetLevel(globalRules.MountPointsRule.Impact, fallbackImpact)
rules.WebhookConfigurationRule.SetLevel(globalRules.WebhookConfigurationRule.Impact, fallbackImpact)
rules.CertificateGatewayIssuerRule.SetLevel(globalRules.CertificateGatewayIssuerRule.Impact, fallbackImpact)
}

// mapOpenAPIRules configures OpenAPI linter rules
Expand Down Expand Up @@ -463,6 +464,7 @@ func mapTemplatesExclusionsAndSettings(linterSettings *pkg.LintersSettings, conf
excludes.KubeRBACProxy = pkg.StringRuleExcludeList(configExcludes.KubeRBACProxy)
excludes.Ingress = configExcludes.Ingress.Get()
excludes.HTTPRoute = configExcludes.HTTPRoute.Get()
excludes.CertificateGatewayIssuer = configExcludes.CertificateGatewayIssuer.Get()
excludes.EnabledModules.Files = pkg.StringRuleExcludeList(configExcludes.EnabledModules.Files)
excludes.EnabledModules.Directories = pkg.DirectoryRuleExcludeList(configExcludes.EnabledModules.Directories)
excludes.WebhookConfiguration = configExcludes.WebhookConfiguration.Get()
Expand Down
46 changes: 24 additions & 22 deletions pkg/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,19 +131,20 @@ type TemplatesLinterConfig struct {
GrafanaDashboardsSettings GrafanaDashboardsSettings
}
type TemplatesLinterRules struct {
VPARule RuleConfig
PDBRule RuleConfig
IngressRule RuleConfig
PrometheusRule RuleConfig
GrafanaRule RuleConfig
KubeRBACProxyRule RuleConfig
ServicePortRule RuleConfig
ClusterDomainRule RuleConfig
RegistryRule RuleConfig
HTTPRouteRule RuleConfig
EnabledModulesRule RuleConfig
WebhookConfigurationRule RuleConfig
MountPointsRule RuleConfig
VPARule RuleConfig
PDBRule RuleConfig
IngressRule RuleConfig
PrometheusRule RuleConfig
GrafanaRule RuleConfig
KubeRBACProxyRule RuleConfig
ServicePortRule RuleConfig
ClusterDomainRule RuleConfig
RegistryRule RuleConfig
HTTPRouteRule RuleConfig
EnabledModulesRule RuleConfig
WebhookConfigurationRule RuleConfig
MountPointsRule RuleConfig
CertificateGatewayIssuerRule RuleConfig
}

type PrometheusRuleSettings struct {
Expand All @@ -154,15 +155,16 @@ type GrafanaDashboardsSettings struct {
Disable bool
}
type TemplatesExcludeRules struct {
VPAAbsent KindRuleExcludeList
PDBAbsent KindRuleExcludeList
ServicePort ServicePortExcludeList
KubeRBACProxy StringRuleExcludeList
Ingress KindRuleExcludeList
HTTPRoute KindRuleExcludeList
EnabledModules EnabledModulesExcludeRule
WebhookConfiguration KindRuleExcludeList
MountPoints StringRuleExcludeList
VPAAbsent KindRuleExcludeList
PDBAbsent KindRuleExcludeList
ServicePort ServicePortExcludeList
KubeRBACProxy StringRuleExcludeList
Ingress KindRuleExcludeList
HTTPRoute KindRuleExcludeList
CertificateGatewayIssuer KindRuleExcludeList
EnabledModules EnabledModulesExcludeRule
WebhookConfiguration KindRuleExcludeList
MountPoints StringRuleExcludeList
}

type EnabledModulesExcludeRule struct {
Expand Down
27 changes: 14 additions & 13 deletions pkg/config/global/global.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,19 +130,20 @@ type TemplatesLinterConfig struct {
}

type TemplatesLinterRules struct {
VPARule RuleConfig `mapstructure:"vpa"`
PDBRule RuleConfig `mapstructure:"pdb"`
IngressRule RuleConfig `mapstructure:"ingress"`
HTTPRouteRule RuleConfig `mapstructure:"httproute"`
PrometheusRule RuleConfig `mapstructure:"prometheus-rules"`
GrafanaRule RuleConfig `mapstructure:"grafana-dashboards"`
KubeRBACProxyRule RuleConfig `mapstructure:"kube-rbac-proxy"`
ServicePortRule RuleConfig `mapstructure:"service-port"`
ClusterDomainRule RuleConfig `mapstructure:"cluster-domain"`
RegistryRule RuleConfig `mapstructure:"registry"`
EnabledModulesRule RuleConfig `mapstructure:"enabled-modules"`
WebhookConfigurationRule RuleConfig `mapstructure:"webhook-configuration-annotations"`
MountPointsRule RuleConfig `mapstructure:"mount-points"`
VPARule RuleConfig `mapstructure:"vpa"`
PDBRule RuleConfig `mapstructure:"pdb"`
IngressRule RuleConfig `mapstructure:"ingress"`
HTTPRouteRule RuleConfig `mapstructure:"httproute"`
PrometheusRule RuleConfig `mapstructure:"prometheus-rules"`
GrafanaRule RuleConfig `mapstructure:"grafana-dashboards"`
KubeRBACProxyRule RuleConfig `mapstructure:"kube-rbac-proxy"`
ServicePortRule RuleConfig `mapstructure:"service-port"`
ClusterDomainRule RuleConfig `mapstructure:"cluster-domain"`
RegistryRule RuleConfig `mapstructure:"registry"`
EnabledModulesRule RuleConfig `mapstructure:"enabled-modules"`
WebhookConfigurationRule RuleConfig `mapstructure:"webhook-configuration-annotations"`
MountPointsRule RuleConfig `mapstructure:"mount-points"`
CertificateGatewayIssuerRule RuleConfig `mapstructure:"certificate-gateway-issuer"`
}

func (c LinterConfig) IsWarn() bool {
Expand Down
46 changes: 24 additions & 22 deletions pkg/config/linters_settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,31 +220,33 @@ type TemplatesSettings struct {
}

type TemplatesLinterRules struct {
VPARule RuleConfig `mapstructure:"vpa"`
PDBRule RuleConfig `mapstructure:"pdb"`
IngressRule RuleConfig `mapstructure:"ingress"`
HTTPRouteRule RuleConfig `mapstructure:"httproute"`
PrometheusRule RuleConfig `mapstructure:"prometheus-rules"`
GrafanaRule RuleConfig `mapstructure:"grafana-dashboards"`
KubeRBACProxyRule RuleConfig `mapstructure:"kube-rbac-proxy"`
ServicePortRule RuleConfig `mapstructure:"service-port"`
ClusterDomainRule RuleConfig `mapstructure:"cluster-domain"`
RegistryRule RuleConfig `mapstructure:"registry"`
EnabledModulesRule RuleConfig `mapstructure:"enabled-modules"`
WebhookConfigurationRule RuleConfig `mapstructure:"webhook-configuration-annotations"`
MountPointsRule RuleConfig `mapstructure:"mount-points"`
VPARule RuleConfig `mapstructure:"vpa"`
PDBRule RuleConfig `mapstructure:"pdb"`
IngressRule RuleConfig `mapstructure:"ingress"`
HTTPRouteRule RuleConfig `mapstructure:"httproute"`
PrometheusRule RuleConfig `mapstructure:"prometheus-rules"`
GrafanaRule RuleConfig `mapstructure:"grafana-dashboards"`
KubeRBACProxyRule RuleConfig `mapstructure:"kube-rbac-proxy"`
ServicePortRule RuleConfig `mapstructure:"service-port"`
ClusterDomainRule RuleConfig `mapstructure:"cluster-domain"`
RegistryRule RuleConfig `mapstructure:"registry"`
EnabledModulesRule RuleConfig `mapstructure:"enabled-modules"`
WebhookConfigurationRule RuleConfig `mapstructure:"webhook-configuration-annotations"`
MountPointsRule RuleConfig `mapstructure:"mount-points"`
CertificateGatewayIssuerRule RuleConfig `mapstructure:"certificate-gateway-issuer"`
}

type TemplatesExcludeRules struct {
VPAAbsent KindRuleExcludeList `mapstructure:"vpa"`
PDBAbsent KindRuleExcludeList `mapstructure:"pdb"`
ServicePort ServicePortExcludeList `mapstructure:"service-port"`
KubeRBACProxy StringRuleExcludeList `mapstructure:"kube-rbac-proxy"`
Ingress KindRuleExcludeList `mapstructure:"ingress"`
HTTPRoute KindRuleExcludeList `mapstructure:"httproute"`
EnabledModules EnabledModulesExcludeRule `mapstructure:"enabled-modules"`
WebhookConfiguration KindRuleExcludeList `mapstructure:"webhook-configuration-annotations"`
MountPoints StringRuleExcludeList `mapstructure:"mount-points"`
VPAAbsent KindRuleExcludeList `mapstructure:"vpa"`
PDBAbsent KindRuleExcludeList `mapstructure:"pdb"`
ServicePort ServicePortExcludeList `mapstructure:"service-port"`
KubeRBACProxy StringRuleExcludeList `mapstructure:"kube-rbac-proxy"`
Ingress KindRuleExcludeList `mapstructure:"ingress"`
HTTPRoute KindRuleExcludeList `mapstructure:"httproute"`
CertificateGatewayIssuer KindRuleExcludeList `mapstructure:"certificate-gateway-issuer"`
EnabledModules EnabledModulesExcludeRule `mapstructure:"enabled-modules"`
WebhookConfiguration KindRuleExcludeList `mapstructure:"webhook-configuration-annotations"`
MountPoints StringRuleExcludeList `mapstructure:"mount-points"`
}

type EnabledModulesExcludeRule struct {
Expand Down
86 changes: 86 additions & 0 deletions pkg/linters/templates/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ Proper template validation prevents runtime issues, ensures applications are pro
| [enabled-modules](#enabled-modules) | Detects usage of `.Values.global.enabledModules` in templates | ✅ | enabled |
| [webhook-configuration-annotations](#webhook-configuration-annotations) | Checks webhook configurations have werf.io/weight or deploy-dependency annotations | ✅ | enabled |
| [mount-points](#mount-points) | Validates that mount-points.yaml directories are used as volumeMounts in pod controllers | ✅ | enabled |
| [certificate-gateway-issuer](#certificate-gateway-issuer) | Validates Gateway API Certificates use the helm_lib ClusterIssuer helper | ✅ | enabled |

"Configurable" means that this rule can be configured using the `.dmtlint.yaml` file, including customizing the rule's parameters and/or disabling the rule.

Expand Down Expand Up @@ -2033,8 +2034,77 @@ linters-settings:
**When to exclude:** Pods managed outside Helm (operators, mutating webhooks, static pods, bashible) have `volumeMounts` that are not present in Helm templates. Directories from `mount-points.yaml` for these containers will produce false positives — exclude them with the corresponding paths.
```

---

### certificate-gateway-issuer

**Purpose:** Ensures Certificate objects used with Gateway API reference the ClusterIssuer through the shared helm_lib helper instead of hardcoding `printf "letsencrypt-gateway-%s"`.

**Description:**

Scans Helm template files for `kind: Certificate` resources whose `spec.issuerRef.name` is set with `{{ printf "letsencrypt-gateway-%s" ... }}` and requires the recommended include helper instead.

**What it checks:**

1. Template files under `templates/` (`.yaml`, `.yml`, `.tpl`, `.tpl.yaml`, `.tpl.yml`)
2. Presence of `kind: Certificate`
3. `issuerRef.name` using `printf "letsencrypt-gateway-%s"` (or single-quoted equivalent)

**Why it matters:**

Hardcoded Gateway issuer names:
- Bypass the shared helm_lib naming convention for Gateway API ClusterIssuers
- Drift when issuer naming changes across Deckhouse releases
- Make Certificate templates harder to review and maintain

**Examples:**

❌ **Incorrect** - Hardcoded printf issuer name:

```yaml
# templates/certificate.yaml
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: gateway-cert
spec:
issuerRef:
name: {{ printf "letsencrypt-gateway-%s" $moduleGateway.name }}
kind: ClusterIssuer
```

**Error:**
```
Certificates related to Gateway API must refer to issuer using {{ include "helm_lib_module_https_cert_manager_cluster_issuer_name_for_gateway_api" . }}
```

✅ **Correct** - Use the helm_lib helper:

```yaml
# templates/certificate.yaml
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: gateway-cert
spec:
issuerRef:
name: {{ include "helm_lib_module_https_cert_manager_cluster_issuer_name_for_gateway_api" . }}
kind: ClusterIssuer
```

**Configuration:**

```yaml
# .dmtlint.yaml
linters-settings:
templates:
exclude-rules:
certificate-gateway-issuer:
- kind: Certificate
name: gateway-cert
```

---

## Configuration

Expand All @@ -2057,6 +2127,11 @@ linters-settings:

prometheus-rules:
disable: true

exclude-rules:
certificate-gateway-issuer:
- kind: Certificate
name: gateway-cert
```

### Per-Rule Impact Levels
Expand Down Expand Up @@ -2092,6 +2167,8 @@ linters-settings:
impact: warning
webhook-configuration-annotations:
impact: error
certificate-gateway-issuer:
impact: warning
```

### Rule-Level Exclusions
Expand Down Expand Up @@ -2131,6 +2208,11 @@ linters-settings:
- kind: Ingress
name: internal-only

# Certificate Gateway issuer exclusions (by kind and name)
certificate-gateway-issuer:
- kind: Certificate
name: legacy-gateway-cert

# Service port exclusions (by service name and port name)
service-port:
- name: d8-control-plane-apiserver
Expand Down Expand Up @@ -2194,6 +2276,10 @@ linters-settings:
ingress:
- kind: Ingress
name: internal-dashboard

certificate-gateway-issuer:
- kind: Certificate
name: internal-dashboard-cert

service-port:
- name: apiserver
Expand Down
Loading
Loading