Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 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
1 change: 1 addition & 0 deletions eng/Packages.Data.props
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@
<PackageReference Update="Azure.ResourceManager" Version="1.11.0-alpha.20240222.6" />
<PackageReference Update="Azure.ResourceManager.AppConfiguration" Version="1.3.0-alpha.20240222.1" />
<PackageReference Update="Azure.ResourceManager.AppService" Version="1.1.0-alpha.20240222.2" />
<PackageReference Update="Azure.ResourceManager.Authorization" Version="1.2.0-alpha.20240227.2" />
<PackageReference Update="Azure.ResourceManager.KeyVault" Version="1.3.0-alpha.20240222.2" />
<PackageReference Update="Azure.ResourceManager.Resources" Version="1.8.0-alpha.20240222.2" />
<PackageReference Update="Azure.ResourceManager.Sql" Version="1.3.0-alpha.20240222.1" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ public static partial class CdkExtensions
public partial class Configuration
{
public Configuration() { }
public bool UsePromptMode { get { throw null; } set { } }
public bool UseInteractiveMode { get { throw null; } set { } }
}
public abstract partial class Construct : Azure.Provisioning.IConstruct
{
Expand Down Expand Up @@ -90,6 +90,7 @@ protected Resource(Azure.Provisioning.IConstruct scope, Azure.Provisioning.Resou
public Azure.Provisioning.Resource? Parent { get { throw null; } }
public Azure.Provisioning.IConstruct Scope { get { throw null; } }
public string Version { get { throw null; } }
public Azure.Provisioning.Authorization.RoleAssignment AssignRole(Azure.Provisioning.Authorization.RoleDefinition roleDefinition, System.Guid? principalId = default(System.Guid?)) { throw null; }
protected virtual Azure.Provisioning.Resource? FindParentInScope(Azure.Provisioning.IConstruct scope) { throw null; }
protected virtual string GetAzureName(Azure.Provisioning.IConstruct scope, string resourceName) { throw null; }
Azure.Provisioning.Resource System.ClientModel.Primitives.IPersistableModel<Azure.Provisioning.Resource>.Create(System.BinaryData data, System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; }
Expand Down Expand Up @@ -151,6 +152,30 @@ public enum WebSiteRuntime
Dotnetcore = 1,
}
}
namespace Azure.Provisioning.Authorization
{
public partial class RoleAssignment : Azure.Provisioning.Resource<Azure.ResourceManager.Authorization.RoleAssignmentData>
{
internal RoleAssignment() : base (default(Azure.Provisioning.IConstruct), default(Azure.Provisioning.Resource), default(string), default(Azure.Core.ResourceType), default(string), default(System.Func<string, Azure.ResourceManager.Authorization.RoleAssignmentData>)) { }
}
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public readonly partial struct RoleDefinition : System.IEquatable<Azure.Provisioning.Authorization.RoleDefinition>
{
private readonly object _dummy;
private readonly int _dummyPrimitive;
public RoleDefinition(string value) { throw null; }
public static Azure.Provisioning.Authorization.RoleDefinition StorageBlobDataContributor { get { throw null; } }
public static Azure.Provisioning.Authorization.RoleDefinition StorageQueueDataContributor { get { throw null; } }
public static Azure.Provisioning.Authorization.RoleDefinition StorageTableDataContributor { get { throw null; } }
public bool Equals(Azure.Provisioning.Authorization.RoleDefinition other) { throw null; }
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
public override bool Equals(object? obj) { throw null; }
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
public override int GetHashCode() { throw null; }
public static implicit operator Azure.Provisioning.Authorization.RoleDefinition (string value) { throw null; }
public override string ToString() { throw null; }
}
}
namespace Azure.Provisioning.KeyVaults
{
public partial class KeyVault : Azure.Provisioning.Resource<Azure.ResourceManager.KeyVault.KeyVaultData>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ public static partial class CdkExtensions
public partial class Configuration
{
public Configuration() { }
public bool UsePromptMode { get { throw null; } set { } }
public bool UseInteractiveMode { get { throw null; } set { } }
}
public abstract partial class Construct : Azure.Provisioning.IConstruct
{
Expand Down Expand Up @@ -90,6 +90,7 @@ protected Resource(Azure.Provisioning.IConstruct scope, Azure.Provisioning.Resou
public Azure.Provisioning.Resource? Parent { get { throw null; } }
public Azure.Provisioning.IConstruct Scope { get { throw null; } }
public string Version { get { throw null; } }
public Azure.Provisioning.Authorization.RoleAssignment AssignRole(Azure.Provisioning.Authorization.RoleDefinition roleDefinition, System.Guid? principalId = default(System.Guid?)) { throw null; }
protected virtual Azure.Provisioning.Resource? FindParentInScope(Azure.Provisioning.IConstruct scope) { throw null; }
protected virtual string GetAzureName(Azure.Provisioning.IConstruct scope, string resourceName) { throw null; }
Azure.Provisioning.Resource System.ClientModel.Primitives.IPersistableModel<Azure.Provisioning.Resource>.Create(System.BinaryData data, System.ClientModel.Primitives.ModelReaderWriterOptions options) { throw null; }
Expand Down Expand Up @@ -151,6 +152,30 @@ public enum WebSiteRuntime
Dotnetcore = 1,
}
}
namespace Azure.Provisioning.Authorization
{
public partial class RoleAssignment : Azure.Provisioning.Resource<Azure.ResourceManager.Authorization.RoleAssignmentData>
{
internal RoleAssignment() : base (default(Azure.Provisioning.IConstruct), default(Azure.Provisioning.Resource), default(string), default(Azure.Core.ResourceType), default(string), default(System.Func<string, Azure.ResourceManager.Authorization.RoleAssignmentData>)) { }
}
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public readonly partial struct RoleDefinition : System.IEquatable<Azure.Provisioning.Authorization.RoleDefinition>
{
private readonly object _dummy;
private readonly int _dummyPrimitive;
public RoleDefinition(string value) { throw null; }
public static Azure.Provisioning.Authorization.RoleDefinition StorageBlobDataContributor { get { throw null; } }
public static Azure.Provisioning.Authorization.RoleDefinition StorageQueueDataContributor { get { throw null; } }
public static Azure.Provisioning.Authorization.RoleDefinition StorageTableDataContributor { get { throw null; } }
public bool Equals(Azure.Provisioning.Authorization.RoleDefinition other) { throw null; }
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
public override bool Equals(object? obj) { throw null; }
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
public override int GetHashCode() { throw null; }
public static implicit operator Azure.Provisioning.Authorization.RoleDefinition (string value) { throw null; }
public override string ToString() { throw null; }
}
}
namespace Azure.Provisioning.KeyVaults
{
public partial class KeyVault : Azure.Provisioning.Resource<Azure.ResourceManager.KeyVault.KeyVaultData>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
<PackageReference Include="Azure.ResourceManager.AppService" />
<PackageReference Include="Azure.ResourceManager.Storage" />
<PackageReference Include="Azure.ResourceManager.AppConfiguration" />
<PackageReference Include="Azure.ResourceManager.Authorization" />
<PackageReference Include="System.ClientModel" />
</ItemGroup>

Expand Down
2 changes: 1 addition & 1 deletion sdk/provisioning/Azure.Provisioning/src/Configuration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@ public class Configuration
/// <summary>
/// Whether to use prompt mode.
/// </summary>
public bool UsePromptMode { get; set; }
public bool UseInteractiveMode { get; set; }
}
}
7 changes: 1 addition & 6 deletions sdk/provisioning/Azure.Provisioning/src/Extensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System;
using System.IO;
using System.Text;
using Azure.Provisioning.Authorization;
using Azure.Provisioning.ResourceManager;
using Azure.Provisioning.Resources;

