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

Add possibility to extract identity providers. #747

Merged
merged 13 commits into from
Jun 21, 2022
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ public class ExtractorConsoleAppConfiguration
[Option(longName: "paramApiOauth2Scope", HelpText = "Parametrize API OAuth2 scope values")]
public string ParamApiOauth2Scope { get; set; }

[Option(longName: "extractSecrets", HelpText = "Exrtact secrets from the services if applies")]
[Option(longName: "extractSecrets", HelpText = "Extract secrets from the services if applies")]
public string ExtractSecrets { get; set; }

/// <summary>
Expand Down
22 changes: 7 additions & 15 deletions src/ArmTemplates/Common/API/Clients/Abstractions/ApiClientBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,36 +25,28 @@ public abstract class ApiClientBase

protected AzureCliAuthenticator Auth { get; private set; } = new AzureCliAuthenticator();

protected Dictionary<string, HttpMethod> httpMethodsMap;

public const string HTTP_GET_METHOD = "get";
public const string HTTP_POST_METHOD = "post";

public ApiClientBase(string baseUrl = null)
{
if (!string.IsNullOrEmpty(baseUrl))
{
this.BaseUrl = baseUrl;
}

this.httpMethodsMap = new Dictionary<string, HttpMethod>();
this.httpMethodsMap.Add(HTTP_GET_METHOD, HttpMethod.Get);
this.httpMethodsMap.Add(HTTP_POST_METHOD, HttpMethod.Post);
}

protected async Task<string> CallApiManagementAsync(string azToken, string requestUrl, bool useCache = true, string method = HTTP_GET_METHOD)
protected async Task<string> CallApiManagementAsync(string azToken, string requestUrl, bool useCache = true, ClientHttpMethod method = ClientHttpMethod.GET)
{
if (useCache && this.cache.TryGetValue(requestUrl, out string cachedResponseBody))
{
return cachedResponseBody;
}

if (!this.httpMethodsMap.ContainsKey(method))
var httpMethod = method switch
{
throw new Exception($"Method {method} is not defined");
}
ClientHttpMethod.GET => HttpMethod.Get,
ClientHttpMethod.POST => HttpMethod.Post,
_ => throw new NotImplementedException("Method not supported")
};

var httpMethod = this.httpMethodsMap[method];
var request = new HttpRequestMessage(httpMethod, requestUrl);
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", azToken);
request.Headers.UserAgent.TryParseAdd($"{Application.Name}/{Application.BuildVersion}");
Expand All @@ -71,7 +63,7 @@ protected async Task<string> CallApiManagementAsync(string azToken, string reque
return responseBody;
}

protected async Task<TResponse> GetResponseAsync<TResponse>(string azToken, string requestUrl, bool useCache = true, string method = "get")
protected async Task<TResponse> GetResponseAsync<TResponse>(string azToken, string requestUrl, bool useCache = true, ClientHttpMethod method = ClientHttpMethod.GET)
{
var stringResponse = await this.CallApiManagementAsync(azToken, requestUrl, useCache, method);
return stringResponse.Deserialize<TResponse>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common.API.Clients.Abstractions;
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common.API.Models;
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common.Constants;
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common.Templates.IdentityProviders;
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Extractor.Models;
Expand Down Expand Up @@ -45,9 +46,7 @@ public async Task<IdentityProviderSecret> ListIdentityProviderSecrets(string ide
string requestUrl = string.Format(ListIdentyProviderSecret,
this.BaseUrl, azSubId, extractorParameters.ResourceGroup, extractorParameters.SourceApimName, identityProviderName, GlobalConstants.ApiVersion);

var identityProviderTemplates = await this.GetResponseAsync<IdentityProviderSecret>(azToken, requestUrl, useCache: false, method: HTTP_POST_METHOD);

return identityProviderTemplates;
return await this.GetResponseAsync<IdentityProviderSecret>(azToken, requestUrl, useCache: false, method: ClientHttpMethod.POST);
}
}
}
13 changes: 13 additions & 0 deletions src/ArmTemplates/Common/API/Models/ClientHttpMethod.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// --------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
// --------------------------------------------------------------------------

