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

Commit 4de20e6

Browse files
f-alizadaFarhad Alizada
andauthored
Add possibility to extract identity providers. (#747)
* Add possibility to extract identity providers. Introduce extractSecret parameter. * Support list secret values for identity providers Co-authored-by: Farhad Alizada <falizada@microsoft.com>
1 parent ff1dcdb commit 4de20e6

33 files changed

+739
-33
lines changed

src/ArmTemplates/Commands/Configurations/ExtractorConsoleAppConfiguration.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,9 @@ public class ExtractorConsoleAppConfiguration
100100
[Option(longName: "paramApiOauth2Scope", HelpText = "Parametrize API OAuth2 scope values")]
101101
public string ParamApiOauth2Scope { get; set; }
102102

103+
[Option(longName: "extractSecrets", HelpText = "Extract secrets from the services if applies")]
104+
public string ExtractSecrets { get; set; }
105+
103106
/// <summary>
104107
/// Api parameter properties for overriding Api OAuth2 scope or/and Service urloverride. Available via extractor-config file only.
105108
/// </summary>

src/ArmTemplates/Commands/Executors/ExtractorExecutor.cs

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common.Templates.Gateway;
1818
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common.Templates.GatewayApi;
1919
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common.Templates.Groups;
20+
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common.Templates.IdentityProviders;
2021
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common.Templates.Logger;
2122
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common.Templates.Master;
2223
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common.Templates.NamedValues;
@@ -60,6 +61,7 @@ public class ExtractorExecutor
6061
readonly IApiRevisionExtractor apiRevisionExtractor;
6162
readonly IGatewayExtractor gatewayExtractor;
6263
readonly IGatewayApiExtractor gatewayApiExtractor;
64+
readonly IIdentityProviderExtractor identityProviderExtractor;
6365

6466
public ExtractorExecutor(
6567
ILogger<ExtractorExecutor> logger,
@@ -80,7 +82,8 @@ public ExtractorExecutor(
8082
IGroupExtractor groupExtractor,
8183
IApiRevisionExtractor apiRevisionExtractor,
8284
IGatewayExtractor gatewayExtractor,
83-
IGatewayApiExtractor gatewayApiExtractor)
85+
IGatewayApiExtractor gatewayApiExtractor,
86+
IIdentityProviderExtractor identityProviderExtractor)
8487
{
8588
this.logger = logger;
8689
this.apisClient = apisClient;
@@ -101,6 +104,7 @@ public ExtractorExecutor(
101104
this.apiRevisionExtractor = apiRevisionExtractor;
102105
this.gatewayExtractor = gatewayExtractor;
103106
this.gatewayApiExtractor = gatewayApiExtractor;
107+
this.identityProviderExtractor = identityProviderExtractor;
104108
}
105109

106110
/// <summary>
@@ -126,7 +130,8 @@ public static ExtractorExecutor BuildExtractorExecutor(
126130
IGroupExtractor groupExtractor = null,
127131
IApiRevisionExtractor apiRevisionExtractor = null,
128132
IGatewayExtractor gatewayExtractor = null,
129-
IGatewayApiExtractor gatewayApiExtractor = null)
133+
IGatewayApiExtractor gatewayApiExtractor = null,
134+
IIdentityProviderExtractor identityProviderExtractor = null)
130135
=> new ExtractorExecutor(
131136
logger,
132137
apisClient,
@@ -146,7 +151,8 @@ public static ExtractorExecutor BuildExtractorExecutor(
146151
groupExtractor,
147152
apiRevisionExtractor,
148153
gatewayExtractor,
149-
gatewayApiExtractor);
154+
gatewayApiExtractor,
155+
identityProviderExtractor);
150156

151157
public void SetExtractorParameters(ExtractorParameters extractorParameters)
152158
{
@@ -401,6 +407,7 @@ public async Task<Template> GenerateParametersTemplateAsync(
401407
LoggerTemplateResources loggerResources,
402408
BackendTemplateResources backendResources,
403409
NamedValuesResources namedValuesResources,
410+
IdentityProviderResources identityProviderResources,
404411
string baseFilesGenerationDirectory)
405412
{
406413
this.logger.LogInformation("Started generation of parameters template...");
@@ -411,6 +418,7 @@ public async Task<Template> GenerateParametersTemplateAsync(
411418
loggerResources,
412419
backendResources,
413420
namedValuesResources,
421+
identityProviderResources,
414422
this.extractorParameters);
415423

416424
if (!templateParameters.Parameters.IsNullOrEmpty())
@@ -438,7 +446,8 @@ public async Task<Template<MasterTemplateResources>> GenerateMasterTemplateAsync
438446
AuthorizationServerTemplateResources authorizationServersTemplateResources = null,
439447
NamedValuesResources namedValuesTemplateResources = null,
440448
TagTemplateResources tagTemplateResources = null,
441-
GroupTemplateResources groupTemplateResources = null)
449+
GroupTemplateResources groupTemplateResources = null,
450+
IdentityProviderResources identityProviderTemplateResources = null)
442451
{
443452
if (string.IsNullOrEmpty(this.extractorParameters.LinkedTemplatesBaseUrl))
444453
{
@@ -452,7 +461,7 @@ public async Task<Template<MasterTemplateResources>> GenerateMasterTemplateAsync
452461
this.extractorParameters, apiTemplateResources, policyTemplateResources, apiVersionSetTemplateResources,
453462
productsTemplateResources, productApisTemplateResources, apiTagsTemplateResources, loggersTemplateResources,
454463
backendsTemplateResources, authorizationServersTemplateResources, namedValuesTemplateResources, tagTemplateResources,
455-
groupTemplateResources);
464+
groupTemplateResources, identityProviderTemplateResources);
456465

457466
if (masterTemplate?.HasResources() == true)
458467
{
@@ -663,6 +672,29 @@ await FileWriter.SaveAsJsonAsync(
663672
return gatewayTemplate;
664673
}
665674

675+
/// <summary>
676+
/// Generates identity providers template in the desired folder
677+
/// </summary>
678+
/// <param name="baseFilesGenerationDirectory">name of base folder where to save output files</param>
679+
/// <returns>generated identity provider template</returns>
680+
public async Task<Template<IdentityProviderResources>> GenerateIdentityProviderTemplateAsync(string baseFilesGenerationDirectory)
681+
{
682+
this.logger.LogInformation("Started generation of identity provider template...");
683+
684+
var identityProviderTemplate = await this.identityProviderExtractor.GenerateIdentityProvidersTemplateAsync(this.extractorParameters);
685+
686+
if (identityProviderTemplate?.HasResources() == true)
687+
{
688+
await FileWriter.SaveAsJsonAsync(
689+
identityProviderTemplate,
690+
directory: baseFilesGenerationDirectory,
691+
fileName: this.extractorParameters.FileNames.IdentityProviders);
692+
}
693+
694+
this.logger.LogInformation("Finished generation of identity providers template...");
695+
return identityProviderTemplate;
696+
}
697+
666698
/// <summary>
667699
/// Generates gateway-api template in the desired folder
668700
/// </summary>
@@ -875,8 +907,9 @@ async Task GenerateTemplates(
875907
var namedValueTemplate = await this.GenerateNamedValuesTemplateAsync(singleApiName, apiTemplate.TypedResources.GetAllPolicies(), loggerTemplate.TypedResources.Loggers, baseFilesGenerationDirectory);
876908
var backendTemplate = await this.GenerateBackendTemplateAsync(singleApiName, apiTemplate.TypedResources.GetAllPolicies(), namedValueTemplate.TypedResources.NamedValues, baseFilesGenerationDirectory);
877909
var groupTemplate = await this.GenerateGroupsTemplateAsync(baseFilesGenerationDirectory);
910+
var identityProviderTemplate = await this.GenerateIdentityProviderTemplateAsync(baseFilesGenerationDirectory);
878911
await this.GenerateGatewayTemplateAsync(singleApiName, baseFilesGenerationDirectory);
879-
await this.GenerateParametersTemplateAsync(apisToExtract, loggerTemplate.TypedResources, backendTemplate.TypedResources, namedValueTemplate.TypedResources, baseFilesGenerationDirectory);
912+
await this.GenerateParametersTemplateAsync(apisToExtract, loggerTemplate.TypedResources, backendTemplate.TypedResources, namedValueTemplate.TypedResources, identityProviderTemplate.TypedResources, baseFilesGenerationDirectory);
880913

881914
await this.GenerateMasterTemplateAsync(
882915
baseFilesGenerationDirectory,
@@ -891,7 +924,8 @@ await this.GenerateMasterTemplateAsync(
891924
authorizationServersTemplateResources: authorizationServerTemplate.TypedResources,
892925
namedValuesTemplateResources: namedValueTemplate.TypedResources,
893926
tagTemplateResources: tagTemplate.TypedResources,
894-
groupTemplateResources: groupTemplate.TypedResources);
927+
groupTemplateResources: groupTemplate.TypedResources,
928+
identityProviderTemplateResources: identityProviderTemplate.TypedResources);
895929
}
896930

897931

src/ArmTemplates/Common/API/Clients/Abstractions/ApiClientBase.cs

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// Licensed under the MIT License.
44
// --------------------------------------------------------------------------
55

6+
using System;
67
using System.Collections.Generic;
78
using System.Net.Http;
89
using System.Net.Http.Headers;
@@ -32,29 +33,39 @@ public ApiClientBase(string baseUrl = null)
3233
}
3334
}
3435

