Skip to content

Commit

Permalink
Export template with custom subscription and resource group #651 (#659)
Browse files Browse the repository at this point in the history
  • Loading branch information
BernieWhite authored Feb 22, 2021
1 parent 3779b0a commit dc2cccc
Show file tree
Hide file tree
Showing 26 changed files with 1,048 additions and 193 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,8 @@ The following conceptual topics exist in the `PSRule.Rules.Azure` module:
- [Azure_AKSNodeMinimumMaxPods](docs/concepts/PSRule.Rules.Azure/en-US/about_PSRule_Azure_Configuration.md#azure_aksnodeminimummaxpods)
- [Azure_AllowedRegions](docs/concepts/PSRule.Rules.Azure/en-US/about_PSRule_Azure_Configuration.md#azure_allowedregions)
- [Azure_MinimumCertificateLifetime](docs/concepts/PSRule.Rules.Azure/en-US/about_PSRule_Azure_Configuration.md#azure_minimumcertificatelifetime)
- [AZURE_RESOURCE_GROUP](docs/concepts/PSRule.Rules.Azure/en-US/about_PSRule_Azure_Configuration.md#azure_resource_group)
- [AZURE_SUBSCRIPTION](docs/concepts/PSRule.Rules.Azure/en-US/about_PSRule_Azure_Configuration.md#azure_subscription)

## Related projects

Expand Down
26 changes: 26 additions & 0 deletions ThirdPartyNotices.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,32 @@ Do Not Translate or Localize

This file is based on or incorporates material from the projects listed below (Third Party IP). The original copyright notice and the license under which Microsoft received such Third Party IP, are set forth below. Such licenses and notices are provided for informational purposes only. Microsoft licenses the Third Party IP to you under the licensing terms for the Microsoft product. Microsoft reserves all other rights not expressly granted under this agreement, whether by implication, estoppel or otherwise.

---------------------------------------------
File: YamlDotNet
---------------------------------------------

https://github.com/aaubry/YamlDotNet

Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014 Antoine Aubry and contributors

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

---------------------------------------------
File: Newtonsoft.Json
---------------------------------------------
Expand Down
8 changes: 8 additions & 0 deletions docs/CHANGELOG-v1.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@

## Unreleased

What's changed since pre-release v1.1.0-B2102015:

- New features:
- Exporting template with `Export-AzRuleTemplateData` supports custom resource group and subscription. [#651](https://github.com/microsoft/PSRule.Rules.Azure/issues/651)
- Subscription and resource group used for deployment can be specified instead of using defaults.
- `ResourceGroupName` parameter of `Export-AzRuleTemplateData` has been renamed to `ResourceGroup`.
- Added a parameter alias for `ResourceGroupName` on `Export-AzRuleTemplateData`.

## v1.1.0-B2102015 (pre-release)

What's changed since pre-release v1.1.0-B2102010:
Expand Down
95 changes: 81 additions & 14 deletions docs/commands/PSRule.Rules.Azure/en-US/Export-AzRuleTemplateData.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,40 @@ Export resource configuration data from Azure templates.

```text
Export-AzRuleTemplateData [[-Name] <String>] -TemplateFile <String> [-ParameterFile <String[]>]
[-ResourceGroupName <String>] [-Subscription <String>] [-OutputPath <String>] [-PassThru] [<CommonParameters>]
[-ResourceGroup <ResourceGroupReference>] [-Subscription <SubscriptionReference>] [-OutputPath <String>]
[-PassThru] [<CommonParameters>]
```

## DESCRIPTION

Export resource configuration data by merging Azure Resource Manager (ARM) template and parameter files.
Template and parameters are merged by resolving template parameters, variables and functions.

This function does not check template files for strict compliance with Azure schemas.

By default this is an offline process, requiring no connectivity to Azure.
Some functions that may be included in templates dynamically query Azure for current state.
For these functions standard placeholder values are used by default.
Functions that use placeholders include `reference`, `list*`.

Functions that use placeholders include `subscription`, `resourceGroup`, `reference`, `list*`.
The `subscription()` function will return the following unless overridden:

This function does not check template files for strict compliance with Azure schemas.
- subscriptionId: 'ffffffff-ffff-ffff-ffff-ffffffffffff'
- tenantId: 'ffffffff-ffff-ffff-ffff-ffffffffffff'
- displayName: 'PSRule Test Subscription'
- state: 'NotDefined'

The `resourceGroup()` function will return the following unless overridden:

Currently the following limitations also apply:
- name: 'ps-rule-test-rg'
- location: 'eastus'
- tags: { }
- properties:
- provisioningState: 'Succeeded'

To override, set the `AZURE_SUBSCRIPTION` and `AZURE_RESOURCE_GROUP` in configuration.

Currently the following limitations apply:

- Nested templates are expanded, external templates are not.
- Deployment resources that link to an external template are returned as a resource.
Expand All @@ -51,6 +68,42 @@ Export-AzRuleTemplateData -TemplateFile .\template.json -ParameterFile .\paramet

Export resource configuration data based on merging a template and parameter file together.

### Example 2

```powershell
Get-AzRuleTemplateLink | Export-AzRuleTemplateData;
```

Recursively scan the current working path and export linked templates.

### Example 3

```powershell
$subscription = @{
subscriptionId = 'nnnnnnnn-nnnn-nnnn-nnnn-nnnnnnnnnnnn'
displayName = 'My Azure Subscription'
tenantId = 'nnnnnnnn-nnnn-nnnn-nnnn-nnnnnnnnnnnn'
}
Get-AzRuleTemplateLink | Export-AzRuleTemplateData -Subscription $subscription;
```

Export linked templates from the current working path using a specific subscription.

### Example 4

```powershell
$rg = @{
name = 'my-test-rg'
location = 'australiaeast'
tags = @{
env = 'prod'
}
}
Get-AzRuleTemplateLink | Export-AzRuleTemplateData -ResourceGroup $rg;
```

Export linked templates from the current working path using a specific resource group.

## PARAMETERS

### -Name
Expand Down Expand Up @@ -143,17 +196,24 @@ Accept pipeline input: False
Accept wildcard characters: False
```

### -ResourceGroupName

The name of the Resource Group where the deployment will occur.
If this option is specified, the properties of the Resource Group will be looked up and used during export.
### -ResourceGroup

A name or hashtable of the Resource Group where the deployment will occur.
This Resource Group specified here will be used to resolve the `resourceGroup()` function.

When the name of Resource Group is specified, the Resource Group will be looked up and used during export.
This requires an authenticated connection to Azure with permissions to read the specified Resource Group.

Alternately, a hashtable of a Resource Group object can be specified.
This option does not require an authenticated Azure connection.
The hashtable will override the defaults for any specified properties.

For more details see about_PSRule_Azure_Configuration.

```yaml
Type: String
Type: ResourceGroupReference
Parameter Sets: (All)
Aliases:
Aliases: ResourceGroupName
Required: False
Position: Named
Expand All @@ -164,13 +224,20 @@ Accept wildcard characters: False

### -Subscription

The name of the Subscription where the deployment will occur.
If this option is specified, the properties of the Subscription will be looked up and used during export.

The name or hashtable of the Subscription where the deployment will occur.
This subscription specified here will be used to resolve the `subscription()` function.

When a subscription name is specified, the Subscription will be looked up and used during export.
This requires an authenticated connection to Azure with permissions to read the specified Subscription.

Alternately, a hashtable of a Subscription object can be specified.
This option does not require an authenticated Azure connection.
The hashtable will override the defaults for any specified properties.

For more details see about_PSRule_Azure_Configuration.

```yaml
Type: String
Type: SubscriptionReference
Parameter Sets: (All)
Aliases:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@ Get-AzRuleTemplateLink [[-InputPath] <String[]>] [-SkipUnlinked] [[-Path] <Strin
Gets a link between an Azure Resource Manager (ARM) parameter file and its referenced template file.
Parameter files reference a template file by defining metadata.

By default, when parameter files without a reference to a template are discover and error is raised.
By default, when parameter files without a reference to a template are discovered an error is raised.

To reference a template, set the `metadata.template` property to a file path.
Referencing templates outside of the path specified with `-Path` is not permitted.

For more information see the [about_PSRule_Azure_Metadata_Link] topic.
For more information see the about_PSRule_Azure_Metadata_Link topic.

## EXAMPLES

Expand Down Expand Up @@ -110,3 +110,5 @@ This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable
## NOTES
## RELATED LINKS
[about_PSRule_Azure_Metadata_Link](../../../concepts/PSRule.Rules.Azure/en-US/about_PSRule_Azure_Metadata_Link.md)
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ The following configurations options are available for use:
- [Azure_AKSNodeMinimumMaxPods](#azure_aksnodeminimummaxpods)
- [Azure_AllowedRegions](#azure_allowedregions)
- [Azure_MinimumCertificateLifetime](#azure_minimumcertificatelifetime)
- [AZURE_RESOURCE_GROUP](#azure_resource_group)
- [AZURE_SUBSCRIPTION](#azure_subscription)

### Azure_AKSMinimumVersion

Expand Down Expand Up @@ -139,6 +141,89 @@ configuration:
Azure_MinimumCertificateLifetime: 90
```

### Azure_Resource_Group

This configuration option sets the resource group object used by the `resourceGroup()` function.
Configure this option to change the resource group object when using exporting templates for analysis.
Provided properties will override the default.
Any properties that are not provided with use the defaults as specified below.

This configuration option will be ignored when `-ResourceGroup` is used with `Export-AzRuleTemplateData`.

Syntax:

```yaml
configuration:
AZURE_RESOURCE_GROUP:
name: string
location: string
tags: object
properties:
provisioningState: string
```

Default:

```yaml
# YAML: The default AZURE_RESOURCE_GROUP configuration option
configuration:
AZURE_RESOURCE_GROUP:
name: 'ps-rule-test-rg'
location: 'eastus'
tags: { }
properties:
provisioningState: 'Succeeded'
```

Example:

```yaml
# YAML: Override the location of the resource group object.
configuration:
AZURE_RESOURCE_GROUP:
location: 'australiasoutheast'
```

### AZURE_SUBSCRIPTION

This configuration option sets the subscription object used by the `subscription()` function.
Configure this option to change the subscription object when using exporting templates for analysis.
Provided properties will override the default.
Any properties that are not provided with use the defaults as specified below.

This configuration option will be ignored when `-Subscription` is used with `Export-AzRuleTemplateData`.

Syntax:

```yaml
configuration:
AZURE_SUBSCRIPTION:
subscriptionId: string
tenantId: string
displayName: string
state: string
```

Default:

```yaml
# YAML: The default AZURE_SUBSCRIPTION configuration option
configuration:
AZURE_SUBSCRIPTION:
subscriptionId: 'ffffffff-ffff-ffff-ffff-ffffffffffff'
tenantId: 'ffffffff-ffff-ffff-ffff-ffffffffffff'
displayName: 'PSRule Test Subscription'
state: 'NotDefined'
```

Example:

```yaml
# YAML: Override the display name of the subscription object
AZURE_SUBSCRIPTION:
displayName: 'My test subscription'
```

## NOTE

An online version of this document is available at https://github.com/Microsoft/PSRule.Rules.Azure/blob/main/docs/concepts/PSRule.Rules.Azure/en-US/about_PSRule_Azure_Configuration.md.
Expand Down
18 changes: 18 additions & 0 deletions docs/scenarios/deployment-objects/export.template.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {},
"functions": [],
"variables": {},
"resources": [],
"outputs": {
"subscription": {
"type": "object",
"value": "[subscription()]"
},
"resourceGroup": {
"type": "object",
"value": "[resourceGroup()]"
}
}
}
58 changes: 58 additions & 0 deletions src/PSRule.Rules.Azure/Common/DictionaryExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using System.Collections.Generic;
using System.Diagnostics;

namespace PSRule.Rules.Azure
{
internal static class DictionaryExtensions
{
[DebuggerStepThrough]
public static bool TryPopValue(this IDictionary<string, object> dictionary, string key, out object value)
{
return dictionary.TryGetValue(key, out value) && dictionary.Remove(key);
}

[DebuggerStepThrough]
public static bool TryPopValue<T>(this IDictionary<string, object> dictionary, string key, out T value)
{
value = default;
if (dictionary.TryGetValue(key, out object v) && dictionary.Remove(key) && v is T result)
{
value = result;
return true;
}
return false;
}

[DebuggerStepThrough]
public static bool TryPopBool(this IDictionary<string, object> dictionary, string key, out bool value)
{
value = default;
return dictionary.TryGetValue(key, out object v) && dictionary.Remove(key) && bool.TryParse(v.ToString(), out value);
}

public static bool TryGetBool(this IDictionary<string, object> dictionary, string key, out bool? value)
{
value = null;
if (!dictionary.TryGetValue(key, out object o))
return false;

if (o is bool bvalue || (o is string svalue && bool.TryParse(svalue, out bvalue)))
{
value = bvalue;
return true;
}
return false;
}

[DebuggerStepThrough]
public static void AddUnique(this IDictionary<string, object> dictionary, IEnumerable<KeyValuePair<string, object>> values)
{
foreach (var kv in values)
if (!dictionary.ContainsKey(kv.Key))
dictionary.Add(kv.Key, kv.Value);
}
}
}
Loading

0 comments on commit dc2cccc

Please sign in to comment.