Skip to content
This repository has been archived by the owner on Feb 23, 2024. It is now read-only.

Commit

Permalink
Add possibility to parametrize API OAuth2 scope settings (#723)
Browse files Browse the repository at this point in the history
* Add parametrization possibility for api oauth2 scope

* Fix tests concurrency issue with mock. Add oauth2 scope parameter to master template

* Introduce ApiParameters variable for extractor, deprecate serviceUrlParameters

* Update documentation according to new api parameter

Co-authored-by: Farhad Alizada <[email protected]>
  • Loading branch information
f-alizada and Farhad Alizada authored May 27, 2022
1 parent 431081e commit 34f94ed
Show file tree
Hide file tree
Showing 17 changed files with 312 additions and 90 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// Licensed under the MIT License.
// --------------------------------------------------------------------------

using System.Collections.Generic;
using CommandLine;
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common.Constants;
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Extractor.Models;
Expand Down Expand Up @@ -60,9 +61,6 @@ public class ExtractorConsoleAppConfiguration
[Option(longName: "baseFileName", HelpText = "Specify base name of the template file")]
public string BaseFileName { get; set; }

// this is used only from json-file and --extractorConfig option, so no option possibility here
public ServiceUrlProperty[] ServiceUrlParameters { get; set; }

[Option(longName: "paramServiceUrl", HelpText = "Parameterize serviceUrl")]
public string ParamServiceUrl { get; set; }

Expand Down Expand Up @@ -98,5 +96,13 @@ public class ExtractorConsoleAppConfiguration

[Option(longName: "overrideProductGuids", HelpText = "Override product GUID identification to system generated")]
public string OverrideProductGuids { get; set; }

[Option(longName: "paramApiOauth2Scope", HelpText = "Parametrize API OAuth2 scope values")]
public string ParamApiOauth2Scope { get; set; }

/// <summary>
/// Api parameter properties for overriding Api OAuth2 scope or/and Service urloverride. Available via extractor-config file only.
/// </summary>
public Dictionary<string, ApiParameterProperty> ApiParameters { get; set; }
}
}
2 changes: 2 additions & 0 deletions src/ArmTemplates/Common/Constants/GlobalConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public static class ParameterNames
public const string LinkedTemplatesBaseUrl = "linkedTemplatesBaseUrl";
public const string NamedValueKeyVaultSecrets = "namedValueKeyVaultSecrets";
public const string BackendSettings = "backendSettings";
public const string ApiOauth2ScopeSettings = "apiOauth2ScopeSettings";
}

