diff --git a/AzureIPNetworks/AzureIPNetworks.csproj b/AzureIPNetworks/AzureIPNetworks.csproj
index bddaaba..2ed48b5 100644
--- a/AzureIPNetworks/AzureIPNetworks.csproj
+++ b/AzureIPNetworks/AzureIPNetworks.csproj
@@ -11,6 +11,7 @@
+
diff --git a/AzureIPNetworks/AzureIPsProvider.cs b/AzureIPNetworks/AzureIPsProvider.cs
index 3a9f1f3..d177959 100644
--- a/AzureIPNetworks/AzureIPsProvider.cs
+++ b/AzureIPNetworks/AzureIPsProvider.cs
@@ -204,9 +204,7 @@ public async ValueTask> GetServiceTagsAsync(AzureCloud c
#endif
}
-///
-/// Implementation of for locally cached data.
-///
+/// Implementation of for data in embedded files.
internal class AzureIPsProviderLocal : AzureIPsProvider
{
///
@@ -222,10 +220,23 @@ protected override ValueTask GetStreamAsync(AzureCloud cloud, Cancellati
}
}
-///
-/// Implementation of for downloading remote data once per run.
-///
-/// Creates an instance.
+/// Implementation of for data in embedded files.
+/// Directory containing the files.
+internal class AzureIPsProviderTemp(string dir) : AzureIPsProvider
+{
+ ///
+ protected override ValueTask GetStreamAsync(AzureCloud cloud, CancellationToken cancellationToken = default)
+ {
+ // read the JSON file from directory
+ var path = Path.Combine(dir, $"{cloud}.json");
+ var stream = File.OpenRead(path);
+
+ // deserialize the JSON file
+ return new ValueTask(stream);
+ }
+}
+
+/// Implementation of for downloading remote data once per application instance.
/// The to use for downloading.
internal class AzureIPsProviderRemote(AzureIPsDownloader downloader) : AzureIPsProvider
{
diff --git a/AzureIPNetworks/KnownData.cs b/AzureIPNetworks/KnownData.cs
new file mode 100644
index 0000000..6170ef4
--- /dev/null
+++ b/AzureIPNetworks/KnownData.cs
@@ -0,0 +1,199 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by the StaticDataGenerator source generator
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+#nullable enable
+
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+
+using System.Collections;
+using System.Collections.Generic;
+
+namespace AzureIPNetworks;
+
+public static partial class KnownData
+{
+ // The regions
+ public static readonly IReadOnlyList Regions = [
+ "",
+ "australiacentral",
+ "australiacentral2",
+ "australiaeast",
+ "australiasoutheast",
+ "brazilne",
+ "brazilse",
+ "brazilsouth",
+ "canadacentral",
+ "canadaeast",
+ "centralfrance",
+ "centralindia",
+ "centralus",
+ "centraluseuap",
+ "chinaeast",
+ "chinaeast2",
+ "chinaeast3",
+ "chinanorth",
+ "chinanorth2",
+ "chinanorth3",
+ "eastasia",
+ "eastus",
+ "eastus2",
+ "eastus2euap",
+ "germanycentral",
+ "germanyn",
+ "germanynortheast",
+ "germanywc",
+ "israelcentral",
+ "italynorth",
+ "japaneast",
+ "japanwest",
+ "jioindiacentral",
+ "jioindiawest",
+ "koreacentral",
+ "koreasouth",
+ "malaysiasouth",
+ "mexicocentral",
+ "northcentralus",
+ "northeurope",
+ "northeurope2",
+ "norwaye",
+ "norwayw",
+ "polandcentral",
+ "qatarcentral",
+ "southafricanorth",
+ "southafricawest",
+ "southcentralus",
+ "southeastasia",
+ "southfrance",
+ "southindia",
+ "spaincentral",
+ "swedencentral",
+ "swedensouth",
+ "switzerlandn",
+ "switzerlandw",
+ "taiwannorth",
+ "taiwannorthwest",
+ "uaecentral",
+ "uaenorth",
+ "uksouth",
+ "ukwest",
+ "usdodcentral",
+ "usdodeast",
+ "usgovarizona",
+ "usgoviowa",
+ "usgovtexas",
+ "usgovvirginia",
+ "usstagec",
+ "usstagee",
+ "westcentralus",
+ "westeurope",
+ "westindia",
+ "westus",
+ "westus2",
+ "westus3",
+ ];
+
+ // The services
+ public static readonly IReadOnlyList Services = [
+ "",
+ "ActionGroup",
+ "ApplicationInsightsAvailability",
+ "AutonomousDevelopmentPlatform",
+ "AzureAD",
+ "AzureAdvancedThreatProtection",
+ "AzureAPIForFHIR",
+ "AzureApiManagement",
+ "AzureAppConfiguration",
+ "AzureAppService",
+ "AzureAppServiceManagement",
+ "AzureArcInfrastructure",
+ "AzureAttestation",
+ "AzureAutomation",
+ "AzureBackup",
+ "AzureBotService",
+ "AzureCognitiveSearch",
+ "AzureConnectors",
+ "AzureContainerRegistry",
+ "AzureCosmosDB",
+ "AzureDatabricks",
+ "AzureDataExplorerManagement",
+ "AzureDataLake",
+ "AzureDeviceUpdate",
+ "AzureDevOps",
+ "AzureDevSpaces",
+ "AzureDigitalTwins",
+ "AzureEventGrid",
+ "AzureEventHub",
+ "AzureFrontDoor",
+ "AzureIdentity",
+ "AzureInformationProtection",
+ "AzureIoTHub",
+ "AzureKeyVault",
+ "AzureLoadTestingInstanceManagement",
+ "AzureMachineLearning",
+ "AzureMachineLearningInference",
+ "AzureManagedGrafana",
+ "AzureMonitor",
+ "AzureMonitorForSAP",
+ "AzureOpenDatasets",
+ "AzurePortal",
+ "AzureResourceManager",
+ "AzureSecurityCenter",
+ "AzureSentinel",
+ "AzureServiceBus",
+ "AzureSignalR",
+ "AzureSiteRecovery",
+ "AzureSphereSecureService_Prod",
+ "AzureSpringCloud",
+ "AzureSQL",
+ "AzureStack",
+ "AzureStorage",
+ "AzureTrafficManager",
+ "AzureUpdateDelivery",
+ "AzureVideoAnalyzerForMedia",
+ "AzureWebPubSub",
+ "BatchNodeManagement",
+ "ChaosStudio",
+ "CognitiveServicesFrontend",
+ "CognitiveServicesManagement",
+ "DataFactory",
+ "Dynamics365BusinessCentral",
+ "Dynamics365ForMarketingEmail",
+ "ElasticAFD",
+ "EOPExtPublished",
+ "GatewayManager",
+ "Grafana",
+ "HDInsight",
+ "LogicApps",
+ "M365ManagementActivityApi",
+ "M365ManagementActivityApiWebhook",
+ "Marketplace",
+ "MicrosoftAzureFluidRelay",
+ "MicrosoftCloudAppSecurity",
+ "MicrosoftContainerRegistry",
+ "MicrosoftDefenderForEndpoint",
+ "MicrosoftPurviewPolicyDistribution",
+ "OneDsCollector",
+ "PowerBI",
+ "PowerPlatformInfra",
+ "PowerPlatformPlex",
+ "PowerQueryOnline",
+ "SCCservice",
+ "Scuba",
+ "SecurityCopilot",
+ "SerialConsole",
+ "ServiceFabric",
+ "SqlManagement",
+ "StorageMover",
+ "StorageSyncService",
+ "TridentKusto",
+ "WindowsAdminCenter",
+ "WindowsVirtualDesktop",
+ "WVDRelays",
+ ];
+}
diff --git a/AzureIPNetworks/ServiceTag.cs b/AzureIPNetworks/ServiceTag.cs
index 2ae8266..9dc654d 100644
--- a/AzureIPNetworks/ServiceTag.cs
+++ b/AzureIPNetworks/ServiceTag.cs
@@ -85,3 +85,8 @@ public enum AzureCloud
///
AzureGermany,
}
+
+///
+/// Known data collected from the files and used just for reference
+///
+public static partial class KnownData { }
diff --git a/AzureIPNetworksDownloader/AzureIPNetworksDownloader.csproj b/AzureIPNetworksDownloader/AzureIPNetworksDownloader.csproj
index 1063740..0e76146 100644
--- a/AzureIPNetworksDownloader/AzureIPNetworksDownloader.csproj
+++ b/AzureIPNetworksDownloader/AzureIPNetworksDownloader.csproj
@@ -1,6 +1,7 @@
+ net8.0
Exe
false
diff --git a/AzureIPNetworksDownloader/Program.cs b/AzureIPNetworksDownloader/Program.cs
index 083317a..afd2b90 100644
--- a/AzureIPNetworksDownloader/Program.cs
+++ b/AzureIPNetworksDownloader/Program.cs
@@ -1,5 +1,7 @@
using AzureIPNetworks;
using System.Text.Json;
+using System.CodeDom.Compiler;
+using System.Text;
using System.Text.Json.Serialization;
var builder = Host.CreateApplicationBuilder(args);
@@ -9,6 +11,7 @@
var app = builder.Build();
+var cancellationToken = CancellationToken.None;
var logger = app.Services.GetRequiredService>();
var downloader = app.Services.GetRequiredService();
@@ -16,30 +19,109 @@
var targetDirectory = Path.GetFullPath(Path.Combine(Directory.GetCurrentDirectory(), "../AzureIPNetworks/Resources"));
var files = new Dictionary();
+// download file for each cloud
foreach (var cloud in clouds)
{
var cloudName = cloud.ToString();
- var (url, stream) = await downloader.DownloadAsync(cloud);
+ var (url, stream) = await downloader.DownloadAsync(cloud, cancellationToken);
var path = $"{Path.Combine(targetDirectory, cloudName)}.json";
if (File.Exists(path)) File.Delete(path);
- var fs = new FileStream(path, FileMode.OpenOrCreate);
- await stream.CopyToAsync(fs);
- await fs.FlushAsync();
+ using var fs = new FileStream(path, FileMode.OpenOrCreate);
+ await stream.CopyToAsync(fs, cancellationToken);
+ await fs.FlushAsync(cancellationToken);
logger.LogInformation("Completed writing service tag file for cloud {CloudName}", cloud);
files[cloud] = Path.GetFileName(url);
}
+// write list of file for reference
if (files.Count == clouds.Length)
{
var path = $"{Path.Combine(targetDirectory, "files")}.json";
if (File.Exists(path)) File.Delete(path);
- var fs = new FileStream(path, FileMode.OpenOrCreate);
- await JsonSerializer.SerializeAsync(fs, files, DownloaderJsonSerializerContext.Default.DictionaryAzureCloudString);
- await fs.FlushAsync();
+ using var fs = new FileStream(path, FileMode.OpenOrCreate);
+ await JsonSerializer.SerializeAsync(fs, files, DownloaderJsonSerializerContext.Default.DictionaryAzureCloudString, cancellationToken);
+ await fs.FlushAsync(cancellationToken);
+ logger.LogInformation("Completed writing files.json");
+}
+
+{
+ var provider = new AzureIPsProviderTemp(targetDirectory);
+ var path = Path.Combine(targetDirectory, "../KnownData.cs");
+ await GenerateKnownDataAsync(clouds, provider, path, cancellationToken);
+ logger.LogInformation("Completed writing KnownData.cs");
}
logger.LogInformation("Finished!");
+static async Task GenerateKnownDataAsync(IEnumerable clouds, AzureIPsProvider provider, string path, CancellationToken cancellationToken = default)
+{
+ // find unique regions and services
+ var regions = new List();
+ var services = new List();
+ foreach (var cloud in clouds)
+ {
+ var tags = await provider.GetServiceTagsAsync(cloud, cancellationToken);
+ regions.AddRange(tags.Select(t => t.Properties.Region));
+ services.AddRange(tags.Select(t => t.Properties.SystemService));
+ }
+ regions = [.. regions.Distinct(StringComparer.OrdinalIgnoreCase).Order()];
+ services = [.. services.Distinct(StringComparer.OrdinalIgnoreCase).Order()];
+ const string Header = @"//------------------------------------------------------------------------------
+//
+// This code was generated by the StaticDataGenerator source generator
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+#nullable enable
+
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+";
+
+ var sb = new StringBuilder();
+ var writer = new IndentedTextWriter(new StringWriter(sb));
+
+ writer.WriteLine(Header);
+
+ writer.WriteLine("using System.Collections;");
+ writer.WriteLine("using System.Collections.Generic;");
+
+ // write the namespace
+ writer.WriteLine();
+ writer.WriteLine("namespace AzureIPNetworks;");
+ writer.WriteLine();
+
+ // begin the class
+ writer.WriteLine("public static partial class KnownData");
+ writer.WriteLine("{");
+ writer.Indent++;
+
+ writer.WriteLine("// The regions");
+ writer.WriteLine("public static readonly IReadOnlyList Regions = [");
+ writer.Indent++;
+ foreach (var r in regions) writer.WriteLine($"\"{r}\",");
+ writer.Indent--;
+ writer.WriteLine("];");
+
+ writer.WriteLine("");
+ writer.WriteLine("// The services");
+ writer.WriteLine("public static readonly IReadOnlyList Services = [");
+ writer.Indent++;
+ foreach (var s in services) writer.WriteLine($"\"{s}\",");
+ writer.Indent--;
+ writer.WriteLine("];");
+
+ // end the class
+ writer.Indent--;
+ writer.WriteLine("}");
+ await writer.FlushAsync(cancellationToken);
+
+ // output to file
+ await File.WriteAllTextAsync(path, sb.ToString(), Encoding.UTF8, cancellationToken);
+}
+
[JsonSerializable(typeof(Dictionary))]
[JsonSourceGenerationOptions(WriteIndented = true)]
internal partial class DownloaderJsonSerializerContext : JsonSerializerContext { }