Skip to content

Commit

Permalink
azurerm_key_vault_certificate_lifetime_action
Browse files Browse the repository at this point in the history
  • Loading branch information
pregress committed Nov 17, 2024
1 parent 841e914 commit 6ab1216
Show file tree
Hide file tree
Showing 5 changed files with 392 additions and 0 deletions.
5 changes: 5 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
|[azurerm_eventhub_namespace_public_network_access_enabled](./rules/azurerm_eventhub_namespace_public_network_access_enabled.md)|Notice||
|[azurerm_eventhub_namespace_unsecure_tls](./rules/azurerm_eventhub_namespace_unsecure_tls.md)|Warning||
|[azurerm_iothub_endpoint_eventhub_authentication_type](./rules/azurerm_iothub_endpoint_eventhub_authentication_type.md)|Notice||
|[azurerm_key_vault_certificate_lifetime_action](./rules/azurerm_key_vault_certificate_lifetime_action.md)|Warning||
|[azurerm_key_vault_enable_rbac_authorization](./rules/azurerm_key_vault_enable_rbac_authorization.md)|Warning||
|[azurerm_key_vault_network_acls_default_deny](./rules/azurerm_key_vault_network_acls_default_deny.md)|Warning||
|[azurerm_key_vault_public_network_access_enabled](./rules/azurerm_key_vault_public_network_access_enabled.md)|Notice||
Expand Down Expand Up @@ -60,6 +61,10 @@
- [azurerm_key_vault_network_acls_default_deny](./rules/azurerm_key_vault_network_acls_default_deny.md)
- [azurerm_key_vault_public_network_access_enabled](./rules/azurerm_key_vault_public_network_access_enabled.md)

### azurerm_key_vault_certificate

- [azurerm_key_vault_certificate_lifetime_action](./rules/azurerm_key_vault_certificate_lifetime_action.md)

### azurerm_linux_function_app

- [azurerm_linux_function_app_ftps_state](./rules/azurerm_linux_function_app_ftps_state.md)
Expand Down
42 changes: 42 additions & 0 deletions docs/rules/azurerm_key_vault_certificate_lifetime_action.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# azurerm_key_vault_certificate_lifetime_action

**Severity:** Warning


## Example

```hcl
resource "azurerm_key_vault_certificate" "example" {
certificate_policy {
# missing lifetime_policy
}
}
```

## Why

Setting lifetime_action to AutoRenew or EmailContacts ensures proactive management of certificate expiration, reducing the risk of service interruptions or security vulnerabilities caused by expired certificates.

## How to Fix

```hcl
resource "azurerm_key_vault_certificate" "example" {
certificate_policy {
lifetime_action {
action {
action_type = "AutoRenew"
}
}
}
}
```


## How to disable

```hcl
rule "azurerm_key_vault_certificate_lifetime_action" {
enabled = false
}
```

