bool DoesPolicyReferenceNamedValue(ExtractorParameters extractorParameters, IEnumerable <TemplateResource> policyResources, string propertyName, PropertyTemplateResource propertyTemplateResource) { // check if named value is referenced in a policy file foreach (PolicyTemplateResource policyTemplateResource in policyResources) { string policyContent = PolicyTemplateUtils.GetPolicyContent(extractorParameters, policyTemplateResource); if (policyContent.Contains(string.Concat("{{", propertyTemplateResource.Properties.displayName, "}}")) || policyContent.Contains(string.Concat("{{", propertyName, "}}"))) { // dont need to go through all policies if the named value has already been found return(true); } } return(false); }
/// <summary> /// Generate the ARM assets for the backend resources /// </summary> /// <param name="apimname"></param> /// <param name="resourceGroup"></param> /// <param name="singleApiName"></param> /// <param name="apiTemplateResources"></param> /// <param name="propertyResources"></param> /// <param name="policyXMLBaseUrl"></param> /// <param name="policyXMLSasToken"></param> /// <param name="extractBackendParameters"></param> /// <returns>a combination of a Template and the value for the BackendSettings parameter</returns> public async Task <Tuple <Template, Dictionary <string, BackendApiParameters> > > GenerateBackendsARMTemplateAsync(string apimname, string resourceGroup, string singleApiName, List <TemplateResource> apiTemplateResources, List <TemplateResource> propertyResources, ExtractorParameters extractorParameters) { Console.WriteLine("------------------------------------------"); Console.WriteLine("Extracting backends from service"); Template armTemplate = this.templateBuilder.GenerateTemplateWithApimServiceNameProperty().Build(); if (extractorParameters.ParameterizeBackend) { TemplateParameterProperties extractBackendParametersProperties = new TemplateParameterProperties() { type = "object" }; armTemplate.Parameters.Add(ParameterNames.BackendSettings, extractBackendParametersProperties); } List <TemplateResource> templateResources = new List <TemplateResource>(); // isolate api and operation policy resources in the case of a single api extraction, as they may reference backends var policyResources = apiTemplateResources.Where(resource => resource.Type == ResourceTypeConstants.APIPolicy || resource.Type == ResourceTypeConstants.APIOperationPolicy || resource.Type == ResourceTypeConstants.ProductPolicy); var namedValueResources = propertyResources.Where(resource => resource.Type == ResourceTypeConstants.Property); // pull all backends for service JObject oBackends = new JObject(); var oBackendParameters = new Dictionary <string, BackendApiParameters>(); int skipNumberOfBackends = 0; do { string backends = await this.GetBackendsAsync(apimname, resourceGroup, skipNumberOfBackends); oBackends = JObject.Parse(backends); foreach (var item in oBackends["value"]) { string backendName = ((JValue)item["name"]).Value.ToString(); string backend = await this.GetBackendDetailsAsync(apimname, resourceGroup, backendName); // convert returned backend to template resource class BackendTemplateResource backendTemplateResource = backend.Deserialize <BackendTemplateResource>(); backendTemplateResource.Name = $"[concat(parameters('{ParameterNames.ApimServiceName}'), '/{backendName}')]"; backendTemplateResource.ApiVersion = GlobalConstants.ApiVersion; bool includeBackend = false; ////only extract the backend if this is a full extraction, or in the case of a single api, if it is referenced by one of the policies if (singleApiName == null) { // if the user is extracting all apis, extract all the backends includeBackend = true; } else { // check extracted policies to see if the backend is referenced. foreach (PolicyTemplateResource policyTemplateResource in policyResources) { string policyContent = PolicyTemplateUtils.GetPolicyContent(extractorParameters, policyTemplateResource); if (this.DoesPolicyReferenceBackend(policyContent, namedValueResources, backendName, backendTemplateResource)) { // backend was used in policy, extract it includeBackend = true; // dont need to go through all policies if the back end has already been found break; } } } if (includeBackend) { if (extractorParameters.ParameterizeBackend) { var apiToken = new BackendApiParameters(); string validApiParamName = ParameterNamingHelper.GenerateValidParameterName(backendName, ParameterPrefix.Diagnostic).ToLower(); if (!string.IsNullOrEmpty(backendTemplateResource.Properties.resourceId)) { apiToken.resourceId = backendTemplateResource.Properties.resourceId; backendTemplateResource.Properties.resourceId = $"[parameters('{ParameterNames.BackendSettings}').{validApiParamName}.resourceId]"; } if (!string.IsNullOrEmpty(backendTemplateResource.Properties.url)) { apiToken.url = backendTemplateResource.Properties.url; backendTemplateResource.Properties.url = $"[parameters('{ParameterNames.BackendSettings}').{validApiParamName}.url]"; } if (!string.IsNullOrEmpty(backendTemplateResource.Properties.protocol)) { apiToken.protocol = backendTemplateResource.Properties.protocol; backendTemplateResource.Properties.protocol = $"[parameters('{ParameterNames.BackendSettings}').{validApiParamName}.protocol]"; } oBackendParameters.Add(validApiParamName, apiToken); } Console.WriteLine("'{0}' Backend found", backendName); templateResources.Add(backendTemplateResource); } } skipNumberOfBackends += GlobalConstants.NumOfRecords; }while (oBackends["nextLink"] != null); armTemplate.Resources = templateResources.ToArray(); return(new Tuple <Template, Dictionary <string, BackendApiParameters> >(armTemplate, oBackendParameters)); }
public async Task <bool> IsNamedValueUsedInBackends(string apimname, string resourceGroup, string singleApiName, List <TemplateResource> apiTemplateResources, ExtractorParameters extractorParameters, string propertyName, string propertyDisplayName) { // isolate api and operation policy resources in the case of a single api extraction, as they may reference backends var policyResources = apiTemplateResources.Where(resource => resource.Type == ResourceTypeConstants.APIPolicy || resource.Type == ResourceTypeConstants.APIOperationPolicy || resource.Type == ResourceTypeConstants.ProductPolicy); var emptyNamedValueResources = new List <TemplateResource>(); // pull all backends for service JObject oBackends = new JObject(); int skipNumberOfBackends = 0; do { string backends = await this.GetBackendsAsync(apimname, resourceGroup, skipNumberOfBackends); oBackends = JObject.Parse(backends); foreach (var item in oBackends["value"]) { var content = item.ToString(); // check if backend references the named value, credentials for example if (content.Contains(string.Concat("{{", propertyName, "}}")) || content.Contains(string.Concat("{{", propertyDisplayName, "}}"))) { //only true if this is a full extraction, or in the case of a single api, if it is referenced by one of the API policies if (singleApiName == null) { return(true); } else { // is this backend related to the single api? // is backend used in the extracted policies for this API // if backend id is referenced in policy // or a named value is referenced in policy to a backend, we have already checked the policy for named value. // check if this backend is used by any of the policies extracted string backendName = ((JValue)item["name"]).Value.ToString(); string backend = await this.GetBackendDetailsAsync(apimname, resourceGroup, backendName); // convert returned backend to template resource class BackendTemplateResource backendTemplateResource = backend.Deserialize <BackendTemplateResource>(); // we have already checked if the named value is used in a policy, we just need to confirm if the backend is referenced by this single api within the policy file // this is why an empty named values must be passed to this method for validation foreach (PolicyTemplateResource policyTemplateResource in policyResources) { string policyContent = PolicyTemplateUtils.GetPolicyContent(extractorParameters, policyTemplateResource); if (this.DoesPolicyReferenceBackend(policyContent, emptyNamedValueResources, backendName, backendTemplateResource)) { // dont need to go through all policies and backends if the named values has already been found return(true); } } } } } skipNumberOfBackends += GlobalConstants.NumOfRecords; }while (oBackends["nextLink"] != null); return(false); }