Expand All @@ -20,12 +21,6 @@ public static string ToCamelCase(this string str)
#endif
}

public static bool IsChildResource(this Resource resource)
{
//TODO: this is a bit of a hack. We should probably have a better way to determine if a resource is a child resource
return resource is DeploymentScript || (resource.Parent is not null && resource.Parent is not ResourceGroup && resource.Parent is not Subscription);
}

public static void Write(this MemoryStream stream, string value)
{
var bytes = Encoding.UTF8.GetBytes(value);
Expand Down
2 changes: 1 addition & 1 deletion sdk/provisioning/Azure.Provisioning/src/Parameter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ public Parameter(string name, string? description = default, object? defaultValu
/// <param name="defaultValue">The parameter defaultValue.</param>
/// <param name="isSecure">Is the parameter secure.</param>
/// <param name="isExpression">Is the parameter an expression.</param>
internal Parameter(string name, string? description = default, object? defaultValue = default, bool isSecure = false, bool isExpression = false)
internal Parameter(string name, string? description, object? defaultValue = default, bool isSecure = false, bool isExpression = false)
: this (name, description, defaultValue, isSecure)
{
IsExpression = isExpression;
Expand Down
25 changes: 24 additions & 1 deletion sdk/provisioning/Azure.Provisioning/src/Resource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@
using System.Security.Cryptography;
using System.Text;
using Azure.Core;
using Azure.Provisioning.Authorization;
using Azure.Provisioning.ResourceManager;
using Azure.Provisioning.Resources;
using Azure.ResourceManager;
using Azure.ResourceManager.Authorization.Models;
using Azure.ResourceManager.Models;

namespace Azure.Provisioning
Expand Down Expand Up @@ -191,6 +193,16 @@ private void ValidateOverrideCanBeAdded(object instance, string name)
}
}

/// <summary>
/// Assigns a role to the resource.
/// </summary>
/// <param name="roleDefinition">The role definition.</param>
/// <param name="principalId">The principal ID.</param>
public RoleAssignment AssignRole(RoleDefinition roleDefinition, Guid? principalId = default)
{
return new RoleAssignment(Scope, this, roleDefinition, principalId);
}

/// <summary>
/// Adds an output to the resource.
/// </summary>
Expand Down Expand Up @@ -246,7 +258,7 @@ private BinaryData SerializeModule(ModelReaderWriterOptions options)

stream.WriteLine($"resource {Name} '{ResourceType}@{Version}' = {{");

if (this.IsChildResource() && this is not DeploymentScript && this is not Subscription)
if (NeedsParent())
{
stream.WriteLine($" parent: {Parent!.Name}");
}
Expand Down Expand Up @@ -298,10 +310,21 @@ private BinaryData SerializeModule(ModelReaderWriterOptions options)
return new BinaryData(stream.GetBuffer().AsMemory(0, (int)stream.Position));
}