1 change: 1 addition & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ func createRuleSet() *tflint.BuiltinRuleSet {
rules.NewAzurermIoTHubEndpointEventHubAuthenticationType(),
rules.NewAzurermKeyVaultNetworkACLsDefaultDeny(),
rules.NewAzurermKeyVaultPublicNetworkAccessEnabled(),
rules.NewAzurermKeyVaultCertificateLifetimeAction(),
rules.NewAzurermKeyVaultRbacDisabled(),
rules.NewAzurermLinuxFunctionAppFtpsState(),
rules.NewAzurermLinuxFunctionAppHTTPSOnly(),
Expand Down
151 changes: 151 additions & 0 deletions rules/azurerm_key_vault_certificate_lifetime_action_action_type.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
package rules

import (
"fmt"
"strings"

"github.com/terraform-linters/tflint-plugin-sdk/hclext"
"github.com/terraform-linters/tflint-plugin-sdk/tflint"

"github.com/terraform-linters/tflint-ruleset-azurerm-security/project"
)

// AzurermKeyVaultCertificateLifetimeAction checks that certificate_policy.lifetime_action.action.action_type
// is set to either "AutoRenew" or "EmailContacts"
type AzurermKeyVaultCertificateLifetimeAction struct {
tflint.DefaultRule

resourceType string
attributePath []string
validValues []string
}

// NewAzurermKeyVaultCertificateLifetimeAction returns a new rule instance
func NewAzurermKeyVaultCertificateLifetimeAction() *AzurermKeyVaultCertificateLifetimeAction {
return &AzurermKeyVaultCertificateLifetimeAction{
resourceType: "azurerm_key_vault_certificate",
attributePath: []string{"certificate_policy", "lifetime_action", "action", "action_type"},
validValues: []string{"AutoRenew", "EmailContacts"},
}
}

// Name returns the rule name
func (r *AzurermKeyVaultCertificateLifetimeAction) Name() string {
return "azurerm_key_vault_certificate_lifetime_action"
}

// Enabled returns whether the rule is enabled by default
func (r *AzurermKeyVaultCertificateLifetimeAction) Enabled() bool {
return true
}

// Severity returns the rule severity
func (r *AzurermKeyVaultCertificateLifetimeAction) Severity() tflint.Severity {
return tflint.WARNING
}

// Link returns the rule reference link
func (r *AzurermKeyVaultCertificateLifetimeAction) Link() string {
return project.ReferenceLink(r.Name())
}

// Check verifies that the certificate policy lifetime action is properly configured
func (r *AzurermKeyVaultCertificateLifetimeAction) Check(runner tflint.Runner) error {
resources, err := runner.GetResourceContent(r.resourceType, &hclext.BodySchema{
Blocks: []hclext.BlockSchema{
{
Type: "certificate_policy",
Body: &hclext.BodySchema{
Blocks: []hclext.BlockSchema{
{
Type: "lifetime_action",
Body: &hclext.BodySchema{
Blocks: []hclext.BlockSchema{
{
Type: "action",
Body: &hclext.BodySchema{
Attributes: []hclext.AttributeSchema{
{Name: "action_type"},
},
},
},
},
},
},
},
},
},
},
}, nil)
if err != nil {
return err
}

for _, resource := range resources.Blocks {
certPolicyBlocks := resource.Body.Blocks.OfType("certificate_policy")
if len(certPolicyBlocks) == 0 {
runner.EmitIssue(
r,
"certificate_policy block is missing",
resource.DefRange,
)
continue
}

certPolicy := certPolicyBlocks[0]
lifetimeActionBlocks := certPolicy.Body.Blocks.OfType("lifetime_action")
if len(lifetimeActionBlocks) == 0 {
runner.EmitIssue(
r,
"lifetime_action block is missing in certificate_policy",
certPolicy.DefRange,
)
continue
}

lifetimeAction := lifetimeActionBlocks[0]
actionBlocks := lifetimeAction.Body.Blocks.OfType("action")
if len(actionBlocks) == 0 {
runner.EmitIssue(
r,
"action block is missing in lifetime_action",
lifetimeAction.DefRange,
)
continue
}

action := actionBlocks[0]
attribute, exists := action.Body.Attributes["action_type"]
if !exists {
runner.EmitIssue(
r,
"action_type is missing in action block, should be set to either AutoRenew or EmailContacts",
action.DefRange,
)
continue
}

err := runner.EvaluateExpr(attribute.Expr, func(val string) error {
valid := false
for _, validValue := range r.validValues {
if strings.EqualFold(val, validValue) {
valid = true
break
}
}
if !valid {
runner.EmitIssue(
r,
fmt.Sprintf("action_type is set to %s, should be set to either AutoRenew or EmailContacts", val),
attribute.Expr.Range(),
)
}
return nil
}, nil)
if err != nil {
return err
}
}

return nil
}
Loading

1 comment on commit 6ab1216

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@check-spelling-bot Report

🔴 Please review

See the 📜action log or 📝 job summary for details.

Unrecognized words (39)
acls
amd
azuread
azurerm
CGO
codecov
completly
coverprofile
Disbale
Errorf
eventhub
Fatalf
ftps
golint
gomod
GOPATH
goreleaser
hashicorp
hclext
iothub
keyvault
len
linux
mssql
pem
placeholders
pregress
ruleset
securirty
sigstore
Sprintf
svg
terraform
tflint
THub
tls
workflows
yml
YQQ
To use the spell-check-this repository and accept these unrecognized words as correct, you could run the following commands

... in a clone of the [email protected]:pregress/tflint-ruleset-azurerm-security.git repository
on the feat_more_rules branch (ℹ️ how do I use this?):

curl -s -S -L 'https://raw.githubusercontent.com/check-spelling/check-spelling/main/apply.pl' |
perl - 'https://github.com/pregress/tflint-ruleset-azurerm-security/actions/runs/11881236945/attempts/1'
Available 📚 dictionaries could cover words not in the 📘 dictionary
Dictionary Entries Covers Uniquely
cspell:golang/dict/go.txt 2099 5 1
cspell:node/dict/node.txt 891 4
cspell:php/dict/php.txt 1689 4
cspell:aws/aws.txt 218 3 2
cspell:filetypes/filetypes.txt 264 2 1

Consider adding them (in .github/workflows/spelling.yml) in jobs:/spelling: for uses: check-spelling/check-spelling@main in its with:

      with:
        extra_dictionaries: |
          cspell:golang/dict/go.txt
          cspell:node/dict/node.txt
          cspell:php/dict/php.txt
          cspell:aws/aws.txt
          cspell:filetypes/filetypes.txt

To stop checking additional dictionaries, add (in .github/workflows/spelling.yml) for uses: check-spelling/check-spelling@main in its with:

check_extra_dictionaries: ''
Pattern suggestions ✂️ (5)

You could add these patterns to .github/actions/spelling/patterns.txt:

# Automatically suggested patterns

# hit-count: 6 file-count: 3
# https/http/file urls
(?:\b(?:https?|ftp|file)://)[-A-Za-z0-9+&@#/*%?=~_|!:,.;]+[-A-Za-z0-9+&@#/*%=~_|]

# hit-count: 5 file-count: 3
# base64 encoded content, possibly wrapped in mime
(?:^|[\s=;:?])[-a-zA-Z=;:/0-9+]{50,}(?:[\s=;:?]|$)

# hit-count: 3 file-count: 2
# GitHub SHAs (markdown)
(?:\[`?[0-9a-f]+`?\]\(https:/|)/(?:www\.|)github\.com(?:/[^/\s"]+){2,}(?:/[^/\s")]+)(?:[0-9a-f]+(?:[-0-9a-zA-Z/#.]*|)\b|)

# hit-count: 3 file-count: 2
# GitHub actions
\buses:\s+[-\w.]+/[-\w./]+@[-\w.]+

# hit-count: 1 file-count: 1
# go install
go install(?:\s+[a-z]+\.[-@\w/.]+)+

Errors (2)

See the 📜action log or 📝 job summary for details.

❌ Errors Count
ℹ️ candidate-pattern 11
❌ check-file-path 258

See ❌ Event descriptions for more information.

Please sign in to comment.