35-
protected async Task<string> CallApiManagementAsync(string azToken, string requestUrl)
36+
protected async Task<string> CallApiManagementAsync(string azToken, string requestUrl, bool useCache = true, ClientHttpMethod method = ClientHttpMethod.GET)
3637
{
37-
if (this.cache.TryGetValue(requestUrl, out string cachedResponseBody))
38+
if (useCache && this.cache.TryGetValue(requestUrl, out string cachedResponseBody))
3839
{
3940
return cachedResponseBody;
4041
}
4142

42-
var request = new HttpRequestMessage(HttpMethod.Get, requestUrl);
43+
var httpMethod = method switch
44+
{
45+
ClientHttpMethod.GET => HttpMethod.Get,
46+
ClientHttpMethod.POST => HttpMethod.Post,
47+
_ => throw new NotImplementedException("Method not supported")
48+
};
49+
50+
var request = new HttpRequestMessage(httpMethod, requestUrl);
4351
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", azToken);
4452
request.Headers.UserAgent.TryParseAdd($"{Application.Name}/{Application.BuildVersion}");
4553

4654
HttpResponseMessage response = await this.httpClient.SendAsync(request);
4755
response.EnsureSuccessStatusCode();
4856
string responseBody = await response.Content.ReadAsStringAsync();
4957

50-
this.cache.Set(requestUrl, responseBody);
58+
if (useCache)
59+
{
60+
this.cache.Set(requestUrl, responseBody);
61+
}
5162

5263
return responseBody;
5364
}
5465

