Skip to content

Release/v2.5.0#361

Merged
misraved merged 4 commits intomainfrom
release/v2.5.0
Feb 3, 2026
Merged

Release/v2.5.0#361
misraved merged 4 commits intomainfrom
release/v2.5.0

Conversation

@misraved
Copy link
Contributor

@misraved misraved commented Feb 2, 2026

Checklist

  • Issue(s) linked

misraved and others added 2 commits February 2, 2026 18:02
… coalesce to handle NULL values correctly (#355) (#360)

Co-authored-by: Jakub 'King' Kubiak <king@browarnicki.pl>
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR (Release/v2.5.0) implements three new automated compliance controls for Azure CIS v5.0.0, replacing previously manual checks, and includes a bug fix for file share soft delete validation.

Changes:

  • Added automated query implementations for CIS v5.0.0 controls: storage account access key rotation (9.3.1.2), diagnostic settings for subscription activity logs (6.1.1.1), and user MFA enforcement (5.1.2)
  • Fixed NULL handling in storage account file share soft delete validation query
  • Updated Azure plugin minimum version requirement from 1.11.0 to 1.12.0

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
mod.pp Updated Azure plugin minimum version to 1.12.0
regulatory_compliance/storage.pp Added storage account access keys periodic regeneration control and query; fixed NULL handling in file share soft delete query
regulatory_compliance/monitor.pp Added diagnostic settings for subscription control and query
regulatory_compliance/activedirectory.pp Added user MFA enabled control and query
cis_v500/section_9.pp Updated control 9.3.1.2 to use new automated storage account keys query
cis_v500/section_6.pp Updated control 6.1.1.1 to use new automated diagnostic settings query
cis_v500/section_5.pp Updated control 5.1.2 to use new automated MFA query
all_controls/storage.pp Added new storage account access keys control to benchmark
all_controls/monitor.pp Added new diagnostic settings control to benchmark; reordered controls alphabetically
all_controls/activedirectory.pp Added new user MFA control to benchmark; removed trailing comma

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 1269 to 1284
azure_storage_account as sa,
jsonb_array_elements(sa.access_keys) as key
)
select
saks.id as resource,
case
when saks.days_since_rotation > 90 then 'alarm'
else 'ok'
end as status,
format(
'Access key %s for storage account %s was last rotated %s days ago (on %s).',
key_name,
storage_account_name,
floor(days_since_rotation)::int,
last_rotated
) as reason
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

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

The query uses jsonb_array_elements(sa.access_keys) which will exclude storage accounts where access_keys is null or an empty array from the results. This means storage accounts without accessible keys won't be reported at all. Consider handling this case explicitly - either by checking for null/empty arrays first or by using a LEFT JOIN approach similar to the storage_account_uses_private_link query (line 440-478) which handles null arrays. Storage accounts without access keys should likely be reported with a different status (e.g., 'skip' or specific message).

Suggested change
azure_storage_account as sa,
jsonb_array_elements(sa.access_keys) as key
)
select
saks.id as resource,
case
when saks.days_since_rotation > 90 then 'alarm'
else 'ok'
end as status,
format(
'Access key %s for storage account %s was last rotated %s days ago (on %s).',
key_name,
storage_account_name,
floor(days_since_rotation)::int,
last_rotated
) as reason
azure_storage_account as sa
left join lateral jsonb_array_elements(sa.access_keys) as key on true
)
select
saks.id as resource,
case
when saks.key_name is null then 'skip'
when saks.days_since_rotation > 90 then 'alarm'
else 'ok'
end as status,
case
when saks.key_name is null then format(
'Storage account %s has no access keys available.',
saks.storage_account_name
)
else format(
'Access key %s for storage account %s was last rotated %s days ago (on %s).',
saks.key_name,
saks.storage_account_name,
floor(saks.days_since_rotation)::int,
saks.last_rotated
)
end as reason

Copilot uses AI. Check for mistakes.
Comment on lines 1278 to 1286
format(
'Access key %s for storage account %s was last rotated %s days ago (on %s).',
key_name,
storage_account_name,
floor(days_since_rotation)::int,
last_rotated
) as reason
${replace(local.common_dimensions_qualifier_sql, "__QUALIFIER__", "saks.")}
${replace(local.common_dimensions_qualifier_subscription_sql, "__QUALIFIER__", "sub.")}
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

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

The query is missing the tag_dimensions_qualifier_sql dimension that is consistently included in other storage account queries in this file. The CTE 'storage_account_key_status' includes the 'tags' field from azure_storage_account, so tag dimensions should be included in the output for consistency with other queries in this file. Compare with queries like 'storage_account_secure_transfer_required_enabled' (line 362) and 'storage_account_key_rotation_reminder_enabled' (line 1229) which include tag dimensions.

Copilot uses AI. Check for mistakes.
@misraved misraved merged commit f0d1a95 into main Feb 3, 2026
3 checks passed
@misraved misraved deleted the release/v2.5.0 branch February 3, 2026 13:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

Comments