Skip to content

Commit

Permalink
Support DefenderForStorageSettings resource by adding default state (#…
Browse files Browse the repository at this point in the history
…3007)

Support DefenderForStorageSettings resource by adding the default state
to reset it to on delete, since it doesn't have an actual delete
operation.

Without the hard-coded exception in the last commit, the generated
schema is incorrect. The cause is unrelated to the PR. What's happening
is that [the Azure
spec](https://github.com/Azure/azure-rest-api-specs/blob/fa8683f6725e5447cc808420c4542ce8375f0325/specification/security/resource-manager/Microsoft.Security/preview/2022-12-01-preview/defenderForStorageSettings.json)
is defined as such (unrelated properties omitted):
```json
      "properties": {
        "isEnabled": {
          "type": "boolean",
          "description": "Indicates whether Defender for Storage is enabled on this storage account."
        },
        "sensitiveDataDiscovery": {
          "x-ms-client-flatten": true,
          "$ref": "#/definitions/SensitiveDataDiscoveryProperties"
        }
      }
```

Where SensitiveDataDiscoveryProperties is:
```json
      "properties": {
        "isEnabled": {
          "type": "boolean",
          "description": "Indicates whether Sensitive Data Discovery should be enabled."
        }
      }
```

The nested object is annotated with x-ms-client-flatten, causing the
object to be flattened, causing the two identical `isEnabled` properties
to collide. #3016 will fix this in v3.

In the meantime, I added a manual exception.

Resolves #2996
  • Loading branch information
thomas11 authored Jan 24, 2024
1 parent 78139dc commit 4b30867
Show file tree
Hide file tree
Showing 43 changed files with 3,152 additions and 7 deletions.
217 changes: 213 additions & 4 deletions provider/cmd/pulumi-resource-azure-native/schema.json

Large diffs are not rendered by default.

13 changes: 11 additions & 2 deletions provider/pkg/gen/properties.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,15 +83,24 @@ func (m *moduleGenerator) genProperties(resolvedSchema *openapi.Schema, isOutput
// Change the name to lowerCamelCase.
sdkName = ToLowerCamel(sdkName)

flatten, ok := property.Extensions.GetBool(extensionClientFlatten)

// Flattened properties aren't modelled in the SDK explicitly: their sub-properties are merged directly to the parent.
// If the type is marked as a dictionary, ignore the extension and proceed with modeling this property explicitly.
// We can't flatten dictionaries in a type-safe manner.
isDict := resolvedProperty.AdditionalProperties != nil
//TODO: Remove when https://github.com/Azure/azure-rest-api-specs/pull/14550 is rolled back

// TODO: Remove when https://github.com/Azure/azure-rest-api-specs/pull/14550 is rolled back
workaroundDelegatedNetworkBreakingChange := property.Ref.String() == "#/definitions/OrchestratorResourceProperties" ||
property.Ref.String() == "#/definitions/DelegatedSubnetProperties" ||
property.Ref.String() == "#/definitions/DelegatedControllerProperties"
if flatten, ok := property.Extensions.GetBool(extensionClientFlatten); (ok && flatten && !isDict) || workaroundDelegatedNetworkBreakingChange {

// TODO: can be removed when https://github.com/pulumi/pulumi-azure-native/pull/3016 is merged
if m.resourceName == "DefenderForStorage" && (name == "malwareScanning" || name == "sensitiveDataDiscovery") {
flatten = false
}

if (ok && flatten && !isDict) || workaroundDelegatedNetworkBreakingChange {
bag, err := m.genProperties(resolvedProperty, isOutput, isType)
if err != nil {
return nil, err
Expand Down
5 changes: 5 additions & 0 deletions provider/pkg/openapi/defaults/defaultResourcesState.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ var defaultResourcesStateRaw = map[string]map[string]interface{}{
"/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Insights/components/{resourceName}/ProactiveDetectionConfigs/{ConfigurationId}": {
"enabled": false,
},
"/{resourceId}/providers/Microsoft.Security/defenderForStorageSettings/{settingName}": {
"isEnabled": false,
// https://learn.microsoft.com/en-us/azure/storage/common/azure-defender-storage-configure?tabs=enable-subscription#rest-api-1
"overrideSubscriptionLevelSettings": true,
},
"/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.ServiceBus/namespaces/{namespaceName}/networkRuleSets/default": {
"defaultAction": "Deny",
},
Expand Down
3 changes: 2 additions & 1 deletion reports/allEndpoints.json
Original file line number Diff line number Diff line change
Expand Up @@ -64359,7 +64359,8 @@
"HttpVerbs": [
"GET",
"PUT"
]
],
"Added": true
}
},
"DevOpsConfigurations": {
Expand Down
3 changes: 3 additions & 0 deletions reports/allResourceVersionsByResource.json
Original file line number Diff line number Diff line change
Expand Up @@ -18006,6 +18006,9 @@
"CustomEntityStoreAssignment": [
"2021-07-01-preview"
],
"DefenderForStorage": [
"2022-12-01-preview"
],
"DevOpsConfiguration": [
"2023-09-01-preview"
],
Expand Down
3 changes: 3 additions & 0 deletions reports/allResourcesByVersion.json
Original file line number Diff line number Diff line change
Expand Up @@ -17469,6 +17469,9 @@
"2022-11-20-preview": [
"APICollection"
],
"2022-12-01-preview": [
"DefenderForStorage"
],
"2023-01-01-preview": [
"SecurityOperator"
],
Expand Down
1 change: 1 addition & 0 deletions reports/pending.json
Original file line number Diff line number Diff line change
Expand Up @@ -870,6 +870,7 @@
"2022-07-01-preview",
"2022-08-01-preview",
"2022-11-20-preview",
"2022-12-01-preview",
"2023-01-01-preview",
"2023-02-01-preview",
"2023-03-01-preview",
Expand Down
145 changes: 145 additions & 0 deletions sdk/dotnet/Security/DefenderForStorage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
// *** WARNING: this file was generated by pulumi. ***
// *** Do not edit by hand unless you're certain you know what you are doing! ***

using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Threading.Tasks;
using Pulumi.Serialization;

namespace Pulumi.AzureNative.Security
{
/// <summary>
/// The Defender for Storage resource.
/// Azure REST API version: 2022-12-01-preview.
/// </summary>
[AzureNativeResourceType("azure-native:security:DefenderForStorage")]
public partial class DefenderForStorage : global::Pulumi.CustomResource
{
/// <summary>
/// Indicates whether Defender for Storage is enabled on this storage account.
/// </summary>
[Output("isEnabled")]
public Output<bool?> IsEnabled { get; private set; } = null!;

/// <summary>
/// Properties of Malware Scanning.
/// </summary>
[Output("malwareScanning")]
public Output<Outputs.MalwareScanningPropertiesResponse?> MalwareScanning { get; private set; } = null!;

/// <summary>
/// Resource name
/// </summary>
[Output("name")]
public Output<string> Name { get; private set; } = null!;

/// <summary>
/// Indicates whether the settings defined for this storage account should override the settings defined for the subscription.
/// </summary>
[Output("overrideSubscriptionLevelSettings")]
public Output<bool?> OverrideSubscriptionLevelSettings { get; private set; } = null!;

/// <summary>
/// Properties of Sensitive Data Discovery.
/// </summary>
[Output("sensitiveDataDiscovery")]
public Output<Outputs.SensitiveDataDiscoveryPropertiesResponse?> SensitiveDataDiscovery { get; private set; } = null!;

/// <summary>
/// Resource type
/// </summary>
[Output("type")]
public Output<string> Type { get; private set; } = null!;


/// <summary>
/// Create a DefenderForStorage resource with the given unique name, arguments, and options.
/// </summary>
///
/// <param name="name">The unique name of the resource</param>
/// <param name="args">The arguments used to populate this resource's properties</param>
/// <param name="options">A bag of options that control this resource's behavior</param>
public DefenderForStorage(string name, DefenderForStorageArgs args, CustomResourceOptions? options = null)
: base("azure-native:security:DefenderForStorage", name, args ?? new DefenderForStorageArgs(), MakeResourceOptions(options, ""))
{
}

private DefenderForStorage(string name, Input<string> id, CustomResourceOptions? options = null)
: base("azure-native:security:DefenderForStorage", name, null, MakeResourceOptions(options, id))
{
}

private static CustomResourceOptions MakeResourceOptions(CustomResourceOptions? options, Input<string>? id)
{
var defaultOptions = new CustomResourceOptions
{
Version = Utilities.Version,
Aliases =
{
new global::Pulumi.Alias { Type = "azure-native:security/v20221201preview:DefenderForStorage" },
},
};
var merged = CustomResourceOptions.Merge(defaultOptions, options);
// Override the ID if one was specified for consistency with other language SDKs.
merged.Id = id ?? merged.Id;
return merged;
}
/// <summary>
/// Get an existing DefenderForStorage resource's state with the given name, ID, and optional extra
/// properties used to qualify the lookup.
/// </summary>
///
/// <param name="name">The unique name of the resulting resource.</param>
/// <param name="id">The unique provider ID of the resource to lookup.</param>
/// <param name="options">A bag of options that control this resource's behavior</param>
public static DefenderForStorage Get(string name, Input<string> id, CustomResourceOptions? options = null)
{
return new DefenderForStorage(name, id, options);
}
}

public sealed class DefenderForStorageArgs : global::Pulumi.ResourceArgs
{
/// <summary>
/// Indicates whether Defender for Storage is enabled on this storage account.
/// </summary>
[Input("isEnabled")]
public Input<bool>? IsEnabled { get; set; }

/// <summary>
/// Properties of Malware Scanning.
/// </summary>
[Input("malwareScanning")]
public Input<Inputs.MalwareScanningPropertiesArgs>? MalwareScanning { get; set; }

/// <summary>
/// Indicates whether the settings defined for this storage account should override the settings defined for the subscription.
/// </summary>
[Input("overrideSubscriptionLevelSettings")]
public Input<bool>? OverrideSubscriptionLevelSettings { get; set; }

/// <summary>
/// The identifier of the resource.
/// </summary>
[Input("resourceId", required: true)]
public Input<string> ResourceId { get; set; } = null!;

/// <summary>
/// Properties of Sensitive Data Discovery.
/// </summary>
[Input("sensitiveDataDiscovery")]
public Input<Inputs.SensitiveDataDiscoveryPropertiesArgs>? SensitiveDataDiscovery { get; set; }

/// <summary>
/// Defender for Storage setting name.
/// </summary>
[Input("settingName")]
public Input<string>? SettingName { get; set; }

public DefenderForStorageArgs()
{
}
public static new DefenderForStorageArgs Empty => new DefenderForStorageArgs();
}
}
128 changes: 128 additions & 0 deletions sdk/dotnet/Security/GetDefenderForStorage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
// *** WARNING: this file was generated by pulumi. ***
// *** Do not edit by hand unless you're certain you know what you are doing! ***

using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Threading.Tasks;
using Pulumi.Serialization;

namespace Pulumi.AzureNative.Security
{
public static class GetDefenderForStorage
{
/// <summary>
/// Gets the Defender for Storage settings for the specified storage account.
/// Azure REST API version: 2022-12-01-preview.
/// </summary>
public static Task<GetDefenderForStorageResult> InvokeAsync(GetDefenderForStorageArgs args, InvokeOptions? options = null)
=> global::Pulumi.Deployment.Instance.InvokeAsync<GetDefenderForStorageResult>("azure-native:security:getDefenderForStorage", args ?? new GetDefenderForStorageArgs(), options.WithDefaults());

/// <summary>
/// Gets the Defender for Storage settings for the specified storage account.
/// Azure REST API version: 2022-12-01-preview.
/// </summary>
public static Output<GetDefenderForStorageResult> Invoke(GetDefenderForStorageInvokeArgs args, InvokeOptions? options = null)
=> global::Pulumi.Deployment.Instance.Invoke<GetDefenderForStorageResult>("azure-native:security:getDefenderForStorage", args ?? new GetDefenderForStorageInvokeArgs(), options.WithDefaults());
}


public sealed class GetDefenderForStorageArgs : global::Pulumi.InvokeArgs
{
/// <summary>
/// The identifier of the resource.
/// </summary>
[Input("resourceId", required: true)]
public string ResourceId { get; set; } = null!;

/// <summary>
/// Defender for Storage setting name.
/// </summary>
[Input("settingName", required: true)]
public string SettingName { get; set; } = null!;

public GetDefenderForStorageArgs()
{
}
public static new GetDefenderForStorageArgs Empty => new GetDefenderForStorageArgs();
}

public sealed class GetDefenderForStorageInvokeArgs : global::Pulumi.InvokeArgs
{
/// <summary>
/// The identifier of the resource.
/// </summary>
[Input("resourceId", required: true)]
public Input<string> ResourceId { get; set; } = null!;

/// <summary>
/// Defender for Storage setting name.
/// </summary>
[Input("settingName", required: true)]
public Input<string> SettingName { get; set; } = null!;

public GetDefenderForStorageInvokeArgs()
{
}
public static new GetDefenderForStorageInvokeArgs Empty => new GetDefenderForStorageInvokeArgs();
}


[OutputType]
public sealed class GetDefenderForStorageResult
{
/// <summary>
/// Resource Id
/// </summary>
public readonly string Id;
/// <summary>
/// Indicates whether Defender for Storage is enabled on this storage account.
/// </summary>
public readonly bool? IsEnabled;
/// <summary>
/// Properties of Malware Scanning.
/// </summary>
public readonly Outputs.MalwareScanningPropertiesResponse? MalwareScanning;
/// <summary>
/// Resource name
/// </summary>
public readonly string Name;
/// <summary>
/// Indicates whether the settings defined for this storage account should override the settings defined for the subscription.
/// </summary>
public readonly bool? OverrideSubscriptionLevelSettings;
/// <summary>
/// Properties of Sensitive Data Discovery.
/// </summary>
public readonly Outputs.SensitiveDataDiscoveryPropertiesResponse? SensitiveDataDiscovery;
/// <summary>
/// Resource type
/// </summary>
public readonly string Type;

[OutputConstructor]
private GetDefenderForStorageResult(
string id,

bool? isEnabled,

Outputs.MalwareScanningPropertiesResponse? malwareScanning,

string name,

bool? overrideSubscriptionLevelSettings,

Outputs.SensitiveDataDiscoveryPropertiesResponse? sensitiveDataDiscovery,

string type)
{
Id = id;
IsEnabled = isEnabled;
MalwareScanning = malwareScanning;
Name = name;
OverrideSubscriptionLevelSettings = overrideSubscriptionLevelSettings;
SensitiveDataDiscovery = sensitiveDataDiscovery;
Type = type;
}
}
}
41 changes: 41 additions & 0 deletions sdk/dotnet/Security/Inputs/MalwareScanningPropertiesArgs.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// *** WARNING: this file was generated by pulumi. ***
// *** Do not edit by hand unless you're certain you know what you are doing! ***

using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Threading.Tasks;
using Pulumi.Serialization;

namespace Pulumi.AzureNative.Security.Inputs
{

/// <summary>
/// Properties of Malware Scanning.
/// </summary>
public sealed class MalwareScanningPropertiesArgs : global::Pulumi.ResourceArgs
{
/// <summary>
/// Defines the max GB to be scanned per Month. Set to -1 if no capping is needed.
/// </summary>
[Input("capGBPerMonth")]
public Input<int>? CapGBPerMonth { get; set; }

/// <summary>
/// Indicates whether On Upload malware scanning should be enabled.
/// </summary>
[Input("isEnabled")]
public Input<bool>? IsEnabled { get; set; }

/// <summary>
/// Optional. Resource id of an Event Grid Topic to send scan results to.
/// </summary>
[Input("scanResultsEventGridTopicResourceId")]
public Input<string>? ScanResultsEventGridTopicResourceId { get; set; }

public MalwareScanningPropertiesArgs()
{
}
public static new MalwareScanningPropertiesArgs Empty => new MalwareScanningPropertiesArgs();
}
}
Loading

0 comments on commit 4b30867

Please sign in to comment.