mirror of
https://github.com/aquasecurity/trivy.git
synced 2025-12-12 07:40:48 -08:00
feat(misconf): Update SecurityCenter schema (#9674)
Signed-off-by: nikpivkin <nikita.pivkin@smartforce.io> Co-authored-by: nikpivkin <nikita.pivkin@smartforce.io>
This commit is contained in:
@@ -3,6 +3,7 @@ package securitycenter
|
||||
import (
|
||||
"github.com/aquasecurity/trivy/pkg/iac/providers/azure/securitycenter"
|
||||
"github.com/aquasecurity/trivy/pkg/iac/scanners/azure"
|
||||
iacTypes "github.com/aquasecurity/trivy/pkg/iac/types"
|
||||
)
|
||||
|
||||
func Adapt(deployment azure.Deployment) securitycenter.SecurityCenter {
|
||||
@@ -12,7 +13,8 @@ func Adapt(deployment azure.Deployment) securitycenter.SecurityCenter {
|
||||
}
|
||||
}
|
||||
|
||||
func adaptContacts(deployment azure.Deployment) (contacts []securitycenter.Contact) {
|
||||
func adaptContacts(deployment azure.Deployment) []securitycenter.Contact {
|
||||
var contacts []securitycenter.Contact
|
||||
for _, resource := range deployment.GetResourcesByType("Microsoft.Security/securityContacts") {
|
||||
contacts = append(contacts, adaptContact(resource))
|
||||
}
|
||||
@@ -21,16 +23,59 @@ func adaptContacts(deployment azure.Deployment) (contacts []securitycenter.Conta
|
||||
}
|
||||
|
||||
func adaptContact(resource azure.Resource) securitycenter.Contact {
|
||||
alertsToAdminsState := resource.Properties.GetMapValue("notificationsByRole").GetMapValue("state").AsStringValue("", resource.Metadata)
|
||||
isEnabledValue := resource.Properties.GetMapValue("isEnabled").AsBoolValue(false, resource.Metadata)
|
||||
|
||||
enableAlertNotifications, minimalSeverity := extractNotificationSettings(resource, isEnabledValue)
|
||||
|
||||
return securitycenter.Contact{
|
||||
Metadata: resource.Metadata,
|
||||
// TODO: The email field does not exist
|
||||
// https://learn.microsoft.com/en-us/azure/templates/microsoft.security/securitycontacts?pivots=deployment-language-arm-template#securitycontactproperties-1
|
||||
EnableAlertNotifications: resource.Properties.GetMapValue("email").AsBoolValue(false, resource.Metadata),
|
||||
Metadata: resource.Metadata,
|
||||
EnableAlertNotifications: enableAlertNotifications,
|
||||
EnableAlertsToAdmins: iacTypes.Bool(alertsToAdminsState.EqualTo("On"), resource.Metadata),
|
||||
Email: resource.Properties.GetMapValue("emails").AsStringValue("", resource.Metadata),
|
||||
Phone: resource.Properties.GetMapValue("phone").AsStringValue("", resource.Metadata),
|
||||
IsEnabled: isEnabledValue,
|
||||
MinimalSeverity: minimalSeverity,
|
||||
}
|
||||
}
|
||||
|
||||
func adaptSubscriptions(deployment azure.Deployment) (subscriptions []securitycenter.SubscriptionPricing) {
|
||||
func extractNotificationSettings(resource azure.Resource, isEnabled iacTypes.BoolValue) (iacTypes.BoolValue, iacTypes.StringValue) {
|
||||
notificationsSources := resource.Properties.GetMapValue("notificationsSources")
|
||||
if !notificationsSources.IsNull() {
|
||||
return extractFromNotificationsSources(notificationsSources, isEnabled, resource)
|
||||
}
|
||||
|
||||
enableAlertNotifications := resource.Properties.GetMapValue("alertNotifications").AsBoolValue(false, resource.Metadata)
|
||||
minimalSeverity := iacTypes.StringDefault("", resource.Metadata)
|
||||
return enableAlertNotifications, minimalSeverity
|
||||
}
|
||||
|
||||
func extractFromNotificationsSources(notificationsSources azure.Value, isEnabled iacTypes.BoolValue, resource azure.Resource) (iacTypes.BoolValue, iacTypes.StringValue) {
|
||||
minimalSeverity := iacTypes.StringDefault("", resource.Metadata)
|
||||
|
||||
for _, source := range notificationsSources.AsList() {
|
||||
sourceMap := source.AsMap()
|
||||
if sourceMap == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
sourceType, hasSourceType := sourceMap["sourceType"]
|
||||
if !hasSourceType || !sourceType.AsStringValue("", resource.Metadata).EqualTo("Alert") {
|
||||
continue
|
||||
}
|
||||
|
||||
if minimalSeverityVal, hasMinimalSeverity := sourceMap["minimalSeverity"]; hasMinimalSeverity {
|
||||
minimalSeverity = minimalSeverityVal.AsStringValue("", resource.Metadata)
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
enableAlertNotifications := iacTypes.Bool(isEnabled.IsTrue() && !minimalSeverity.IsEmpty(), resource.Metadata)
|
||||
return enableAlertNotifications, minimalSeverity
|
||||
}
|
||||
|
||||
func adaptSubscriptions(deployment azure.Deployment) []securitycenter.SubscriptionPricing {
|
||||
var subscriptions []securitycenter.SubscriptionPricing
|
||||
for _, resource := range deployment.GetResourcesByType("Microsoft.Security/pricings") {
|
||||
subscriptions = append(subscriptions, adaptSubscription(resource))
|
||||
}
|
||||
|
||||
@@ -36,13 +36,18 @@ func TestAdapt(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "complete",
|
||||
name: "complete - legacy format",
|
||||
source: `{
|
||||
"resources": [
|
||||
{
|
||||
"type": "Microsoft.Security/securityContacts",
|
||||
"properties": {
|
||||
"phone": "buz"
|
||||
"emails": "security@example.com",
|
||||
"phone": "buz",
|
||||
"alertNotifications": true,
|
||||
"notificationsByRole": {
|
||||
"state": "On"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -55,13 +60,93 @@ func TestAdapt(t *testing.T) {
|
||||
}`,
|
||||
expected: securitycenter.SecurityCenter{
|
||||
Contacts: []securitycenter.Contact{{
|
||||
Phone: types.StringTest("buz"),
|
||||
Email: types.StringTest("security@example.com"),
|
||||
Phone: types.StringTest("buz"),
|
||||
EnableAlertNotifications: types.BoolTest(true),
|
||||
EnableAlertsToAdmins: types.BoolTest(true),
|
||||
}},
|
||||
Subscriptions: []securitycenter.SubscriptionPricing{{
|
||||
Tier: types.StringTest("Standard"),
|
||||
}},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "complete - new format",
|
||||
source: `{
|
||||
"resources": [
|
||||
{
|
||||
"type": "Microsoft.Security/securityContacts",
|
||||
"properties": {
|
||||
"emails": "security@example.com",
|
||||
"phone": "+1-555-555-5555",
|
||||
"isEnabled": true,
|
||||
"notificationsSources": [
|
||||
{
|
||||
"sourceType": "Alert",
|
||||
"minimalSeverity": "High"
|
||||
}
|
||||
],
|
||||
"notificationsByRole": {
|
||||
"state": "On"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Microsoft.Security/pricings",
|
||||
"properties": {
|
||||
"pricingTier": "Standard"
|
||||
}
|
||||
}
|
||||
]
|
||||
}`,
|
||||
expected: securitycenter.SecurityCenter{
|
||||
Contacts: []securitycenter.Contact{{
|
||||
Email: types.StringTest("security@example.com"),
|
||||
Phone: types.StringTest("+1-555-555-5555"),
|
||||
EnableAlertNotifications: types.BoolTest(true),
|
||||
EnableAlertsToAdmins: types.BoolTest(true),
|
||||
IsEnabled: types.BoolTest(true),
|
||||
MinimalSeverity: types.StringTest("High"),
|
||||
}},
|
||||
Subscriptions: []securitycenter.SubscriptionPricing{{
|
||||
Tier: types.StringTest("Standard"),
|
||||
}},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "new format - disabled",
|
||||
source: `{
|
||||
"resources": [
|
||||
{
|
||||
"type": "Microsoft.Security/securityContacts",
|
||||
"properties": {
|
||||
"emails": "security@example.com",
|
||||
"phone": "+1-555-555-5555",
|
||||
"isEnabled": false,
|
||||
"notificationsSources": [
|
||||
{
|
||||
"sourceType": "Alert",
|
||||
"minimalSeverity": "Medium"
|
||||
}
|
||||
],
|
||||
"notificationsByRole": {
|
||||
"state": "Off"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}`,
|
||||
expected: securitycenter.SecurityCenter{
|
||||
Contacts: []securitycenter.Contact{{
|
||||
Email: types.StringTest("security@example.com"),
|
||||
Phone: types.StringTest("+1-555-555-5555"),
|
||||
EnableAlertNotifications: types.BoolTest(false),
|
||||
EnableAlertsToAdmins: types.BoolTest(false),
|
||||
IsEnabled: types.BoolTest(false),
|
||||
MinimalSeverity: types.StringTest("Medium"),
|
||||
}},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
|
||||
@@ -3,6 +3,7 @@ package securitycenter
|
||||
import (
|
||||
"github.com/aquasecurity/trivy/pkg/iac/providers/azure/securitycenter"
|
||||
"github.com/aquasecurity/trivy/pkg/iac/terraform"
|
||||
iacTypes "github.com/aquasecurity/trivy/pkg/iac/types"
|
||||
)
|
||||
|
||||
func Adapt(modules terraform.Modules) securitycenter.SecurityCenter {
|
||||
@@ -38,13 +39,24 @@ func adaptContact(resource *terraform.Block) securitycenter.Contact {
|
||||
enableAlertNotifAttr := resource.GetAttribute("alert_notifications")
|
||||
enableAlertNotifVal := enableAlertNotifAttr.AsBoolValueOrDefault(false, resource)
|
||||
|
||||
// TODO: add support for the new format https://github.com/hashicorp/terraform-provider-azurerm/issues/30797
|
||||
alertsToAdminsAttr := resource.GetAttribute("alerts_to_admins")
|
||||
alertsToAdminsVal := alertsToAdminsAttr.AsBoolValueOrDefault(false, resource)
|
||||
|
||||
emailAttr := resource.GetAttribute("email")
|
||||
emailVal := emailAttr.AsStringValueOrDefault("", resource)
|
||||
|
||||
phoneAttr := resource.GetAttribute("phone")
|
||||
phoneVal := phoneAttr.AsStringValueOrDefault("", resource)
|
||||
|
||||
return securitycenter.Contact{
|
||||
Metadata: resource.GetMetadata(),
|
||||
EnableAlertNotifications: enableAlertNotifVal,
|
||||
EnableAlertsToAdmins: alertsToAdminsVal,
|
||||
Email: emailVal,
|
||||
Phone: phoneVal,
|
||||
IsEnabled: iacTypes.BoolValue{}, // Not supported in Terraform provider yet
|
||||
MinimalSeverity: iacTypes.StringValue{}, // Not supported in Terraform provider yet
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,14 +22,20 @@ func Test_adaptContact(t *testing.T) {
|
||||
name: "defined",
|
||||
terraform: `
|
||||
resource "azurerm_security_center_contact" "example" {
|
||||
email = "contact@example.com"
|
||||
phone = "+1-555-555-5555"
|
||||
alert_notifications = true
|
||||
alerts_to_admins = true
|
||||
}
|
||||
`,
|
||||
expected: securitycenter.Contact{
|
||||
Metadata: iacTypes.NewTestMetadata(),
|
||||
EnableAlertNotifications: iacTypes.Bool(true, iacTypes.NewTestMetadata()),
|
||||
EnableAlertsToAdmins: iacTypes.Bool(true, iacTypes.NewTestMetadata()),
|
||||
Email: iacTypes.String("contact@example.com", iacTypes.NewTestMetadata()),
|
||||
Phone: iacTypes.String("+1-555-555-5555", iacTypes.NewTestMetadata()),
|
||||
IsEnabled: iacTypes.BoolValue{},
|
||||
MinimalSeverity: iacTypes.StringValue{},
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -41,7 +47,11 @@ func Test_adaptContact(t *testing.T) {
|
||||
expected: securitycenter.Contact{
|
||||
Metadata: iacTypes.NewTestMetadata(),
|
||||
EnableAlertNotifications: iacTypes.Bool(false, iacTypes.NewTestMetadata()),
|
||||
EnableAlertsToAdmins: iacTypes.Bool(false, iacTypes.NewTestMetadata()),
|
||||
Email: iacTypes.String("", iacTypes.NewTestMetadata()),
|
||||
Phone: iacTypes.String("", iacTypes.NewTestMetadata()),
|
||||
IsEnabled: iacTypes.BoolValue{},
|
||||
MinimalSeverity: iacTypes.StringValue{},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -107,8 +117,10 @@ func Test_adaptSubscription(t *testing.T) {
|
||||
func TestLines(t *testing.T) {
|
||||
src := `
|
||||
resource "azurerm_security_center_contact" "example" {
|
||||
email = "contact@example.com"
|
||||
phone = "+1-555-555-5555"
|
||||
alert_notifications = true
|
||||
alerts_to_admins = true
|
||||
}
|
||||
|
||||
resource "azurerm_security_center_subscription_pricing" "example" {
|
||||
@@ -124,12 +136,18 @@ func TestLines(t *testing.T) {
|
||||
contact := adapted.Contacts[0]
|
||||
sub := adapted.Subscriptions[0]
|
||||
|
||||
assert.Equal(t, 3, contact.Phone.GetMetadata().Range().GetStartLine())
|
||||
assert.Equal(t, 3, contact.Phone.GetMetadata().Range().GetEndLine())
|
||||
assert.Equal(t, 3, contact.Email.GetMetadata().Range().GetStartLine())
|
||||
assert.Equal(t, 3, contact.Email.GetMetadata().Range().GetEndLine())
|
||||
|
||||
assert.Equal(t, 4, contact.EnableAlertNotifications.GetMetadata().Range().GetStartLine())
|
||||
assert.Equal(t, 4, contact.EnableAlertNotifications.GetMetadata().Range().GetEndLine())
|
||||
assert.Equal(t, 4, contact.Phone.GetMetadata().Range().GetStartLine())
|
||||
assert.Equal(t, 4, contact.Phone.GetMetadata().Range().GetEndLine())
|
||||
|
||||
assert.Equal(t, 8, sub.Tier.GetMetadata().Range().GetStartLine())
|
||||
assert.Equal(t, 8, sub.Tier.GetMetadata().Range().GetEndLine())
|
||||
assert.Equal(t, 5, contact.EnableAlertNotifications.GetMetadata().Range().GetStartLine())
|
||||
assert.Equal(t, 5, contact.EnableAlertNotifications.GetMetadata().Range().GetEndLine())
|
||||
|
||||
assert.Equal(t, 6, contact.EnableAlertsToAdmins.GetMetadata().Range().GetStartLine())
|
||||
assert.Equal(t, 6, contact.EnableAlertsToAdmins.GetMetadata().Range().GetEndLine())
|
||||
|
||||
assert.Equal(t, 10, sub.Tier.GetMetadata().Range().GetStartLine())
|
||||
assert.Equal(t, 10, sub.Tier.GetMetadata().Range().GetEndLine())
|
||||
}
|
||||
|
||||
@@ -12,7 +12,11 @@ type SecurityCenter struct {
|
||||
type Contact struct {
|
||||
Metadata iacTypes.Metadata
|
||||
EnableAlertNotifications iacTypes.BoolValue
|
||||
EnableAlertsToAdmins iacTypes.BoolValue
|
||||
Email iacTypes.StringValue
|
||||
Phone iacTypes.StringValue
|
||||
IsEnabled iacTypes.BoolValue
|
||||
MinimalSeverity iacTypes.StringValue
|
||||
}
|
||||
|
||||
const (
|
||||
|
||||
@@ -5407,10 +5407,26 @@
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/github.com.aquasecurity.trivy.pkg.iac.types.Metadata"
|
||||
},
|
||||
"email": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/github.com.aquasecurity.trivy.pkg.iac.types.StringValue"
|
||||
},
|
||||
"enablealertnotifications": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/github.com.aquasecurity.trivy.pkg.iac.types.BoolValue"
|
||||
},
|
||||
"enablealertstoadmins": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/github.com.aquasecurity.trivy.pkg.iac.types.BoolValue"
|
||||
},
|
||||
"isenabled": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/github.com.aquasecurity.trivy.pkg.iac.types.BoolValue"
|
||||
},
|
||||
"minimalseverity": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/github.com.aquasecurity.trivy.pkg.iac.types.StringValue"
|
||||
},
|
||||
"phone": {
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/github.com.aquasecurity.trivy.pkg.iac.types.StringValue"
|
||||
|
||||
Reference in New Issue
Block a user