public Template CreateBackendTemplate(CreatorConfig creatorConfig) { // create empty template Template backendTemplate = CreateEmptyTemplate(); // add parameters backendTemplate.parameters = new Dictionary <string, TemplateParameterProperties> { { ParameterNames.ApimServiceName, new TemplateParameterProperties() { type = "string" } } }; List <TemplateResource> resources = new List <TemplateResource>(); foreach (BackendTemplateProperties backendTemplatePropeties in creatorConfig.backends) { // create backend resource with properties BackendTemplateResource backendTemplateResource = new BackendTemplateResource() { name = $"[concat(parameters('{ParameterNames.ApimServiceName}'), '/{backendTemplatePropeties.title}')]", type = ResourceTypeConstants.Backend, apiVersion = GlobalConstants.APIVersion, properties = backendTemplatePropeties, dependsOn = new string[] { } }; resources.Add(backendTemplateResource); } backendTemplate.resources = resources.ToArray(); return(backendTemplate); }
public async Task <Template> GenerateBackendsARMTemplateAsync(string apimname, string resourceGroup, string singleApiName, List <TemplateResource> apiTemplateResources, List <TemplateResource> propertyResources, string policyXMLBaseUrl, string policyXMLSasToken) { Console.WriteLine("------------------------------------------"); Console.WriteLine("Extracting backends from service"); Template armTemplate = GenerateEmptyTemplateWithParameters(policyXMLBaseUrl, policyXMLSasToken); 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 string backends = await GetBackendsAsync(apimname, resourceGroup); JObject oBackends = JObject.Parse(backends); foreach (var item in oBackends["value"]) { string backendName = ((JValue)item["name"]).Value.ToString(); string backend = await GetBackendDetailsAsync(apimname, resourceGroup, backendName); // convert returned backend to template resource class BackendTemplateResource backendTemplateResource = JsonConvert.DeserializeObject <BackendTemplateResource>(backend); backendTemplateResource.name = $"[concat(parameters('{ParameterNames.ApimServiceName}'), '/{backendName}')]"; backendTemplateResource.apiVersion = GlobalConstants.APIVersion; ////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 // Console.WriteLine("'{0}' Backend found", backendName); // templateResources.Add(backendTemplateResource); //} //else //{ // bool isReferencedInPolicy = false; // foreach (PolicyTemplateResource policyTemplateResource in policyResources) // { // // the backend is used in a policy if the xml contains a set-backend-service policy, which will reference the backend's url or id // string policyContent = policyTemplateResource.properties.policyContent; // isReferencedInPolicy = DoesPolicyReferenceBackend(policyContent, namedValueResources, backendName, backendTemplateResource); // } // if (isReferencedInPolicy == true) // { // // backend was used in policy, extract it // Console.WriteLine("'{0}' Backend found", backendName); // templateResources.Add(backendTemplateResource); // } //} Console.WriteLine("'{0}' Backend found", backendName); templateResources.Add(backendTemplateResource); } armTemplate.resources = templateResources.ToArray(); return(armTemplate); }
public Template CreateBackendTemplate(CreatorConfig creatorConfig) { // create empty template Template backendTemplate = CreateEmptyTemplate(); // add parameters backendTemplate.parameters = new Dictionary <string, TemplateParameterProperties> { { ParameterNames.ApimServiceName, new TemplateParameterProperties() { type = "string" } } }; List <TemplateResource> resources = new List <TemplateResource>(); StringBuilder serviceParameter = new StringBuilder(); foreach (BackendTemplateProperties backendTemplatePropeties in creatorConfig.backends) { if (serviceParameter.Length == 0) { serviceParameter.Append("{"); } else { serviceParameter.Append(","); } serviceParameter.Append(string.Concat("\"", GetSanitisedName(backendTemplatePropeties.title), "\": \"", backendTemplatePropeties.url, "\"")); // create backend resource with properties BackendTemplateResource backendTemplateResource = new BackendTemplateResource() { name = $"[concat(parameters('{ParameterNames.ApimServiceName}'), '/{backendTemplatePropeties.title}')]", type = ResourceTypeConstants.Backend, apiVersion = GlobalConstants.APIVersion, properties = backendTemplatePropeties, dependsOn = new string[] { } }; backendTemplateResource.properties.url = $"[parameters('{ParameterNames.ServiceUrl}').{GetSanitisedName(backendTemplatePropeties.title)}]"; resources.Add(backendTemplateResource); } serviceParameter.Append("}"); backendTemplate.parameters.Add(ParameterNames.ServiceUrl, new TemplateParameterProperties() { type = "object", defaultValue = serviceParameter.ToString() }); backendTemplate.resources = resources.ToArray(); return(backendTemplate); }
bool DoesPolicyReferenceBackend( string policyContent, IEnumerable <NamedValueTemplateResource> namedValueResources, string backendName, BackendTemplateResource backendTemplateResource) { // a policy is referenced by a backend with the set-backend-service policy, which will reference use the backends name or url, or through referencing a named value that applies to the backend var namedValueResourcesUsedByBackend = namedValueResources.Where(resource => this.DoesBackendReferenceNamedValue(resource, backendTemplateResource)); if (backendName != null && policyContent.Contains(backendName) || backendTemplateResource.Properties.Url != null && policyContent.Contains(backendTemplateResource.Properties.Url) || backendTemplateResource.Properties.Title != null && policyContent.Contains(backendTemplateResource.Properties.Title) || backendTemplateResource.Properties.ResourceId != null && policyContent.Contains(backendTemplateResource.Properties.ResourceId)) { return(true); } return(namedValueResourcesUsedByBackend.Any(x => (x.Properties.DisplayName is not null && policyContent.Contains(x.Properties.DisplayName)) || (x.Properties.Value is not null && policyContent.Contains(x.Properties.Value)))); }
public async Task <Template> Create(DeploymentDefinition creatorConfig) { var template = EmptyTemplate; template.Parameters.Add(ApiServiceNameParameter.Key, ApiServiceNameParameter.Value); var resources = new List <TemplateResource>(); foreach (var backendTemplatePropeties in creatorConfig.Backends) { var backendTemplateResource = new BackendTemplateResource() { Name = $"[concat(parameters('ApimServiceName'), '/{backendTemplatePropeties.Title}')]", Properties = backendTemplatePropeties, DependsOn = new string[] { } }; resources.Add(backendTemplateResource); } template.Resources = resources.ToArray(); return(await Task.FromResult(template)); }
public bool DoesPolicyReferenceBackend(string policyContent, IEnumerable <TemplateResource> namedValueResources, string backendName, BackendTemplateResource backendTemplateResource) { // a policy is referenced by a backend with the set-backend-service policy, which will reference use the backends name or url, or through referencing a named value that applies to the backend var namedValueResourcesUsedByBackend = namedValueResources.Where(resource => DoesBackendReferenceNamedValue(resource, backendTemplateResource)); if ((backendName != null && policyContent.Contains(backendName)) || (backendTemplateResource.properties.url != null && policyContent.Contains(backendTemplateResource.properties.url)) || (backendTemplateResource.properties.title != null && policyContent.Contains(backendTemplateResource.properties.title)) || (backendTemplateResource.properties.resourceId != null && policyContent.Contains(backendTemplateResource.properties.resourceId))) { return(true); } foreach (PropertyTemplateResource namedValueResource in namedValueResourcesUsedByBackend) { if (policyContent.Contains(namedValueResource.properties.displayName) || policyContent.Contains(namedValueResource.properties.value)) { return(true); } } return(false); }
public bool DoesBackendReferenceNamedValue(TemplateResource namedValueResource, BackendTemplateResource backendTemplateResource) { string namedValue = (namedValueResource as PropertyTemplateResource).properties.value; return(namedValue == backendTemplateResource.properties.url || namedValue == backendTemplateResource.properties.description || namedValue == backendTemplateResource.properties.title); }
/// <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); }
public void ShouldCreateBackendTemplateFromCreatorConfig() { // arrange BackendTemplateCreator backendTemplateCreator = new BackendTemplateCreator(new TemplateBuilder()); CreatorConfig creatorConfig = new CreatorConfig() { backends = new List <BackendTemplateProperties>() }; BackendTemplateProperties backend = new BackendTemplateProperties() { title = "title", description = "description", resourceId = "resourceId", url = "url", protocol = "protocol", proxy = new BackendProxy() { url = "url", username = "******", password = "******" }, tls = new BackendTLS() { validateCertificateChain = true, validateCertificateName = true }, credentials = new BackendCredentials() { certificate = new string[] { "cert1" }, query = new object(), header = new object(), authorization = new BackendCredentialsAuthorization() { scheme = "scheme", parameter = "parameter" } }, properties = new BackendSubProperties() { serviceFabricCluster = new BackendServiceFabricCluster() { clientCertificatethumbprint = "", managementEndpoints = new string[] { "endpoint" }, maxPartitionResolutionRetries = 1, serverCertificateThumbprints = new string[] { "thumbprint" }, serverX509Names = new ServerX509Names[] { new ServerX509Names() { name = "name", issuerCertificateThumbprint = "thumbprint" } } } } }; creatorConfig.backends.Add(backend); // act Template backendTemplate = backendTemplateCreator.CreateBackendTemplate(creatorConfig); BackendTemplateResource backendTemplateResource = (BackendTemplateResource)backendTemplate.Resources[0]; // assert Assert.Equal($"[concat(parameters('{ParameterNames.ApimServiceName}'), '/{backend.title}')]", backendTemplateResource.Name); Assert.Equal(backend.title, backendTemplateResource.Properties.title); Assert.Equal(backend.description, backendTemplateResource.Properties.description); Assert.Equal(backend.resourceId, backendTemplateResource.Properties.resourceId); Assert.Equal(backend.url, backendTemplateResource.Properties.url); Assert.Equal(backend.protocol, backendTemplateResource.Properties.protocol); Assert.Equal(backend.proxy.url, backendTemplateResource.Properties.proxy.url); Assert.Equal(backend.proxy.username, backendTemplateResource.Properties.proxy.username); Assert.Equal(backend.proxy.password, backendTemplateResource.Properties.proxy.password); Assert.Equal(backend.tls.validateCertificateChain, backendTemplateResource.Properties.tls.validateCertificateChain); Assert.Equal(backend.tls.validateCertificateName, backendTemplateResource.Properties.tls.validateCertificateName); Assert.Equal(backend.credentials.certificate, backendTemplateResource.Properties.credentials.certificate); Assert.Equal(backend.credentials.query, backendTemplateResource.Properties.credentials.query); Assert.Equal(backend.credentials.header, backendTemplateResource.Properties.credentials.header); Assert.Equal(backend.credentials.authorization.scheme, backendTemplateResource.Properties.credentials.authorization.scheme); Assert.Equal(backend.credentials.authorization.parameter, backendTemplateResource.Properties.credentials.authorization.parameter); Assert.Equal(backend.properties.serviceFabricCluster.clientCertificatethumbprint, backendTemplateResource.Properties.properties.serviceFabricCluster.clientCertificatethumbprint); Assert.Equal(backend.properties.serviceFabricCluster.managementEndpoints, backendTemplateResource.Properties.properties.serviceFabricCluster.managementEndpoints); Assert.Equal(backend.properties.serviceFabricCluster.maxPartitionResolutionRetries, backendTemplateResource.Properties.properties.serviceFabricCluster.maxPartitionResolutionRetries); Assert.Equal(backend.properties.serviceFabricCluster.serverCertificateThumbprints, backendTemplateResource.Properties.properties.serviceFabricCluster.serverCertificateThumbprints); Assert.Equal(backend.properties.serviceFabricCluster.serverX509Names[0].issuerCertificateThumbprint, backendTemplateResource.Properties.properties.serviceFabricCluster.serverX509Names[0].issuerCertificateThumbprint); Assert.Equal(backend.properties.serviceFabricCluster.serverX509Names[0].name, backendTemplateResource.Properties.properties.serviceFabricCluster.serverX509Names[0].name); }
public bool DoesBackendReferenceNamedValue(NamedValueTemplateResource namedValueResource, BackendTemplateResource backendTemplateResource) { var namedValue = namedValueResource.Properties.Value; return(namedValue == backendTemplateResource.Properties.Url || namedValue == backendTemplateResource.Properties.Description || namedValue == backendTemplateResource.Properties.Title); }
public void ShouldCreateBackendTemplateFromCreatorConfig() { // arrange BackendTemplateCreator backendTemplateCreator = new BackendTemplateCreator(new TemplateBuilder()); CreatorConfig creatorConfig = new CreatorConfig() { backends = new List <BackendTemplateProperties>() }; BackendTemplateProperties backend = new BackendTemplateProperties() { Title = "title", Description = "description", ResourceId = "resourceId", Url = "url", Protocol = "protocol", Proxy = new BackendProxy() { Url = "url", Username = "******", Password = "******" }, Tls = new BackendTls() { ValidateCertificateChain = true, ValidateCertificateName = true }, Credentials = new BackendCredentials() { Certificate = new string[] { "cert1" }, Query = new object(), Header = new object(), Authorization = new BackendCredentialsAuthorization() { Scheme = "scheme", Parameter = "parameter" } }, Properties = new BackendServiceFabricProperties() { ServiceFabricCluster = new BackendServiceFabricCluster() { ClientCertificatethumbprint = "", ManagementEndpoints = new string[] { "endpoint" }, MaxPartitionResolutionRetries = 1, ServerCertificateThumbprints = new string[] { "thumbprint" }, ServerX509Names = new ServerX509Names[] { new ServerX509Names() { Name = "name", IssuerCertificateThumbprint = "thumbprint" } } } } }; creatorConfig.backends.Add(backend); // act Template backendTemplate = backendTemplateCreator.CreateBackendTemplate(creatorConfig); BackendTemplateResource backendTemplateResource = (BackendTemplateResource)backendTemplate.Resources[0]; // assert Assert.Equal($"[concat(parameters('{ParameterNames.ApimServiceName}'), '/{backend.Title}')]", backendTemplateResource.Name); Assert.Equal(backend.Title, backendTemplateResource.Properties.Title); Assert.Equal(backend.Description, backendTemplateResource.Properties.Description); Assert.Equal(backend.ResourceId, backendTemplateResource.Properties.ResourceId); Assert.Equal(backend.Url, backendTemplateResource.Properties.Url); Assert.Equal(backend.Protocol, backendTemplateResource.Properties.Protocol); Assert.Equal(backend.Proxy.Url, backendTemplateResource.Properties.Proxy.Url); Assert.Equal(backend.Proxy.Username, backendTemplateResource.Properties.Proxy.Username); Assert.Equal(backend.Proxy.Password, backendTemplateResource.Properties.Proxy.Password); Assert.Equal(backend.Tls.ValidateCertificateChain, backendTemplateResource.Properties.Tls.ValidateCertificateChain); Assert.Equal(backend.Tls.ValidateCertificateName, backendTemplateResource.Properties.Tls.ValidateCertificateName); Assert.Equal(backend.Credentials.Certificate, backendTemplateResource.Properties.Credentials.Certificate); Assert.Equal(backend.Credentials.Query, backendTemplateResource.Properties.Credentials.Query); Assert.Equal(backend.Credentials.Header, backendTemplateResource.Properties.Credentials.Header); Assert.Equal(backend.Credentials.Authorization.Scheme, backendTemplateResource.Properties.Credentials.Authorization.Scheme); Assert.Equal(backend.Credentials.Authorization.Parameter, backendTemplateResource.Properties.Credentials.Authorization.Parameter); Assert.Equal(backend.Properties.ServiceFabricCluster.ClientCertificatethumbprint, backendTemplateResource.Properties.Properties.ServiceFabricCluster.ClientCertificatethumbprint); Assert.Equal(backend.Properties.ServiceFabricCluster.ManagementEndpoints, backendTemplateResource.Properties.Properties.ServiceFabricCluster.ManagementEndpoints); Assert.Equal(backend.Properties.ServiceFabricCluster.MaxPartitionResolutionRetries, backendTemplateResource.Properties.Properties.ServiceFabricCluster.MaxPartitionResolutionRetries); Assert.Equal(backend.Properties.ServiceFabricCluster.ServerCertificateThumbprints, backendTemplateResource.Properties.Properties.ServiceFabricCluster.ServerCertificateThumbprints); Assert.Equal(backend.Properties.ServiceFabricCluster.ServerX509Names[0].IssuerCertificateThumbprint, backendTemplateResource.Properties.Properties.ServiceFabricCluster.ServerX509Names[0].IssuerCertificateThumbprint); Assert.Equal(backend.Properties.ServiceFabricCluster.ServerX509Names[0].Name, backendTemplateResource.Properties.Properties.ServiceFabricCluster.ServerX509Names[0].Name); }