public static class ParameterPrefix
Expand All @@ -48,5 +49,6 @@ public static class ParameterPrefix
public const string Property = "Property";
public const string LogResourceId = "LogResourceId";
public const string Backend = "Backend";
public const string ApiOauth2Scope = "ApiOauth2Scope";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,6 @@ public TemplateParameterProperties(string metadataDescription, string type)
Description = metadataDescription,
};
this.Type = type;
}
}
}
}
27 changes: 21 additions & 6 deletions src/ArmTemplates/Common/Templates/Builders/TemplateBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ public TemplateBuilder GenerateTemplateWithPresetProperties(ExtractorParameters
=> this.GenerateTemplateWithApimServiceNameProperty()
.AddPolicyProperties(extractorParameters)
.AddParameterizedServiceUrlProperty(extractorParameters)
.AddParameterizedApiLoggerIdProperty(extractorParameters);
.AddParameterizedApiLoggerIdProperty(extractorParameters)
.AddParameterizedApiScopeProperty(extractorParameters);

public TemplateBuilder GenerateEmptyTemplate()
{
Expand All @@ -82,7 +83,7 @@ public TemplateBuilder AddPolicyProperties(ExtractorParameters extractorParamete
{
if (extractorParameters.PolicyXMLBaseUrl != null)
{
TemplateParameterProperties policyTemplateBaseUrlParameterProperties = new TemplateParameterProperties()
var policyTemplateBaseUrlParameterProperties = new TemplateParameterProperties()
{
Type = "string"
};
Expand All @@ -91,7 +92,7 @@ public TemplateBuilder AddPolicyProperties(ExtractorParameters extractorParamete

if (extractorParameters.PolicyXMLSasToken != null)
{
TemplateParameterProperties policyTemplateSasTokenParameterProperties = new TemplateParameterProperties()
var policyTemplateSasTokenParameterProperties = new TemplateParameterProperties()
{
Type = "string"
};
Expand All @@ -104,9 +105,9 @@ public TemplateBuilder AddPolicyProperties(ExtractorParameters extractorParamete

public TemplateBuilder AddParameterizedServiceUrlProperty(ExtractorParameters extractorParameters)
{
if (extractorParameters.ParameterizeServiceUrl || extractorParameters.ServiceUrlParameters != null && extractorParameters.ServiceUrlParameters.Length > 0)
if (extractorParameters.ParameterizeServiceUrl)
{
TemplateParameterProperties serviceUrlParamProperty = new TemplateParameterProperties()
var serviceUrlParamProperty = new TemplateParameterProperties()
{
Type = "object"
};
Expand All @@ -116,11 +117,25 @@ public TemplateBuilder AddParameterizedServiceUrlProperty(ExtractorParameters ex
return this;
}

public TemplateBuilder AddParameterizedApiScopeProperty(ExtractorParameters extractorParameters)
{
if (extractorParameters.ParametrizeApiOauth2Scope)
{
var apiScopeParameterProperty = new TemplateParameterProperties()
{
Type = "object"
};
this.template.Parameters.Add(ParameterNames.ApiOauth2ScopeSettings, apiScopeParameterProperty);
}

return this;
}

public TemplateBuilder AddParameterizedApiLoggerIdProperty(ExtractorParameters extractorParameters)
{
if (extractorParameters.ParameterizeApiLoggerId)
{
TemplateParameterProperties apiLoggerProperty = new TemplateParameterProperties()
var apiLoggerProperty = new TemplateParameterProperties()
{
Type = "object"
};
Expand Down
8 changes: 8 additions & 0 deletions src/ArmTemplates/Extractor/EntityExtractors/APIExtractor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,14 @@ void SetArmTemplateValuesToApiTemplateResource(ApiTemplateResource apiResource,
apiResource.Properties.ServiceUrl = $"[parameters('{ParameterNames.ServiceUrl}').{ParameterNamingHelper.GenerateValidParameterName(originalServiceApiName, ParameterPrefix.Api)}]";
}

if (extractorParameters.ParametrizeApiOauth2Scope)
{
if (apiResource.Properties.AuthenticationSettings?.OAuth2?.Scope is not null)
{
apiResource.Properties.AuthenticationSettings.OAuth2.Scope = $"[parameters('{ParameterNames.ApiOauth2ScopeSettings}').{ParameterNamingHelper.GenerateValidParameterName(originalServiceApiName, ParameterPrefix.ApiOauth2Scope)}]";
}
}

if (apiResource.Properties.ApiVersionSetId != null)
{
apiResource.DependsOn = Array.Empty<string>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ void SaveBackendApiParametersToCache()
}

var backendApiParameters = new BackendApiParameters();
var backendValidName = ParameterNamingHelper.GenerateValidParameterName(originalBackendName, ParameterPrefix.Diagnostic).ToLower();
var backendValidName = ParameterNamingHelper.GenerateValidParameterName(originalBackendName, ParameterPrefix.Backend).ToLower();

if (!string.IsNullOrEmpty(backendResource.Properties.ResourceId))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -262,10 +262,17 @@ static MasterTemplateResource CreateLinkedMasterTemplateResourceForApiTemplate(s
{
masterResourceTemplate.Properties.Parameters.Add(ParameterNames.ServiceUrl, new TemplateParameterProperties() { Value = $"[parameters('{ParameterNames.ServiceUrl}')]" });
}

if (extractorParameters.ParameterizeApiLoggerId)
{
masterResourceTemplate.Properties.Parameters.Add(ParameterNames.ApiLoggerId, new TemplateParameterProperties() { Value = $"[parameters('{ParameterNames.ApiLoggerId}')]" });
}

if (extractorParameters.ParametrizeApiOauth2Scope)
{
masterResourceTemplate.Properties.Parameters.Add(ParameterNames.ApiOauth2ScopeSettings, new TemplateParameterProperties() { Value = $"[parameters('{ParameterNames.ApiOauth2ScopeSettings}')]" });
}

return masterResourceTemplate;
}

Expand Down Expand Up @@ -423,6 +430,13 @@ Dictionary<string, TemplateParameterProperties> CreateMasterTemplateParameters(E
new TemplateParameterProperties(metadataDescription: "The settings for the Backends", type: "object"));
}

if (extractorParameters.ParametrizeApiOauth2Scope)
{
parameters.Add(
ParameterNames.ApiOauth2ScopeSettings,
new TemplateParameterProperties(metadataDescription: "The settings for the APIs Oauth2 Scope values", type: "object"));
}

return parameters;
}

Expand Down
46 changes: 43 additions & 3 deletions src/ArmTemplates/Extractor/EntityExtractors/ParametersExtractor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ public async Task<Template> CreateMasterTemplateParameterValues(
AddPolicyParameters();
AddNamedValuesParameters();
await AddServiceUrlParameterAsync();
await AddApiOauth2ScopeParameterAsync();

void AddLinkedUrlParameters()
{
Expand Down Expand Up @@ -102,15 +103,18 @@ async Task AddServiceUrlParameterAsync()
{
var validApiName = ParameterNamingHelper.GenerateValidParameterName(apiName, ParameterPrefix.Api);

string serviceUrl;
if (extractorParameters.ServiceUrlParameters is null)
string serviceUrl = null;
if (extractorParameters.ApiParameters is null)
{
var apiDetails = await this.apisClient.GetSingleAsync(apiName, extractorParameters);
serviceUrl = apiDetails.Properties.ServiceUrl;
}
else
{
serviceUrl = extractorParameters.ServiceUrlParameters.FirstOrDefault(x => x.ApiName.Equals(apiName))?.ServiceUrl;
if (extractorParameters.ApiParameters.ContainsKey(apiName))
{
serviceUrl = extractorParameters.ApiParameters[apiName].ServiceUrl;
}
}

serviceUrls.Add(validApiName, serviceUrl);
Expand All @@ -119,6 +123,42 @@ async Task AddServiceUrlParameterAsync()
parameters.Add(ParameterNames.ServiceUrl, new TemplateObjectParameterProperties() { Value = serviceUrls });
}

async Task AddApiOauth2ScopeParameterAsync()
{
if (!extractorParameters.ParametrizeApiOauth2Scope)
{
return;
}

var apiOauth2Scopes = new Dictionary<string, string>();
foreach (var apiName in apisToExtract)
{
var apiDetails = await this.apisClient.GetSingleAsync(apiName, extractorParameters);

if (apiDetails.Properties.AuthenticationSettings?.OAuth2 is not null)
{
string apiOAuthScope = null;
var validApiName = ParameterNamingHelper.GenerateValidParameterName(apiName, ParameterPrefix.Api);

if (extractorParameters.ApiParameters.IsNullOrEmpty())
{
apiOAuthScope = apiDetails.Properties.AuthenticationSettings.OAuth2?.Scope;
}
else
{
if (extractorParameters.ApiParameters.ContainsKey(apiName))
{
apiOAuthScope = extractorParameters.ApiParameters[apiName].Oauth2Scope;
}
}

apiOauth2Scopes.Add(validApiName, apiOAuthScope);
}
}

parameters.Add(ParameterNames.ApiOauth2ScopeSettings, new TemplateObjectParameterProperties() { Value = apiOauth2Scopes });
}

void AddNamedValuesParameters()
{
if (!extractorParameters.ParameterizeNamedValue &&
Expand Down
20 changes: 20 additions & 0 deletions src/ArmTemplates/Extractor/Models/ApiParameterProperty.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// --------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
// --------------------------------------------------------------------------

namespace Microsoft.Azure.Management.ApiManagement.ArmTemplates.Extractor.Models
{
public class ApiParameterProperty
{
public string Oauth2Scope { get; }

public string ServiceUrl { get; }

public ApiParameterProperty(string oauth2Scope, string serviceUrl)
{
this.Oauth2Scope = oauth2Scope;
this.ServiceUrl = serviceUrl;
}
}
}
15 changes: 10 additions & 5 deletions src/ArmTemplates/Extractor/Models/ExtractorParameters.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Commands.Configurations;
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common.Extensions;
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common.FileHandlers;
Expand Down Expand Up @@ -61,8 +62,6 @@ public record ExtractorParameters

public string ApiVersionSetName { get; private set; }

public ServiceUrlProperty[] ServiceUrlParameters { get; private set; }

public bool ParameterizeServiceUrl { get; private set; }

public bool ParameterizeNamedValue { get; private set; }
Expand All @@ -85,6 +84,10 @@ public record ExtractorParameters

public bool OverrideProductGuids { get; set; }

public bool ParametrizeApiOauth2Scope { get; set; }

public Dictionary<string, ApiParameterProperty> ApiParameters { get; private set; }

public ExtractorParameters(ExtractorConsoleAppConfiguration extractorConfig)
{
this.SourceApimName = extractorConfig.SourceApimName;
Expand All @@ -99,8 +102,6 @@ public ExtractorParameters(ExtractorConsoleAppConfiguration extractorConfig)
this.PolicyXMLSasToken = extractorConfig.PolicyXMLSasToken;
this.ApiVersionSetName = extractorConfig.ApiVersionSetName;
this.IncludeAllRevisions = extractorConfig.IncludeAllRevisions != null && extractorConfig.IncludeAllRevisions.Equals("true", StringComparison.OrdinalIgnoreCase);
this.ServiceUrlParameters = extractorConfig.ServiceUrlParameters;
this.ParameterizeServiceUrl = extractorConfig.ParamServiceUrl != null && extractorConfig.ParamServiceUrl.Equals("true", StringComparison.OrdinalIgnoreCase) || extractorConfig.ServiceUrlParameters != null;
this.ParameterizeNamedValue = extractorConfig.ParamNamedValue != null && extractorConfig.ParamNamedValue.Equals("true", StringComparison.OrdinalIgnoreCase);
this.ParameterizeApiLoggerId = extractorConfig.ParamApiLoggerId != null && extractorConfig.ParamApiLoggerId.Equals("true", StringComparison.OrdinalIgnoreCase);
this.ParameterizeLogResourceId = extractorConfig.ParamLogResourceId != null && extractorConfig.ParamLogResourceId.Equals("true", StringComparison.OrdinalIgnoreCase);
Expand All @@ -115,6 +116,9 @@ public ExtractorParameters(ExtractorConsoleAppConfiguration extractorConfig)
this.ExtractGateways = extractorConfig.ExtractGateways != null && extractorConfig.ExtractGateways.Equals("true", StringComparison.OrdinalIgnoreCase);
this.OverrideGroupGuids = extractorConfig.OverrideGroupGuids != null && extractorConfig.OverrideGroupGuids.Equals("true", StringComparison.OrdinalIgnoreCase);
this.OverrideProductGuids = extractorConfig.OverrideProductGuids != null && extractorConfig.OverrideProductGuids.Equals("true", StringComparison.OrdinalIgnoreCase);
this.ApiParameters = extractorConfig.ApiParameters;
this.ParameterizeServiceUrl = extractorConfig.ParamServiceUrl != null && extractorConfig.ParamServiceUrl.Equals("true", StringComparison.OrdinalIgnoreCase) || (extractorConfig.ApiParameters != null && extractorConfig.ApiParameters.Any(x => x.Value.ServiceUrl is not null));
this.ParametrizeApiOauth2Scope = (extractorConfig.ParamApiOauth2Scope != null && extractorConfig.ParamApiOauth2Scope.Equals("true", StringComparison.OrdinalIgnoreCase)) || (extractorConfig.ApiParameters != null && extractorConfig.ApiParameters.Any(x => x.Value.Oauth2Scope is not null));
}

public ExtractorParameters OverrideConfiguration(ExtractorConsoleAppConfiguration overridingConfig)
Expand All @@ -137,7 +141,7 @@ public ExtractorParameters OverrideConfiguration(ExtractorConsoleAppConfiguratio
// there can be no service url parameters in overriding configuration
// this.ServiceUrlParameters = overridingConfig.ServiceUrlParameters ?? this.ServiceUrlParameters;

this.ParameterizeServiceUrl = !string.IsNullOrEmpty(overridingConfig.ParamServiceUrl) ? overridingConfig.ParamServiceUrl.Equals("true", StringComparison.OrdinalIgnoreCase) || overridingConfig.ServiceUrlParameters != null : this.ParameterizeServiceUrl;
this.ParameterizeServiceUrl = !string.IsNullOrEmpty(overridingConfig.ParamServiceUrl) ? overridingConfig.ParamServiceUrl.Equals("true", StringComparison.OrdinalIgnoreCase) : this.ParameterizeServiceUrl;
this.ParameterizeNamedValue = !string.IsNullOrEmpty(overridingConfig.ParamNamedValue) ? overridingConfig.ParamNamedValue.Equals("true", StringComparison.OrdinalIgnoreCase) : this.ParameterizeNamedValue;
this.ParameterizeApiLoggerId = !string.IsNullOrEmpty(overridingConfig.ParamApiLoggerId) ? overridingConfig.ParamApiLoggerId.Equals("true", StringComparison.OrdinalIgnoreCase) : this.ParameterizeApiLoggerId;
this.ParameterizeLogResourceId = !string.IsNullOrEmpty(overridingConfig.ParamLogResourceId) ? overridingConfig.ParamLogResourceId.Equals("true", StringComparison.OrdinalIgnoreCase) : this.ParameterizeLogResourceId;
Expand All @@ -147,6 +151,7 @@ public ExtractorParameters OverrideConfiguration(ExtractorConsoleAppConfiguratio
this.SplitApis = !string.IsNullOrEmpty(overridingConfig.SplitAPIs) ? overridingConfig.SplitAPIs.Equals("true", StringComparison.OrdinalIgnoreCase) : this.SplitApis;
this.IncludeAllRevisions = !string.IsNullOrEmpty(overridingConfig.IncludeAllRevisions) ? overridingConfig.IncludeAllRevisions.Equals("true", StringComparison.OrdinalIgnoreCase) : this.IncludeAllRevisions;
this.ExtractGateways = !string.IsNullOrEmpty(overridingConfig.ExtractGateways) ? overridingConfig.ExtractGateways.Equals("true", StringComparison.OrdinalIgnoreCase) : this.ExtractGateways;
this.ParametrizeApiOauth2Scope = !string.IsNullOrEmpty(overridingConfig.ParamApiOauth2Scope) ? overridingConfig.ParamApiOauth2Scope.Equals("true", StringComparison.OrdinalIgnoreCase) : this.ParametrizeApiOauth2Scope;

if (!string.IsNullOrEmpty(overridingConfig.BaseFileName))
{
Expand Down
Loading

0 comments on commit 34f94ed

Please sign in to comment.