зеркало из
1
0
Форкнуть 0
- Added APIM rules #342 #343 #344 #345 #346
- Fix path ordering in unit tests
This commit is contained in:
Bernie White 2020-04-12 15:02:39 +10:00 коммит произвёл GitHub
Родитель 5eae1062a9
Коммит 063efa1862
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
15 изменённых файлов: 901 добавлений и 30 удалений

Просмотреть файл

@ -2,6 +2,14 @@
## Unreleased
- New rules:
- API Management:
- Check API Management products require a subscription. [#342](https://github.com/Microsoft/PSRule.Rules.Azure/issues/342)
- Check API Management products require approval. [#343](https://github.com/Microsoft/PSRule.Rules.Azure/issues/343)
- Check API Management sample products have been removed. [#344](https://github.com/Microsoft/PSRule.Rules.Azure/issues/344)
- Check API Management uses a managed identity. [#345](https://github.com/Microsoft/PSRule.Rules.Azure/issues/345)
- Check API Management certificates are not expired. [#346](https://github.com/Microsoft/PSRule.Rules.Azure/issues/346)
## v0.10.1
What's changed since v0.10.0:

Просмотреть файл

@ -0,0 +1,37 @@
---
severity: Important
category: Reliability
resource: API Management
online version: https://github.com/Microsoft/PSRule.Rules.Azure/blob/master/docs/rules/en/Azure.APIM.CertificateExpiry.md
---
# API Management uses current certificates
## SYNOPSIS
Renew certificates used for custom domain bindings.
## DESCRIPTION
When custom domains are configured within an API Management service.
A certificate must be assigned to allow traffic to be transmitted using TLS.
Each certificate has an expiry date, after which the certificate is not valid.
After expiry, client connections to the API Management service will reject the certificate.
## RECOMMENDATION
Consider renewing certificates before expiry to prevent service issues.
## NOTES
By default, this rule fails when certificates have less than 30 days remaining before expiry.
To configure this rule:
- Override the Azure_MinimumCertificateLifetime configuration value with the minimum number of days until expiry that should pass.
## LINKS
- [Configure a custom domain name](https://docs.microsoft.com/en-us/azure/api-management/configure-custom-domain#use-the-azure-portal-to-set-a-custom-domain-name)
- [Azure template reference](https://docs.microsoft.com/en-us/azure/templates/microsoft.apimanagement/2019-12-01/service#hostnameconfiguration-object)

Просмотреть файл

@ -0,0 +1,28 @@
---
severity: Important
category: Security configuration
resource: API Management
online version: https://github.com/Microsoft/PSRule.Rules.Azure/blob/master/docs/rules/en/Azure.APIM.ManagedIdentity.md
---
# API Management uses a managed identity
## SYNOPSIS
Use managed identities to access Azure resources.
## DESCRIPTION
API Management must authenticate to access Azure resources such as Key Vault.
Use Key Vault to store certificates and secrets used within API Management.
## RECOMMENDATION
Consider configuring a managed identity for each API Management instance.
Also consider using managed identities to authenticate to related Azure services.
## LINKS
- [Use managed identities in Azure API Management](https://docs.microsoft.com/en-us/azure/api-management/api-management-howto-use-managed-service-identity)
- [Authenticate with managed identity](https://docs.microsoft.com/en-us/azure/api-management/api-management-authentication-policies#ManagedIdentity)
- [Azure template reference](https://docs.microsoft.com/en-us/azure/templates/microsoft.apimanagement/2019-12-01/service#ApiManagementServiceIdentity)

Просмотреть файл

@ -0,0 +1,28 @@
---
severity: Important
category: Security configuration
resource: API Management
online version: https://github.com/Microsoft/PSRule.Rules.Azure/blob/master/docs/rules/en/Azure.APIM.ProductApproval.md
---
# Require approval for products
## SYNOPSIS
Configure products to require approval.
## DESCRIPTION
When publishing APIs through Azure API Management (APIM), APIs are assigned to products.
Access to use an API is delegated through a product.
When products do not require approval, users can create a subscription for a product without approval.
## RECOMMENDATION
Consider configuring all API Management products to require approval.
## LINKS
- [Create and publish a product](https://docs.microsoft.com/en-us/azure/api-management/api-management-howto-add-products)
- [Azure template reference](https://docs.microsoft.com/en-us/azure/templates/microsoft.apimanagement/2019-12-01/service/products)

Просмотреть файл

@ -0,0 +1,29 @@
---
severity: Important
category: Security configuration
resource: API Management
online version: https://github.com/Microsoft/PSRule.Rules.Azure/blob/master/docs/rules/en/Azure.APIM.ProductSubscription.md
---
# Require a subscription for products
## SYNOPSIS
Configure products to require a subscription.
## DESCRIPTION
When publishing APIs through Azure API Management (APIM), APIs can be secured using subscription keys.
Client applications that consume published APIs must subscribe before making calls to those APIs.
When combined with policies, subscriptions allow controls such as throttling to be implemented.
## RECOMMENDATION
Consider configuring all API Management products to require a subscription.
## LINKS
- [Subscriptions in Azure API Management](https://docs.microsoft.com/en-us/azure/api-management/api-management-subscriptions)
- [Create and publish a product](https://docs.microsoft.com/en-us/azure/api-management/api-management-howto-add-products)
- [Azure template reference](https://docs.microsoft.com/en-us/azure/templates/microsoft.apimanagement/2019-12-01/service/products)

Просмотреть файл

@ -0,0 +1,25 @@
---
severity: Awareness
category: Security configuration
resource: API Management
online version: https://github.com/Microsoft/PSRule.Rules.Azure/blob/master/docs/rules/en/Azure.APIM.SampleProducts.md
---
# Remove default products
## SYNOPSIS
Remove starter and unlimited sample products.
## DESCRIPTION
API Management includes two sample products _Starter_ and _Unlimited_.
Accidentally adding APIs to these sample products may expose APIs more than intended.
## RECOMMENDATION
Consider removing starter and unlimited sample products from API Management.
## LINKS
- [Create and publish a product](https://docs.microsoft.com/en-us/azure/api-management/api-management-howto-add-products)

Просмотреть файл

@ -63,6 +63,7 @@ Name | Synopsis | Severity
Name | Synopsis | Severity
---- | -------- | --------
[Azure.AKS.MinNodeCount](Azure.AKS.MinNodeCount.md) | AKS clusters should have minimum number of nodes for failover and updates. | Important
[Azure.APIM.CertificateExpiry](Azure.APIM.CertificateExpiry.md) | Renew certificates used for custom domain bindings. | Important
[Azure.AppGw.MinInstance](Azure.AppGw.MinInstance.md) | Application Gateways should use a minimum of two instances. | Important
[Azure.AppService.PlanInstanceCount](Azure.AppService.PlanInstanceCount.md) | Use an App Service Plan with at least two (2) instances. | Single point of failure
[Azure.Monitor.ServiceHealth](Azure.Monitor.ServiceHealth.md) | Configure Service Health alerts to notify administrators. | Important
@ -106,7 +107,11 @@ Name | Synopsis | Severity
[Azure.APIM.EncryptValues](Azure.APIM.EncryptValues.md) | API Management named values should be encrypted. | Important
[Azure.APIM.HTTPBackend](Azure.APIM.HTTPBackend.md) | Use HTTPS for communication to backend services. | Critical
[Azure.APIM.HTTPEndpoint](Azure.APIM.HTTPEndpoint.md) | Enforce HTTPS for communication to API clients. | Important
[Azure.APIM.ManagedIdentity](Azure.APIM.ManagedIdentity.md) | Use managed identities to access Azure resources. | Important
[Azure.APIM.ProductApproval](Azure.APIM.ProductApproval.md) | Configure products to require approval. | Important
[Azure.APIM.ProductSubscription](Azure.APIM.ProductSubscription.md) | Configure products to require a subscription. | Important
[Azure.APIM.Protocols](Azure.APIM.Protocols.md) | API Management should only accept a minimum of TLS 1.2. | Important
[Azure.APIM.SampleProducts](Azure.APIM.SampleProducts.md) | Remove starter and unlimited sample products. | Awareness
[Azure.AppGw.OWASP](Azure.AppGw.OWASP.md) | Application Gateway Web Application Firewall (WAF) should use OWASP 3.x rules. | Important
[Azure.AppGw.Prevention](Azure.AppGw.Prevention.md) | Internet exposed Application Gateways should use prevention mode to protect backend resources. | Critical
[Azure.AppGw.SSLPolicy](Azure.AppGw.SSLPolicy.md) | Application Gateway should only accept a minimum of TLS 1.2. | Critical

Просмотреть файл

@ -196,8 +196,8 @@ task PSScriptAnalyzer NuGet, {
# Synopsis: Install PSRule
task PSRule NuGet, {
if ($Null -eq (Get-InstalledModule -Name PSRule -MinimumVersion 0.15.0 -ErrorAction Ignore)) {
Install-Module -Name PSRule -Repository PSGallery -MinimumVersion 0.15.0 -Scope CurrentUser -Force;
if ($Null -eq (Get-InstalledModule -Name PSRule -MinimumVersion 0.16.0 -ErrorAction Ignore)) {
Install-Module -Name PSRule -Repository PSGallery -MinimumVersion 0.16.0 -Scope CurrentUser -Force;
}
Import-Module -Name PSRule -Verbose:$False;
}
@ -289,14 +289,15 @@ task Rules PSRule, {
$assertParams = @{
Path = './.ps-rule/'
Style = $AssertStyle
OutputFormat = 'NUnit3';
OutputFormat = 'NUnit3'
ErrorAction = 'Stop'
}
Import-Module (Join-Path -Path $PWD -ChildPath out/modules/PSRule.Rules.Azure) -Force;
Get-RepoRuleData -Path $PWD |
Assert-PSRule @assertParams -OutputPath reports/ps-rule-file.xml -ErrorAction Stop;
Assert-PSRule @assertParams -OutputPath reports/ps-rule-file.xml;
$rules = Get-PSRule -Module PSRule.Rules.Azure -Culture 'en-US';
$rules | Assert-PSRule @assertParams -OutputPath reports/ps-rule-file2.xml -ErrorAction Stop;
$rules = Get-PSRule -Module PSRule.Rules.Azure;
$rules | Assert-PSRule @assertParams -OutputPath reports/ps-rule-file2.xml;
}
# Synopsis: Run script analyzer

Просмотреть файл

@ -4,3 +4,7 @@ binding:
targetName:
- RuleName
- FullName
output:
culture:
- en-US

Просмотреть файл

@ -473,7 +473,7 @@ function GetSubResource {
Get-AzResource @getParams -ExpandProperties;
}
catch {
Write-Verbose -Message "Failed to read: $ResourceType";
Write-Warning -Message "Failed to read: $ResourceType";
}
}
}
@ -489,12 +489,28 @@ function VisitAPIManagement {
)
process {
$resources = @();
$resources += GetSubResource @PSBoundParameters -ResourceType 'Microsoft.ApiManagement/service/apis' -ApiVersion '2019-01-01';
$resources += GetSubResource @PSBoundParameters -ResourceType 'Microsoft.ApiManagement/service/backends' -ApiVersion '2019-01-01';
$resources += GetSubResource @PSBoundParameters -ResourceType 'Microsoft.ApiManagement/service/properties' -ApiVersion '2019-01-01' | ForEach-Object {
$_.properties.value = '*** MASKED ***';
$_;
$apis += GetSubResource @PSBoundParameters -ResourceType 'Microsoft.ApiManagement/service/apis' -ApiVersion '2019-12-01';
foreach ($api in $apis) {
$resources += $api;
$apiParams = @{
Name = "$($Resource.Name)/$($api.Name)"
ResourceType = 'Microsoft.ApiManagement/service/apis/policies'
ResourceGroupName = $Resource.ResourceGroupName
DefaultProfile = $Context
ApiVersion = '2019-12-01'
};
$resources += Get-AzResource @apiParams;
}
$resources += GetSubResource @PSBoundParameters -ResourceType 'Microsoft.ApiManagement/service/backends' -ApiVersion '2019-12-01';
$resources += GetSubResource @PSBoundParameters -ResourceType 'Microsoft.ApiManagement/service/products' -ApiVersion '2019-12-01';
$resources += GetSubResource @PSBoundParameters -ResourceType 'Microsoft.ApiManagement/service/policies' -ApiVersion '2019-12-01';
$resources += GetSubResource @PSBoundParameters -ResourceType 'Microsoft.ApiManagement/service/identityProviders' -ApiVersion '2019-12-01';
$resources += GetSubResource @PSBoundParameters -ResourceType 'Microsoft.ApiManagement/service/diagnostics' -ApiVersion '2019-12-01';
$resources += GetSubResource @PSBoundParameters -ResourceType 'Microsoft.ApiManagement/service/loggers' -ApiVersion '2019-12-01';
$resources += GetSubResource @PSBoundParameters -ResourceType 'Microsoft.ApiManagement/service/certificates' -ApiVersion '2019-12-01';
$resources += GetSubResource @PSBoundParameters -ResourceType 'Microsoft.ApiManagement/service/namedValues' -ApiVersion '2019-12-01';
$resources += GetSubResource @PSBoundParameters -ResourceType 'Microsoft.ApiManagement/service/portalsettings' -ApiVersion '2019-12-01';
$Resource | Add-Member -MemberType NoteProperty -Name resources -Value $resources -PassThru;
}
}

Просмотреть файл

@ -20,4 +20,7 @@
SecurityCenterNotConfigured = "Security Center are not configured."
LateralTraversalNotRestricted = "A rule to limit lateral traversal was not found."
AllInboundRestricted = "The first inbound rule denies traffic from all sources."
APIMProductSubscription = "The product '{0}' does not require a subscription to use."
APIMProductApproval = "The product '{0}' does not require approval."
APIMCertificateExpiry = "The certificate for host name '{0}' expires or expired on '{1}'."
}

Просмотреть файл

@ -68,9 +68,9 @@ Rule 'Azure.APIM.HTTPBackend' -Type 'Microsoft.ApiManagement/service', 'Microsof
}
# Synopsis: Encrypt all named values
Rule 'Azure.APIM.EncryptValues' -Type 'Microsoft.ApiManagement/service', 'Microsoft.ApiManagement/service/properties' -Tag @{ release = 'GA' } {
Rule 'Azure.APIM.EncryptValues' -Type 'Microsoft.ApiManagement/service', 'Microsoft.ApiManagement/service/properties', 'Microsoft.ApiManagement/service/namedValues' -Tag @{ release = 'GA' } {
if ($PSRule.TargetType -eq 'Microsoft.ApiManagement/service') {
$properties = @(GetSubResources -ResourceType 'Microsoft.ApiManagement/service/properties')
$properties = @(GetSubResources -ResourceType 'Microsoft.ApiManagement/service/properties', 'Microsoft.ApiManagement/service/namedValues')
if ($properties.Length -eq 0) {
$True;
}
@ -78,7 +78,76 @@ Rule 'Azure.APIM.EncryptValues' -Type 'Microsoft.ApiManagement/service', 'Micros
$Assert.HasFieldValue($prop, 'properties.secret', $True)
}
}
elseif ($PSRule.TargetType -eq 'Microsoft.ApiManagement/service/properties') {
elseif ($PSRule.TargetType -in 'Microsoft.ApiManagement/service/properties', 'Microsoft.ApiManagement/service/namedValues') {
$Assert.HasFieldValue($TargetObject, 'properties.secret', $True)
}
}
# Synopsis: Require subscription for products
Rule 'Azure.APIM.ProductSubscription' -Type 'Microsoft.ApiManagement/service', 'Microsoft.ApiManagement/service/products' -Tag @{ release = 'GA' } {
$products = @($TargetObject);
if ($PSRule.TargetType -eq 'Microsoft.ApiManagement/service') {
$products = @(GetSubResources -ResourceType 'Microsoft.ApiManagement/service/products');
if ($products.Length -eq 0) {
$True;
}
}
foreach ($product in $products) {
$Assert.
HasFieldValue($product, 'Properties.subscriptionRequired', $True).
WithReason(($LocalizedData.APIMProductSubscription -f $product.Name), $True);
}
}
# Synopsis: Require approval for products
Rule 'Azure.APIM.ProductApproval' -Type 'Microsoft.ApiManagement/service', 'Microsoft.ApiManagement/service/products' -Tag @{ release = 'GA' } {
$products = @($TargetObject);
if ($PSRule.TargetType -eq 'Microsoft.ApiManagement/service') {
$products = @(GetSubResources -ResourceType 'Microsoft.ApiManagement/service/products');
if ($products.Length -eq 0) {
$True;
}
}
foreach ($product in $products) {
$Assert.
HasFieldValue($product, 'Properties.approvalRequired', $True).
WithReason(($LocalizedData.APIMProductApproval -f $product.Name), $True);
}
}
# Synopsis: Remove sample products
Rule 'Azure.APIM.SampleProducts' -Type 'Microsoft.ApiManagement/service', 'Microsoft.ApiManagement/service/products' -Tag @{ release = 'GA' } {
$products = @($TargetObject);
if ($PSRule.TargetType -eq 'Microsoft.ApiManagement/service') {
$products = @(GetSubResources -ResourceType 'Microsoft.ApiManagement/service/products');
if ($products.Length -eq 0) {
$True;
}
}
foreach ($product in $products) {
$product | Within 'Name' -Not 'unlimited', 'starter'
}
}
# Synopsis: Provision a managed identity
Rule 'Azure.APIM.ManagedIdentity' -Type 'Microsoft.ApiManagement/service' -Tag @{ release = 'GA' } {
Within 'Identity.Type' 'SystemAssigned', 'UserAssigned'
}
# Synopsis: Renew expired certificates
Rule 'Azure.APIM.CertificateExpiry' -Type 'Microsoft.ApiManagement/service' -Tag @{ release = 'GA' } {
$configurations = @($TargetObject.Properties.hostnameConfigurations | Where-Object {
$Null -ne $_.certificate
})
if ($configurations.Length -eq 0) {
$True;
}
else {
foreach ($configuration in $configurations) {
$remaining = ($configuration.certificate.expiry - [DateTime]::Now).Days;
$Assert.
GreaterOrEqual($remaining, '.', $Configuration.Azure_MinimumCertificateLifetime).
WithReason(($LocalizedData.APIMCertificateExpiry -f $configuration.hostName, $configuration.certificate.expiry.ToString('yyyy/MM/dd')), $True);
}
}
} -Configure @{ Azure_MinimumCertificateLifetime = 30 }

Просмотреть файл

@ -46,8 +46,8 @@ Describe 'Azure.APIM' {
# Pass
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' });
$ruleResult | Should -Not -BeNullOrEmpty;
$ruleResult.Length | Should -Be 1;
$ruleResult.TargetName | Should -Be 'apim-B';
$ruleResult.Length | Should -Be 2;
$ruleResult.TargetName | Should -BeIn 'apim-B', 'apim-C';
}
It 'Azure.APIM.HTTPEndpoint' {
@ -62,8 +62,8 @@ Describe 'Azure.APIM' {
# Pass
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' });
$ruleResult | Should -Not -BeNullOrEmpty;
$ruleResult.Length | Should -Be 1;
$ruleResult.TargetName | Should -Be 'apim-B';
$ruleResult.Length | Should -Be 2;
$ruleResult.TargetName | Should -BeIn 'apim-B', 'apim-C';
}
It 'Azure.APIM.HTTPBackend' {
@ -79,13 +79,45 @@ Describe 'Azure.APIM' {
# Pass
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' });
$ruleResult | Should -Not -BeNullOrEmpty;
$ruleResult.Length | Should -Be 1;
$ruleResult.TargetName | Should -Be 'apim-B';
$ruleResult.Length | Should -Be 2;
$ruleResult.TargetName | Should -BeIn 'apim-B', 'apim-C';
}
It 'Azure.APIM.EncryptValues' {
$filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.APIM.EncryptValues' };
# Fail
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' });
$ruleResult | Should -Not -BeNullOrEmpty;
$ruleResult.Length | Should -Be 2;
$ruleResult.TargetName | Should -BeIn 'apim-A', 'apim-C';
# Pass
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' });
$ruleResult | Should -Not -BeNullOrEmpty;
$ruleResult.Length | Should -Be 1;
$ruleResult.TargetName | Should -Be 'apim-B';
}
It 'Azure.APIM.ProductSubscription' {
$filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.APIM.ProductSubscription' };
# Fail
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' });
$ruleResult | Should -Not -BeNullOrEmpty;
$ruleResult.Length | Should -Be 2;
$ruleResult.TargetName | Should -BeIn 'apim-B', 'apim-C';
# Pass
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' });
$ruleResult | Should -Not -BeNullOrEmpty;
$ruleResult.Length | Should -Be 1;
$ruleResult.TargetName | Should -Be 'apim-A';
}
It 'Azure.APIM.ProductApproval' {
$filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.APIM.ProductApproval' };
# Fail
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' });
$ruleResult | Should -Not -BeNullOrEmpty;
@ -95,8 +127,56 @@ Describe 'Azure.APIM' {
# Pass
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' });
$ruleResult | Should -Not -BeNullOrEmpty;
$ruleResult.Length | Should -Be 2;
$ruleResult.TargetName | Should -BeIn 'apim-B', 'apim-C';
}
It 'Azure.APIM.SampleProducts' {
$filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.APIM.SampleProducts' };
# Fail
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' });
$ruleResult | Should -Not -BeNullOrEmpty;
$ruleResult.Length | Should -Be 1;
$ruleResult.TargetName | Should -Be 'apim-A';
# Pass
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' });
$ruleResult | Should -Not -BeNullOrEmpty;
$ruleResult.Length | Should -Be 2;
$ruleResult.TargetName | Should -BeIn 'apim-B', 'apim-C';
}
It 'Azure.APIM.ManagedIdentity' {
$filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.APIM.ManagedIdentity' };
# Fail
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' });
$ruleResult | Should -Not -BeNullOrEmpty;
$ruleResult.Length | Should -Be 1;
$ruleResult.TargetName | Should -Be 'apim-B';
# Pass
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' });
$ruleResult | Should -Not -BeNullOrEmpty;
$ruleResult.Length | Should -Be 2;
$ruleResult.TargetName | Should -BeIn 'apim-A', 'apim-C';
}
It 'Azure.APIM.CertificateExpiry' {
$filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.APIM.CertificateExpiry' };
# Fail
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' });
$ruleResult | Should -Not -BeNullOrEmpty;
$ruleResult.Length | Should -Be 1;
$ruleResult.TargetName | Should -Be 'apim-C';
# Pass
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' });
$ruleResult | Should -Not -BeNullOrEmpty;
$ruleResult.Length | Should -Be 2;
$ruleResult.TargetName | Should -BeIn 'apim-B', 'apim-A';
}
}
}

Просмотреть файл

@ -4,6 +4,7 @@
using PSRule.Rules.Azure.Pipeline;
using System;
using System.IO;
using System.Linq;
using Xunit;
namespace PSRule.Rules.Azure
@ -28,14 +29,14 @@ namespace PSRule.Rules.Azure
builder.Add(GetSourcePath("*Parameters*.json"));
var actual3 = builder.Build();
Assert.Equal(2, actual3.Length);
Assert.Equal(GetSourcePath("Resources.Parameters.json"), actual3[0].FullName);
Assert.Equal(GetSourcePath("Resources.Parameters2.json"), actual3[1].FullName);
Assert.NotNull(actual3.SingleOrDefault(f => f.FullName == GetSourcePath("Resources.Parameters.json")));
Assert.NotNull(actual3.SingleOrDefault(f => f.FullName == GetSourcePath("Resources.Parameters2.json")));
builder.Add(GetSourcePath("*Parameters?.json"));
var actual4 = builder.Build();
Assert.Equal(2, actual4.Length);
Assert.Equal(GetSourcePath("Resources.Parameters.json"), actual4[0].FullName);
Assert.Equal(GetSourcePath("Resources.Parameters2.json"), actual4[1].FullName);
Assert.NotNull(actual4.SingleOrDefault(f => f.FullName == GetSourcePath("Resources.Parameters.json")));
Assert.NotNull(actual4.SingleOrDefault(f => f.FullName == GetSourcePath("Resources.Parameters2.json")));
}
private static string GetSourcePath(string fileName)

Просмотреть файл

@ -2,7 +2,12 @@
{
"ResourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-test/providers/Microsoft.ApiManagement/service/apim-A",
"Id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-test/providers/Microsoft.ApiManagement/service/apim-A",
"Identity": null,
"Identity": {
"PrincipalId": "00000000-0000-0000-0000-000000000000",
"TenantId": "00000000-0000-0000-0000-000000000000",
"Type": "SystemAssigned",
"UserAssignedIdentities": null
},
"Kind": null,
"Location": "region",
"ManagedBy": null,
@ -30,7 +35,35 @@
"certificatePassword": null,
"negotiateClientCertificate": false,
"certificate": null,
"defaultSslBinding": false
},
{
"type": "Proxy",
"hostName": "api.contoso.com",
"encodedCertificate": null,
"keyVaultId": "https://vault-A.vault.azure.net/secrets/apicert",
"certificatePassword": null,
"negotiateClientCertificate": false,
"certificate": {
"expiry": "2099-01-01T12:00:00+00:00",
"thumbprint": "0000000000000000000000000000000000000000",
"subject": "CN=api.contoso.com, OU=A, O=O, L=L, S=S, C=C"
},
"defaultSslBinding": true
},
{
"type": "Management",
"hostName": "management.contoso.com",
"encodedCertificate": null,
"keyVaultId": "https://vault-A.vault.azure.net/secrets/managementcert",
"certificatePassword": null,
"negotiateClientCertificate": false,
"certificate": {
"expiry": "2099-01-01T12:00:00+00:00",
"thumbprint": "0000000000000000000000000000000000000000",
"subject": "CN=management.contoso.com, OU=A, O=O, L=L, S=S, C=C"
},
"defaultSslBinding": false
}
],
"publicIPAddresses": [
@ -252,6 +285,116 @@
"Sku": null,
"Tags": null,
"SubscriptionId": "00000000-0000-0000-0000-000000000000"
},
{
"ResourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-test/providers/Microsoft.ApiManagement/service/apim-A/products/product-A",
"Id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-test/providers/Microsoft.ApiManagement/service/apim-A/products/product-A",
"Identity": null,
"Kind": null,
"Location": null,
"ManagedBy": null,
"ResourceName": "product-A",
"Name": "product-A",
"ExtensionResourceName": null,
"Properties": {
"displayName": "product-A",
"description": "An example product for unit tests.",
"terms": null,
"subscriptionRequired": true,
"approvalRequired": true,
"subscriptionsLimit": null,
"state": "published"
},
"ResourceGroupName": "rg-test",
"Type": "Microsoft.ApiManagement/service/products",
"ResourceType": "Microsoft.ApiManagement/service/products",
"ExtensionResourceType": null,
"Sku": null,
"Tags": null,
"SubscriptionId": "00000000-0000-0000-0000-000000000000"
},
{
"ResourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-test/providers/Microsoft.ApiManagement/service/apim-A/products/product-B",
"Id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-test/providers/Microsoft.ApiManagement/service/apim-A/products/product-B",
"Identity": null,
"Kind": null,
"Location": null,
"ManagedBy": null,
"ResourceName": "product-B",
"Name": "product-B",
"ExtensionResourceName": null,
"Properties": {
"displayName": "product-B",
"description": "An example product for unit tests.",
"terms": null,
"subscriptionRequired": true,
"approvalRequired": true,
"subscriptionsLimit": null,
"state": "notPublished"
},
"ResourceGroupName": "rg-test",
"Type": "Microsoft.ApiManagement/service/products",
"ResourceType": "Microsoft.ApiManagement/service/products",
"ExtensionResourceType": null,
"Sku": null,
"Tags": null,
"SubscriptionId": "00000000-0000-0000-0000-000000000000"
},
{
"ResourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-test/providers/Microsoft.ApiManagement/service/apim-A/products/starter",
"Id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-test/providers/Microsoft.ApiManagement/service/apim-A/products/starter",
"Identity": null,
"Kind": null,
"Location": null,
"ManagedBy": null,
"ResourceName": "starter",
"Name": "starter",
"ExtensionResourceName": null,
"ParentResource": null,
"Plan": null,
"Properties": {
"displayName": "Starter",
"description": "Subscribers will be able to run 5 calls/minute up to a maximum of 100 calls/week.",
"terms": "",
"subscriptionRequired": true,
"approvalRequired": false,
"subscriptionsLimit": 1,
"state": "notPublished"
},
"ResourceGroupName": "rg-test",
"Type": "Microsoft.ApiManagement/service/products",
"ResourceType": "Microsoft.ApiManagement/service/products",
"ExtensionResourceType": null,
"Sku": null,
"Tags": null,
"SubscriptionId": "00000000-0000-0000-0000-000000000000"
},
{
"ResourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-test/providers/Microsoft.ApiManagement/service/apim-A/products/unlimited",
"Id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-test/providers/Microsoft.ApiManagement/service/apim-A/products/unlimited",
"Identity": null,
"Kind": null,
"Location": null,
"ManagedBy": null,
"ResourceName": "unlimited",
"Name": "unlimited",
"ExtensionResourceName": null,
"Properties": {
"displayName": "Unlimited",
"description": "Subscribers have completely unlimited access to the API. Administrator approval is required.",
"terms": null,
"subscriptionRequired": true,
"approvalRequired": true,
"subscriptionsLimit": 1,
"state": "notPublished"
},
"ResourceGroupName": "rg-test",
"Type": "Microsoft.ApiManagement/service/products",
"ResourceType": "Microsoft.ApiManagement/service/products",
"ExtensionResourceType": null,
"Sku": null,
"Tags": null,
"SubscriptionId": "00000000-0000-0000-0000-000000000000"
}
]
},
@ -401,6 +544,60 @@
"ChangedTime": null,
"ETag": null
},
{
"ResourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-test/providers/Microsoft.ApiManagement/service/apim-B/products/product-A",
"Id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-test/providers/Microsoft.ApiManagement/service/apim-B/products/product-A",
"Identity": null,
"Kind": null,
"Location": null,
"ManagedBy": null,
"ResourceName": "product-A",
"Name": "product-A",
"ExtensionResourceName": null,
"Properties": {
"displayName": "product-A",
"description": "An example product for unit tests.",
"terms": null,
"subscriptionRequired": true,
"approvalRequired": true,
"subscriptionsLimit": null,
"state": "published"
},
"ResourceGroupName": "rg-test",
"Type": "Microsoft.ApiManagement/service/products",
"ResourceType": "Microsoft.ApiManagement/service/products",
"ExtensionResourceType": null,
"Sku": null,
"Tags": null,
"SubscriptionId": "00000000-0000-0000-0000-000000000000"
},
{
"ResourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-test/providers/Microsoft.ApiManagement/service/apim-B/products/product-B",
"Id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-test/providers/Microsoft.ApiManagement/service/apim-B/products/product-B",
"Identity": null,
"Kind": null,
"Location": null,
"ManagedBy": null,
"ResourceName": "product-B",
"Name": "product-B",
"ExtensionResourceName": null,
"Properties": {
"displayName": "product-B",
"description": "An example product for unit tests.",
"terms": null,
"subscriptionRequired": false,
"approvalRequired": true,
"subscriptionsLimit": null,
"state": "notPublished"
},
"ResourceGroupName": "rg-test",
"Type": "Microsoft.ApiManagement/service/products",
"ResourceType": "Microsoft.ApiManagement/service/products",
"ExtensionResourceType": null,
"Sku": null,
"Tags": null,
"SubscriptionId": "00000000-0000-0000-0000-000000000000"
},
{
"ResourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-test/providers/Microsoft.ApiManagement/service/apim-B/backends/endpoint-A",
"Id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-test/providers/Microsoft.ApiManagement/service/apim-B/backends/endpoint-A",
@ -483,8 +680,8 @@
"SubscriptionId": "00000000-0000-0000-0000-000000000000"
},
{
"ResourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-test/providers/Microsoft.ApiManagement/service/apim-B/properties/property-B",
"Id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-test/providers/Microsoft.ApiManagement/service/apim-B/properties/property-B",
"ResourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-test/providers/Microsoft.ApiManagement/service/apim-B/namedValues/property-B",
"Id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-test/providers/Microsoft.ApiManagement/service/apim-B/namedValues/property-B",
"Identity": null,
"Kind": null,
"Location": null,
@ -501,8 +698,348 @@
"secret": true
},
"ResourceGroupName": "rg-test",
"Type": "Microsoft.ApiManagement/service/properties",
"ResourceType": "Microsoft.ApiManagement/service/properties",
"Type": "Microsoft.ApiManagement/service/namedValues",
"ResourceType": "Microsoft.ApiManagement/service/namedValues",
"ExtensionResourceType": null,
"Sku": null,
"Tags": null,
"SubscriptionId": "00000000-0000-0000-0000-000000000000"
}
]
},
{
"ResourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-test/providers/Microsoft.ApiManagement/service/apim-C",
"Id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-test/providers/Microsoft.ApiManagement/service/apim-C",
"Identity": {
"PrincipalId": "00000000-0000-0000-0000-000000000000",
"TenantId": "00000000-0000-0000-0000-000000000000",
"Type": "UserAssigned",
"UserAssignedIdentities": null
},
"Kind": null,
"Location": "region",
"ManagedBy": null,
"ResourceName": "apim-C",
"Name": "apim-C",
"Plan": null,
"Properties": {
"publisherEmail": "email",
"publisherName": "n/a",
"notificationSenderEmail": "apimgmt-noreply@mail.windowsazure.com",
"provisioningState": "Succeeded",
"targetProvisioningState": "",
"gatewayUrl": "https://apim-C.azure-api.net",
"gatewayRegionalUrl": "https://apim-C-region-01.regional.azure-api.net",
"portalUrl": "https://apim-C.portal.azure-api.net",
"developerPortalUrl": "https://apim-C.developer.azure-api.net",
"managementApiUrl": "https://apim-C.management.azure-api.net",
"scmUrl": "https://apim-C.scm.azure-api.net",
"hostnameConfigurations": [
{
"type": "Proxy",
"hostName": "apim-C.azure-api.net",
"encodedCertificate": null,
"keyVaultId": null,
"certificatePassword": null,
"negotiateClientCertificate": false,
"certificate": null,
"defaultSslBinding": false
},
{
"type": "Proxy",
"hostName": "api.contoso.com",
"encodedCertificate": null,
"keyVaultId": "https://vault-A.vault.azure.net/secrets/apicert",
"certificatePassword": null,
"negotiateClientCertificate": false,
"certificate": {
"expiry": "2020-01-01T12:00:00+00:00",
"thumbprint": "0000000000000000000000000000000000000000",
"subject": "CN=api.contoso.com, OU=A, O=O, L=L, S=S, C=C"
},
"defaultSslBinding": true
},
{
"type": "Management",
"hostName": "management.contoso.com",
"encodedCertificate": null,
"keyVaultId": "https://vault-A.vault.azure.net/secrets/managementcert",
"certificatePassword": null,
"negotiateClientCertificate": false,
"certificate": {
"expiry": "2099-01-01T12:00:00+00:00",
"thumbprint": "0000000000000000000000000000000000000000",
"subject": "CN=management.contoso.com, OU=A, O=O, L=L, S=S, C=C"
},
"defaultSslBinding": false
}
],
"publicIPAddresses": [
"0.0.0.0"
],
"privateIPAddresses": null,
"additionalLocations": null,
"virtualNetworkConfiguration": null,
"customProperties": {
"Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Protocols.Tls10": "False",
"Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Protocols.Tls11": "False",
"Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Protocols.Ssl30": "False",
"Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Ciphers.TripleDes168": "False",
"Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Backend.Protocols.Tls10": "False",
"Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Backend.Protocols.Tls11": "False",
"Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Backend.Protocols.Ssl30": "False",
"Microsoft.WindowsAzure.ApiManagement.Gateway.Protocols.Server.Http2": "False"
},
"virtualNetworkType": "None",
"certificates": null
},
"ResourceGroupName": "rg-test",
"Type": "Microsoft.ApiManagement/service",
"ResourceType": "Microsoft.ApiManagement/service",
"Sku": {
"Name": "Developer",
"Tier": null,
"Size": null,
"Family": null,
"Model": null,
"Capacity": 1
},
"Tags": {},
"SubscriptionId": "00000000-0000-0000-0000-000000000000",
"resources": [
{
"ResourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-test/providers/Microsoft.ApiManagement/service/apim-C/apis/api-A",
"Id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-test/providers/Microsoft.ApiManagement/service/apim-C/apis/api-A",
"Identity": null,
"Kind": null,
"Location": null,
"ManagedBy": null,
"ResourceName": "api-A",
"Name": "api-A",
"Plan": null,
"Properties": {
"displayName": "api-A",
"apiRevision": "1",
"description": "Azure Logic App.",
"serviceUrl": "https://endpoint-a.contoso.com",
"path": "api-a",
"protocols": [
"https"
],
"authenticationSettings": {
"oAuth2": null,
"openid": null
},
"subscriptionKeyParameterNames": {
"header": "Ocp-Apim-Subscription-Key",
"query": "subscription-key"
},
"isCurrent": true
},
"ResourceGroupName": "rg-test",
"Type": "Microsoft.ApiManagement/service/apis",
"ResourceType": "Microsoft.ApiManagement/service/apis",
"Sku": null,
"Tags": null,
"SubscriptionId": "00000000-0000-0000-0000-000000000000"
},
{
"ResourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-test/providers/Microsoft.ApiManagement/service/apim-C/apis/api-B",
"Id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-test/providers/Microsoft.ApiManagement/service/apim-C/apis/api-B",
"Identity": null,
"Kind": null,
"Location": null,
"ManagedBy": null,
"ResourceName": "api-B",
"Name": "api-B",
"ExtensionResourceName": null,
"ParentResource": null,
"Plan": null,
"Properties": {
"displayName": "api-B",
"apiRevision": "1",
"description": "",
"subscriptionRequired": false,
"serviceUrl": "https://endpoint-b.contoso.com",
"path": "api-b",
"protocols": [
"https"
],
"authenticationSettings": {
"oAuth2": null,
"openid": null
},
"subscriptionKeyParameterNames": {
"header": "Ocp-Apim-Subscription-Key",
"query": "subscription-key"
},
"isCurrent": true
},
"ResourceGroupName": "rg-test",
"Type": "Microsoft.ApiManagement/service/apis",
"ResourceType": "Microsoft.ApiManagement/service/apis",
"ExtensionResourceType": null,
"Sku": null,
"Tags": null,
"SubscriptionId": "00000000-0000-0000-0000-000000000000",
"CreatedTime": null,
"ChangedTime": null,
"ETag": null
},
{
"ResourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-test/providers/Microsoft.ApiManagement/service/apim-C/products/product-A",
"Id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-test/providers/Microsoft.ApiManagement/service/apim-C/products/product-A",
"Identity": null,
"Kind": null,
"Location": null,
"ManagedBy": null,
"ResourceName": "product-A",
"Name": "product-A",
"ExtensionResourceName": null,
"Properties": {
"displayName": "product-A",
"description": "An example product for unit tests.",
"terms": null,
"subscriptionRequired": true,
"approvalRequired": true,
"subscriptionsLimit": null,
"state": "published"
},
"ResourceGroupName": "rg-test",
"Type": "Microsoft.ApiManagement/service/products",
"ResourceType": "Microsoft.ApiManagement/service/products",
"ExtensionResourceType": null,
"Sku": null,
"Tags": null,
"SubscriptionId": "00000000-0000-0000-0000-000000000000"
},
{
"ResourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-test/providers/Microsoft.ApiManagement/service/apim-C/products/product-B",
"Id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-test/providers/Microsoft.ApiManagement/service/apim-C/products/product-B",
"Identity": null,
"Kind": null,
"Location": null,
"ManagedBy": null,
"ResourceName": "product-B",
"Name": "product-B",
"ExtensionResourceName": null,
"Properties": {
"displayName": "product-B",
"description": "An example product for unit tests.",
"terms": null,
"subscriptionRequired": false,
"approvalRequired": true,
"subscriptionsLimit": null,
"state": "notPublished"
},
"ResourceGroupName": "rg-test",
"Type": "Microsoft.ApiManagement/service/products",
"ResourceType": "Microsoft.ApiManagement/service/products",
"ExtensionResourceType": null,
"Sku": null,
"Tags": null,
"SubscriptionId": "00000000-0000-0000-0000-000000000000"
},
{
"ResourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-test/providers/Microsoft.ApiManagement/service/apim-C/backends/endpoint-A",
"Id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-test/providers/Microsoft.ApiManagement/service/apim-C/backends/endpoint-A",
"Identity": null,
"Kind": null,
"Location": null,
"ManagedBy": null,
"ResourceName": "endpoint-A",
"Name": "endpoint-A",
"Plan": null,
"Properties": {
"title": null,
"description": "endpoint-A",
"url": "https://endpoint-a.contoso.com",
"protocol": "http",
"resourceId": ""
},
"ResourceGroupName": "rg-test",
"Type": "Microsoft.ApiManagement/service/backends",
"ResourceType": "Microsoft.ApiManagement/service/backends",
"ExtensionResourceType": null,
"Sku": null,
"Tags": null,
"SubscriptionId": "00000000-0000-0000-0000-000000000000"
},
{
"ResourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-test/providers/Microsoft.ApiManagement/service/apim-C/backends/endpoint-B",
"Id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-test/providers/Microsoft.ApiManagement/service/apim-C/backends/endpoint-B",
"Identity": null,
"Kind": null,
"Location": null,
"ManagedBy": null,
"ResourceName": "endpoint-B",
"Name": "endpoint-B",
"ExtensionResourceName": null,
"ParentResource": null,
"Plan": null,
"Properties": {
"title": null,
"description": "endpoint-B",
"url": "https://endpoint-b.contoso.com",
"protocol": "http",
"resourceId": ""
},
"ResourceGroupName": "rg-test",
"Type": "Microsoft.ApiManagement/service/backends",
"ResourceType": "Microsoft.ApiManagement/service/backends",
"ExtensionResourceType": null,
"Sku": null,
"Tags": null,
"SubscriptionId": "00000000-0000-0000-0000-000000000000",
"CreatedTime": null,
"ChangedTime": null,
"ETag": null
},
{
"ResourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-test/providers/Microsoft.ApiManagement/service/apim-C/namedValues/property-A",
"Id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-test/providers/Microsoft.ApiManagement/service/apim-C/namedValues/property-A",
"Identity": null,
"Kind": null,
"Location": null,
"ManagedBy": null,
"ResourceName": "property-A",
"Name": "property-A",
"ExtensionResourceName": null,
"ParentResource": null,
"Plan": null,
"Properties": {
"displayName": "property-A",
"tags": [],
"secret": true
},
"ResourceGroupName": "rg-test",
"Type": "Microsoft.ApiManagement/service/namedValues",
"ResourceType": "Microsoft.ApiManagement/service/namedValues",
"ExtensionResourceType": null,
"Sku": null,
"Tags": null,
"SubscriptionId": "00000000-0000-0000-0000-000000000000"
},
{
"ResourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-test/providers/Microsoft.ApiManagement/service/apim-C/namedValues/property-B",
"Id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-test/providers/Microsoft.ApiManagement/service/apim-C/namedValues/property-B",
"Identity": null,
"Kind": null,
"Location": null,
"ManagedBy": null,
"ResourceName": "property-B",
"Name": "property-B",
"ExtensionResourceName": null,
"ParentResource": null,
"Plan": null,
"Properties": {
"displayName": "property-B",
"tags": null,
"secret": false
},
"ResourceGroupName": "rg-test",
"Type": "Microsoft.ApiManagement/service/namedValues",
"ResourceType": "Microsoft.ApiManagement/service/namedValues",
"ExtensionResourceType": null,
"Sku": null,
"Tags": null,