55-
protected async Task<TResponse> GetResponseAsync<TResponse>(string azToken, string requestUrl)
66+
protected async Task<TResponse> GetResponseAsync<TResponse>(string azToken, string requestUrl, bool useCache = true, ClientHttpMethod method = ClientHttpMethod.GET)
5667
{
57-
var stringResponse = await this.CallApiManagementAsync(azToken, requestUrl);
68+
var stringResponse = await this.CallApiManagementAsync(azToken, requestUrl, useCache, method);
5869
return stringResponse.Deserialize<TResponse>();
5970
}
6071

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// --------------------------------------------------------------------------
2+
// Copyright (c) Microsoft Corporation. All rights reserved.
3+
// Licensed under the MIT License.
4+
// --------------------------------------------------------------------------
5+
6+
using System.Collections.Generic;
7+
using System.Threading.Tasks;
8+
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common.Templates.IdentityProviders;
9+
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Extractor.Models;
10+
11+
namespace Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common.API.Clients.Abstractions
12+
{
13+
public interface IIdentityProviderClient
14+
{
15+
Task<List<IdentityProviderResource>> GetAllAsync(ExtractorParameters extractorParameters);
16+
17+
Task<IdentityProviderSecret> ListIdentityProviderSecrets(string identityProviderName, ExtractorParameters extractorParameters);
18+
}
19+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// --------------------------------------------------------------------------
2+
// Copyright (c) Microsoft Corporation. All rights reserved.
3+
// Licensed under the MIT License.
4+
// --------------------------------------------------------------------------
5+
6+
using System.Collections.Generic;
7+
using System.Threading.Tasks;
8+
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common.API.Clients.Abstractions;
9+
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common.API.Models;
10+
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common.Constants;
11+
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common.Templates.IdentityProviders;
12+
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Extractor.Models;
13+
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Extractor.Utilities.DataProcessors.Absctraction;
14+
15+
namespace Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common.API.Clients.IdentityProviders
16+
{
17+
public class IdentityProviderClient : ApiClientBase, IIdentityProviderClient
18+
{
19+
const string GetAllIdentityProvidersRequest = "{0}/subscriptions/{1}/resourceGroups/{2}/providers/Microsoft.ApiManagement/service/{3}/identityProviders?api-version={4}";
20+
const string ListIdentyProviderSecret = "{0}/subscriptions/{1}/resourceGroups/{2}/providers/Microsoft.ApiManagement/service/{3}/identityProviders/{4}/listSecrets?api-version={5}";
21+
22+
readonly IIdentityProviderProcessor identityProviderProcessor;
23+
24+
public IdentityProviderClient(IIdentityProviderProcessor identityProviderProcessor)
25+
{
26+
this.identityProviderProcessor = identityProviderProcessor;
27+
}
28+
29+
public async Task<List<IdentityProviderResource>> GetAllAsync(ExtractorParameters extractorParameters)
30+
{
31+
var (azToken, azSubId) = await this.Auth.GetAccessToken();
32+
33+
string requestUrl = string.Format(GetAllIdentityProvidersRequest,
34+
this.BaseUrl, azSubId, extractorParameters.ResourceGroup, extractorParameters.SourceApimName, GlobalConstants.ApiVersion);
35+
36+
var identityProviderTemplates = await this.GetPagedResponseAsync<IdentityProviderResource>(azToken, requestUrl);
37+
this.identityProviderProcessor.ProcessData(identityProviderTemplates, extractorParameters);
38+
39+
return identityProviderTemplates;
40+
}
41+
42+
public async Task<IdentityProviderSecret> ListIdentityProviderSecrets(string identityProviderName, ExtractorParameters extractorParameters)
43+
{
44+
var (azToken, azSubId) = await this.Auth.GetAccessToken();
45+
46+
string requestUrl = string.Format(ListIdentyProviderSecret,
47+
this.BaseUrl, azSubId, extractorParameters.ResourceGroup, extractorParameters.SourceApimName, identityProviderName, GlobalConstants.ApiVersion);
48+
49+
return await this.GetResponseAsync<IdentityProviderSecret>(azToken, requestUrl, useCache: false, method: ClientHttpMethod.POST);
50+
}
51+
}
52+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// --------------------------------------------------------------------------
2+
// Copyright (c) Microsoft Corporation. All rights reserved.
3+
// Licensed under the MIT License.
4+
// --------------------------------------------------------------------------
5+
6+
namespace Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common.API.Models
7+
{
8+
/// <summary>
9+
/// ClientHttpMethod represents HttpMethod type. The class is stored in a separate enum-type to not include System.Web.Mvc to the application.
10+
/// </summary>
11+
public enum ClientHttpMethod
12+
{
13+
GET,
14+
POST
15+
}
16+
}

src/ArmTemplates/Common/Constants/GlobalConstants.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ public static class ParameterNames
4040
public const string NamedValueKeyVaultSecrets = "namedValueKeyVaultSecrets";
4141
public const string BackendSettings = "backendSettings";
4242
public const string ApiOauth2ScopeSettings = "apiOauth2ScopeSettings";
43+
public const string SecretValues = "secretValues";
44+
public const string IdentityProvidersSecretValues = "identityProviders";
4345
}
4446

4547
public static class ParameterPrefix

src/ArmTemplates/Common/Constants/ResourceTypeConstants.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,6 @@ public static class ResourceTypeConstants
3434
public const string Gateway = "Microsoft.ApiManagement/service/gateways";
3535
public const string GatewayApi = "Microsoft.ApiManagement/service/gateways/apis";
3636
public const string ArmDeployments = "Microsoft.Resources/deployments";
37+
public const string IdentityProviders = "Microsoft.ApiManagement/service/identityProviders";
3738
}
3839
}