private bool NeedsParent()
{
return this is not (Subscription or RoleAssignment) &&
Parent is not null && Parent is not (ResourceGroup or Subscription or RoleAssignment);
}

private bool NeedsScope()
{
Debug.Assert(ModuleScope != null, "ModuleScope should not be null");

if (this is RoleAssignment)
{
return true;
}

switch (Parent)
{
case ResourceGroup _:
Expand Down
4 changes: 2 additions & 2 deletions sdk/provisioning/Azure.Provisioning/src/ResourceOfT.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,11 @@ protected Resource(
Properties = (T)ResourceData;

// Resources that have a non-RG parent do not require a location value
if (scope.Configuration?.UsePromptMode == true && Parent is ResourceGroup)
if (scope.Configuration?.UseInteractiveMode == true && Parent is ResourceGroup)
{
// We can't use the lambda overload because not all of the T's will inherit from TrackedResourceData
// TODO we may need to add a protected LocationSelector property in the future if there are exceptions to the rule
AssignParameter(Properties, "Location", new Parameter("location", defaultValue: $"{ResourceGroup.AnonymousResourceGroupName}.location", isExpression: true));
AssignParameter(Properties, "Location", new Parameter("location", null, defaultValue: $"{ResourceGroup.AnonymousResourceGroupName}.location", isExpression: true));
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using Azure.Core;
using Azure.ResourceManager.Authorization;
using Azure.ResourceManager.Authorization.Models;

namespace Azure.Provisioning.Authorization
{
/// <summary>
/// Role assignment resource.
/// </summary>
public class RoleAssignment : Resource<RoleAssignmentData>
{
internal static readonly ResourceType ResourceType = "Microsoft.Resources/roleAssignments";

/// <summary>
/// Initializes a new instance of the <see cref="RoleAssignment"/>.
/// </summary>
/// <param name="scope">The scope.</param>
/// <param name="resource"></param>
/// <param name="roleDefinition"></param>
/// <param name="principalId"></param>
internal RoleAssignment(
IConstruct scope,
Resource resource,
RoleDefinition roleDefinition,
Guid? principalId = default)
: base(
scope,
resource,
resource.Name,
ResourceType,
"2022-04-01",
(name) => ArmAuthorizationModelFactory.RoleAssignmentData(
name: name,
roleDefinitionId: ResourceIdentifier.Parse($"/providers/Microsoft.Authorization/roleDefinitions/{roleDefinition}"),
principalId: principalId))
{
if (scope.Configuration?.UseInteractiveMode != true && principalId == null)
{
throw new InvalidOperationException("PrincipalId must be specified when not in interactive mode.");
}

if (principalId == null)
{
AssignParameter(data => data.PrincipalId, new Parameter("principalId"));
AssignProperty(data => data.Name, $"guid('{resource.Name}', principalId, '{roleDefinition}')");
}
else
{
AssignProperty(data => data.Name, $"guid('{resource.Name}', '{principalId}', '{roleDefinition}')");
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.ComponentModel;

namespace Azure.Provisioning.Authorization
{
/// <summary> Role definition. </summary>
public readonly partial struct RoleDefinition : IEquatable<RoleDefinition>
{
private readonly string _value;

/// <summary> Initializes a new instance of <see cref="RoleDefinition"/>. </summary>
/// <exception cref="ArgumentNullException"> <paramref name="value"/> is null. </exception>
public RoleDefinition(string value)
{
_value = value ?? throw new ArgumentNullException(nameof(value));
}

/// <summary>
/// Storage blob data contributor role.
/// </summary>
public static RoleDefinition StorageBlobDataContributor { get; } = new RoleDefinition("ba92f5b4-2d11-453d-a403-e96b0029c9fe");

/// <summary>
/// Storage queue data contributor role.
/// </summary>
public static RoleDefinition StorageQueueDataContributor { get; } = new RoleDefinition("974c5e8b-45b9-4653-ba55-5f855dd0fb88");

/// <summary>
/// Storage table data contributor role.
/// </summary>
public static RoleDefinition StorageTableDataContributor { get; } = new RoleDefinition("0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3");

/// <summary> Converts a string to a <see cref="RoleDefinition"/>. </summary>
public static implicit operator RoleDefinition(string value) => new RoleDefinition(value);

/// <inheritdoc />
[EditorBrowsable(EditorBrowsableState.Never)]
public override bool Equals(object? obj) => obj is RoleDefinition other && Equals(other);
/// <inheritdoc />
public bool Equals(RoleDefinition other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase);

/// <inheritdoc />
[EditorBrowsable(EditorBrowsableState.Never)]
public override int GetHashCode() => _value?.GetHashCode() ?? 0;
/// <inheritdoc />
public override string ToString() => _value;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public static ResourceGroup AddResourceGroup(this IConstruct construct)
throw new InvalidOperationException("ResourceGroup already exists on the construct");
}

return new ResourceGroup(construct, name: construct.Configuration?.UsePromptMode == true ? ResourceGroup.AnonymousResourceGroupName : "rg");
return new ResourceGroup(construct, name: construct.Configuration?.UseInteractiveMode == true ? ResourceGroup.AnonymousResourceGroupName : "rg");
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,7 @@ public StorageAccount(IConstruct scope, StorageKind kind, StorageSkuName sku, Re
sku: new StorageSku(sku),
kind: StorageKind.StorageV2))
{
if (scope.Configuration?.UsePromptMode == true)
{
AssignProperty(data => data.Name, $"toLower(take(concat('{name}', uniqueString(resourceGroup().id)), 24))");
}
AssignProperty(data => data.Name, $"toLower(take(concat('{name}', uniqueString(resourceGroup().id)), 24))");
}

/// <inheritdoc/>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
targetScope = 'resourceGroup'

@description('')
param location string = resourceGroup().location

@description('')
param principalId string


resource storageAccount_d1RlrfJGB 'Microsoft.Storage/storageAccounts@2022-09-01' = {
name: toLower(take(concat('photoAcct', uniqueString(resourceGroup().id)), 24))
location: location
sku: {
name: 'Premium_LRS'
}
kind: 'StorageV2'
properties: {
}
}

resource blobService_tjgcRkcbL 'Microsoft.Storage/storageAccounts/blobServices@2022-09-01' = {
parent: storageAccount_d1RlrfJGB
name: 'default'
properties: {
}
}

resource roleAssignment_XCw6aC1YR 'Microsoft.Resources/roleAssignments@2022-04-01' = {
scope: storageAccount_d1RlrfJGB
name: guid('storageAccount_d1RlrfJGB', principalId, 'ba92f5b4-2d11-453d-a403-e96b0029c9fe')
properties: {
roleDefinitionId: '/providers/Microsoft.Authorization/roleDefinitions/ba92f5b4-2d11-453d-a403-e96b0029c9fe'
principalId: principalId
}
}
Loading