namespace Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common.API.Models
{
public enum ClientHttpMethod
DeagleGross marked this conversation as resolved.
Show resolved Hide resolved
{
GET,
POST
}
}
4 changes: 2 additions & 2 deletions src/ArmTemplates/Common/Templates/Builders/TemplateBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -147,11 +147,11 @@ public TemplateBuilder AddParameterizedApiLoggerIdProperty(ExtractorParameters e

public TemplateBuilder AddParametrizedIdentityProvidersSecrets()
{
var apiLoggerProperty = new TemplateParameterProperties()
var secretValuesProperty = new TemplateParameterProperties()
{
Type = "object"
};
this.template.Parameters.Add(ParameterNames.SecretValues, apiLoggerProperty);
this.template.Parameters.Add(ParameterNames.SecretValues, secretValuesProperty);

return this;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,23 @@ namespace Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common.Templates
public class IdentityProviderProperties
{
public string[] AllowedTenants { get; set; }

public string Authority { get; set; }

public string ClientId { get; set; }

public string ClientSecret { get; set; }

public string PasswordResetPolicyName { get; set; }

public string ProfileEditingPolicyName { get; set; }

public string SigninPolicyName { get; set; }

public string SigninTenant { get; set; }

public string SignupPolicyName { get; set; }

public string Type { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,30 @@
// Licensed under the MIT License.
// --------------------------------------------------------------------------

using System.Collections.Generic;

namespace Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common.Templates.IdentityProviders
{
public static class IdentityProviderType
DeagleGross marked this conversation as resolved.
Show resolved Hide resolved
{
public static readonly string AAD = "aad";
public static readonly string AADB2C = "aadB2C";
public static readonly string Facebook = "facebook";
public static readonly string Google = "google";
public static readonly string Microsoft = "microsoft";
public static readonly string Twitter = "twitter";
public const string AAD = "aad";
public const string AADB2C = "aadB2C";
public const string Facebook = "facebook";
public const string Google = "google";
public const string Microsoft = "microsoft";
public const string Twitter = "twitter";

public static HashSet<string> ClientSecretSupportedIdentityProviders = new() {
f-alizada marked this conversation as resolved.
Show resolved Hide resolved
AAD,
AADB2C,
Facebook,
Google,
Microsoft,
Twitter
};

public static bool IsIdentityProviderSupportsClientSecret(string identityProviderType) {
DeagleGross marked this conversation as resolved.
Show resolved Hide resolved
return ClientSecretSupportedIdentityProviders.Contains(identityProviderType);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ public class IdentityProviderExtractor : IIdentityProviderExtractor
{
readonly ILogger<IdentityProviderExtractor> logger;
readonly ITemplateBuilder templateBuilder;

readonly IIdentityProviderClient identityProviderClient;

public IdentityProviderExtractor(
Expand All @@ -30,7 +29,6 @@ public IdentityProviderExtractor(
{
this.logger = logger;
this.templateBuilder = templateBuilder;

this.identityProviderClient = identityProviderClient;
}

Expand All @@ -53,7 +51,11 @@ public async Task<Template<IdentityProviderResources>> GenerateIdentityProviders
identityProvider.Type = ResourceTypeConstants.IdentityProviders;
identityProvider.Name = $"[concat(parameters('{ParameterNames.ApimServiceName}'), '/{identityProvider.Name}')]";
identityProvider.ApiVersion = GlobalConstants.ApiVersion;
identityProvider.Properties.ClientSecret = $"[parameters('{ParameterNames.SecretValues}').{ParameterNames.IdentityProvidersSecretValues}.{NamingHelper.GenerateValidParameterName(identityProvider.OriginalName, ParameterPrefix.Property).ToLower()}]";

if (IdentityProviderType.IsIdentityProviderSupportsClientSecret(identityProvider.Properties.Type))
{
identityProvider.Properties.ClientSecret = $"[parameters('{ParameterNames.SecretValues}').{ParameterNames.IdentityProvidersSecretValues}.{NamingHelper.GenerateValidParameterName(identityProvider.OriginalName, ParameterPrefix.Property).ToLower()}]";
}

identityProviderTemplate.TypedResources.IdentityProviders.Add(identityProvider);
}
Expand Down
2 changes: 1 addition & 1 deletion src/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,7 @@ You have two choices when specifying your settings:
| overrideProductGuids | No | Set to true will override the product id in output template in case it does not match with system predefined values. |
| paramApiOauth2Scope | No | Set to true will parametrize the scope values for APIs in which User authorization setting set to OAuth 2.0. |
| apiParameters | No | Parameterize api parameters (Oauth2 Scope/Service Url) values for APIs in advance. |
| exctractSecrets | No | By default false. If set to "true" secrets will be extracted as well. Currently applies to identityProvider service. |
| exctractSecrets | No | By default false. If set to "true" secrets will be extracted as well and parameters templated will be supplied with actual secret values. Currently applies to identityProvider service. |


#### Note
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public static IdentityProviderProperties GetMockedIdentityProviderProperties(str
{
ClientId = "clientid",
ClientSecret = null,
Type = $"type{identityProviderName}"
Type = IdentityProviderType.AAD
};
}

Expand All @@ -47,7 +47,6 @@ public static IIdentityProviderClient GetMockedIdentityProviderClient(List<strin
{
var mockServiceIdentityProviderApiClient = new Mock<IIdentityProviderClient>(MockBehavior.Strict);

f-alizada marked this conversation as resolved.
Show resolved Hide resolved

mockServiceIdentityProviderApiClient
.Setup(x => x.GetAllAsync(It.IsAny<ExtractorParameters>()))
.ReturnsAsync((ExtractorParameters _) => GenerateMockedIdentityProviderList(identityProviderNames));
Expand Down