src/ArmTemplates/Common/FileHandlers/FileNameGenerator.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ public static FileNames GenerateFileNames(string baseFileName)
3434
ProductAPIs = $@"{baseFileName}productAPIs.template.json",
3535
Gateway = $@"{baseFileName}gateways.template.json",
3636
GatewayApi = $@"{baseFileName}gateways-apis.template.json",
37+
IdentityProviders = $@"{baseFileName}identity-providers.template.json",
3738
TagApi = $@"{baseFileName}apiTags.template.json",
3839
Parameters = $@"{baseFileName}parameters.json",
3940
LinkedMaster = $@"{baseFileName}master.template.json",

src/ArmTemplates/Common/FileHandlers/FileNames.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ public class FileNames
3333

3434
public string GatewayApi { get; set; }
3535

36+
public string IdentityProviders { get; set; }
37+
3638
public string Parameters { get; set; }
3739

3840
// linked property outputs 1 master template

src/ArmTemplates/Common/Templates/Builders/Abstractions/ITemplateBuilder.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,5 +39,7 @@ public Template<TTemplateResources> Build<TTemplateResources>()
3939
TemplateBuilder AddParameterizedBackendSettings(ExtractorParameters extractorParameters);
4040

4141
TemplateBuilder AddParameterizedLogResourceIdProperty(ExtractorParameters extractorParameters);
42+
43+
TemplateBuilder AddParametrizedIdentityProvidersSecrets();
4244
}
4345
}

src/ArmTemplates/Common/Templates/Builders/TemplateBuilder.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,5 +144,16 @@ public TemplateBuilder AddParameterizedApiLoggerIdProperty(ExtractorParameters e
144144

145145
return this;
146146
}
147+
148+
public TemplateBuilder AddParametrizedIdentityProvidersSecrets()
149+
{
150+
var secretValuesProperty = new TemplateParameterProperties()
151+
{
152+
Type = "object"
153+
};
154+
this.template.Parameters.Add(ParameterNames.SecretValues, secretValuesProperty);
155+
156+
return this;
157+
}
147158
}
148159
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// --------------------------------------------------------------------------
2+
// Copyright (c) Microsoft Corporation. All rights reserved.
3+
// Licensed under the MIT License.
4+
// --------------------------------------------------------------------------
5+
6+
namespace Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common.Templates.IdentityProviders
7+
{
8+
public class IdentityProviderProperties
9+
{
10+
public string[] AllowedTenants { get; set; }
11+
12+
public string Authority { get; set; }
13+
14+
public string ClientId { get; set; }
15+
16+
public string ClientSecret { get; set; }
17+
18+
public string PasswordResetPolicyName { get; set; }
19+
20+
public string ProfileEditingPolicyName { get; set; }
21+
22+
public string SigninPolicyName { get; set; }
23+
24+
public string SigninTenant { get; set; }
25+
26+
public string SignupPolicyName { get; set; }
27+
28+
public string Type { get; set; }
29+
}
30+
}

0 commit comments

Comments
 (0)