logger)
37 | {
38 | _logger = logger;
39 | }
40 | #endregion
41 |
42 | #region Public Methods
43 | public void OnGet()
44 | {
45 | }
46 | #endregion
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/source/Pages/Error.cshtml:
--------------------------------------------------------------------------------
1 | @page
2 | @model ErrorModel
3 | @{
4 | ViewData["Title"] = "Error";
5 | }
6 |
7 | Error.
8 | An error occurred while processing your request.
9 |
10 | @if (Model.ShowRequestId)
11 | {
12 |
13 | Request ID: @Model.RequestId
14 |
15 | }
16 |
17 | Development Mode
18 |
19 | Swapping to the Development environment displays detailed information about the error that occurred.
20 |
21 |
22 | The Development environment shouldn't be enabled for deployed applications.
23 | It can result in displaying sensitive information from exceptions to end users.
24 | For local debugging, enable the Development environment by setting the ASPNETCORE_ENVIRONMENT environment variable to Development
25 | and restarting the app.
26 |
27 |
--------------------------------------------------------------------------------
/source/Pages/Error.cshtml.cs:
--------------------------------------------------------------------------------
1 | #region Copyright
2 | //=======================================================================================
3 | // Microsoft
4 | //
5 | // This sample is supplemental to the technical guidance published on my personal
6 | // blog at https://github.com/paolosalvatori.
7 | //
8 | // Author: Paolo Salvatori
9 | //=======================================================================================
10 | // Copyright (c) Microsoft Corporation. All rights reserved.
11 | //
12 | // LICENSED UNDER THE APACHE LICENSE, VERSION 2.0 (THE "LICENSE"); YOU MAY NOT USE THESE
13 | // FILES EXCEPT IN COMPLIANCE WITH THE LICENSE. YOU MAY OBTAIN A COPY OF THE LICENSE AT
14 | // http://www.apache.org/licenses/LICENSE-2.0
15 | // UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING, SOFTWARE DISTRIBUTED UNDER THE
16 | // LICENSE IS DISTRIBUTED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 | // KIND, EITHER EXPRESS OR IMPLIED. SEE THE LICENSE FOR THE SPECIFIC LANGUAGE GOVERNING
18 | // PERMISSIONS AND LIMITATIONS UNDER THE LICENSE.
19 | //=======================================================================================
20 | #endregion
21 |
22 | #region Using Directives
23 | using Microsoft.AspNetCore.Mvc;
24 | using Microsoft.AspNetCore.Mvc.RazorPages;
25 | using Microsoft.Extensions.Logging;
26 | using System.Diagnostics;
27 | #endregion
28 |
29 | namespace SyntheticApi.Pages
30 | {
31 | [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
32 | public class ErrorModel : PageModel
33 | {
34 | #region Private Fields
35 | private readonly ILogger _logger;
36 | #endregion
37 |
38 | #region Public properties
39 | public string RequestId { get; set; }
40 |
41 | public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
42 | #endregion
43 |
44 | #region Public Constructors
45 | public ErrorModel(ILogger logger)
46 | {
47 | _logger = logger;
48 | }
49 | #endregion
50 |
51 | #region Public Methods
52 | public void OnGet()
53 | {
54 | RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;
55 | }
56 | #endregion
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/source/Pages/Index.cshtml:
--------------------------------------------------------------------------------
1 | @page
2 | @model IndexModel
3 | @{
4 | ViewData["Title"] = "Home page";
5 | }
6 |
7 |
Properties
8 |
9 |
10 |
11 |
12 | Property
13 |
14 |
15 | Value
16 |
17 |
18 |
19 |
20 |
21 |
22 | @Html.DisplayNameFor(modelItem => modelItem.MachineName)
23 |
24 |
25 | @Html.DisplayFor(modelItem => modelItem.MachineName)
26 |
27 |
28 |
29 |
30 | @Html.DisplayNameFor(modelItem => modelItem.Path)
31 |
32 |
33 | @Html.DisplayFor(modelItem => modelItem.Path)
34 |
35 |
36 |
37 |
38 | @Html.DisplayNameFor(modelItem => modelItem.IsHttps)
39 |
40 |
41 | @Html.DisplayFor(modelItem => modelItem.IsHttps)
42 |
43 |
44 |
45 |
46 |
Headers
47 |
48 |
49 |
50 |
51 | @Html.DisplayNameFor(modelItem => modelItem.Headers.First().Key)
52 |
53 |
54 | @Html.DisplayNameFor(modelItem => modelItem.Headers.First().Value)
55 |
56 |
57 |
58 |
59 | @foreach (var header in Model.Headers)
60 | {
61 |
62 |
63 | @Html.DisplayFor(modelItem => header.Key)
64 |
65 |
66 | @Html.DisplayFor(modelItem => header.Value[0])
67 |
68 |
69 | }
70 |
71 |
72 |
73 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/source/Pages/Index.cshtml.cs:
--------------------------------------------------------------------------------
1 | #region Copyright
2 | //=======================================================================================
3 | // Microsoft
4 | //
5 | // This sample is supplemental to the technical guidance published on my personal
6 | // blog at https://github.com/paolosalvatori.
7 | //
8 | // Author: Paolo Salvatori
9 | //=======================================================================================
10 | // Copyright (c) Microsoft Corporation. All rights reserved.
11 | //
12 | // LICENSED UNDER THE APACHE LICENSE, VERSION 2.0 (THE "LICENSE"); YOU MAY NOT USE THESE
13 | // FILES EXCEPT IN COMPLIANCE WITH THE LICENSE. YOU MAY OBTAIN A COPY OF THE LICENSE AT
14 | // http://www.apache.org/licenses/LICENSE-2.0
15 | // UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING, SOFTWARE DISTRIBUTED UNDER THE
16 | // LICENSE IS DISTRIBUTED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 | // KIND, EITHER EXPRESS OR IMPLIED. SEE THE LICENSE FOR THE SPECIFIC LANGUAGE GOVERNING
18 | // PERMISSIONS AND LIMITATIONS UNDER THE LICENSE.
19 | //=======================================================================================
20 | #endregion
21 |
22 | #region Using Directives
23 | using Microsoft.AspNetCore.Mvc;
24 | using Microsoft.AspNetCore.Mvc.RazorPages;
25 | using Microsoft.Extensions.Logging;
26 | using Microsoft.Extensions.Primitives;
27 | using System;
28 | using System.Collections.Generic;
29 | using System.Linq;
30 | #endregion
31 |
32 | namespace SyntheticApi.Pages
33 | {
34 | public class IndexModel : PageModel
35 | {
36 | #region Private Fields
37 | private readonly ILogger _logger;
38 | #endregion
39 |
40 | #region Public Constructors
41 | public IndexModel(ILogger logger)
42 | {
43 | _logger = logger;
44 | }
45 | #endregion
46 |
47 | #region Public Methods
48 | public void OnGet()
49 | {
50 |
51 | }
52 |
53 | [BindProperty(SupportsGet = true)]
54 | public IList> Headers
55 | {
56 | get
57 | {
58 | return Request.Headers.ToList();
59 | }
60 | set
61 | { }
62 | }
63 |
64 | [BindProperty(SupportsGet = true)]
65 | public string MachineName
66 | {
67 | get
68 | {
69 | return Environment.MachineName;
70 | }
71 | set
72 | { }
73 | }
74 |
75 | [BindProperty(SupportsGet = true)]
76 | public string IsHttps
77 | {
78 | get
79 | {
80 | return Request.IsHttps.ToString();
81 | }
82 | set
83 | { }
84 | }
85 |
86 | [BindProperty(SupportsGet = true)]
87 | public string Path
88 | {
89 | get
90 | {
91 | return Request.Path;
92 | }
93 | set
94 | { }
95 | }
96 | #endregion
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/source/Pages/Shared/_Layout.cshtml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | @ViewData["Title"] - SyntheticApi
7 |
8 |
9 |
10 |
11 |
32 |
33 |
34 | @RenderBody()
35 |
36 |
37 |
38 |
43 |
44 |
45 |
46 |
47 |
48 | @RenderSection("Scripts", required: false)
49 |
50 |
51 |
--------------------------------------------------------------------------------
/source/Pages/Shared/_ValidationScriptsPartial.cshtml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/source/Pages/_ViewImports.cshtml:
--------------------------------------------------------------------------------
1 | @using SyntheticApi
2 | @namespace SyntheticApi.Pages
3 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
4 |
--------------------------------------------------------------------------------
/source/Pages/_ViewStart.cshtml:
--------------------------------------------------------------------------------
1 | @{
2 | Layout = "_Layout";
3 | }
4 |
--------------------------------------------------------------------------------
/source/Program.cs:
--------------------------------------------------------------------------------
1 | #region Copyright
2 | //=======================================================================================
3 | // Microsoft
4 | //
5 | // This sample is supplemental to the technical guidance published on my personal
6 | // blog at https://github.com/paolosalvatori.
7 | //
8 | // Author: Paolo Salvatori
9 | //=======================================================================================
10 | // Copyright (c) Microsoft Corporation. All rights reserved.
11 | //
12 | // LICENSED UNDER THE APACHE LICENSE, VERSION 2.0 (THE "LICENSE"); YOU MAY NOT USE THESE
13 | // FILES EXCEPT IN COMPLIANCE WITH THE LICENSE. YOU MAY OBTAIN A COPY OF THE LICENSE AT
14 | // http://www.apache.org/licenses/LICENSE-2.0
15 | // UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING, SOFTWARE DISTRIBUTED UNDER THE
16 | // LICENSE IS DISTRIBUTED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 | // KIND, EITHER EXPRESS OR IMPLIED. SEE THE LICENSE FOR THE SPECIFIC LANGUAGE GOVERNING
18 | // PERMISSIONS AND LIMITATIONS UNDER THE LICENSE.
19 | //=======================================================================================
20 | #endregion
21 |
22 | #region Using Directives
23 | using Microsoft.AspNetCore.Hosting;
24 | using Microsoft.Extensions.Hosting;
25 | #endregion
26 |
27 | namespace SyntheticApi
28 | {
29 | public class Program
30 | {
31 | public static void Main(string[] args)
32 | {
33 | CreateHostBuilder(args).Build().Run();
34 | }
35 |
36 | public static IHostBuilder CreateHostBuilder(string[] args) =>
37 | Host.CreateDefaultBuilder(args)
38 | .ConfigureWebHostDefaults(webBuilder =>
39 | {
40 | webBuilder.UseStartup();
41 | });
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/source/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "iisSettings": {
3 | "windowsAuthentication": false,
4 | "anonymousAuthentication": true,
5 | "iisExpress": {
6 | "applicationUrl": "http://localhost:61431/",
7 | "sslPort": 44352
8 | }
9 | },
10 | "profiles": {
11 | "IIS Express": {
12 | "commandName": "IISExpress",
13 | "launchBrowser": true,
14 | "environmentVariables": {
15 | "ASPNETCORE_ENVIRONMENT": "Development"
16 | }
17 | },
18 | "SyntheticApi": {
19 | "commandName": "Project",
20 | "launchBrowser": true,
21 | "environmentVariables": {
22 | "ASPNETCORE_ENVIRONMENT": "Development"
23 | },
24 | "applicationUrl": "https://localhost:5001;http://localhost:5000"
25 | },
26 | "Docker": {
27 | "commandName": "Docker",
28 | "launchBrowser": true,
29 | "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}",
30 | "publishAllPorts": true,
31 | "useSSL": true
32 | }
33 | }
34 | }
--------------------------------------------------------------------------------
/source/Startup.cs:
--------------------------------------------------------------------------------
1 | #region Copyright
2 | //=======================================================================================
3 | // Microsoft
4 | //
5 | // This sample is supplemental to the technical guidance published on my personal
6 | // blog at https://github.com/paolosalvatori.
7 | //
8 | // Author: Paolo Salvatori
9 | //=======================================================================================
10 | // Copyright (c) Microsoft Corporation. All rights reserved.
11 | //
12 | // LICENSED UNDER THE APACHE LICENSE, VERSION 2.0 (THE "LICENSE"); YOU MAY NOT USE THESE
13 | // FILES EXCEPT IN COMPLIANCE WITH THE LICENSE. YOU MAY OBTAIN A COPY OF THE LICENSE AT
14 | // http://www.apache.org/licenses/LICENSE-2.0
15 | // UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING, SOFTWARE DISTRIBUTED UNDER THE
16 | // LICENSE IS DISTRIBUTED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 | // KIND, EITHER EXPRESS OR IMPLIED. SEE THE LICENSE FOR THE SPECIFIC LANGUAGE GOVERNING
18 | // PERMISSIONS AND LIMITATIONS UNDER THE LICENSE.
19 | //=======================================================================================
20 | #endregion
21 |
22 | #region Using Directives
23 | using System;
24 | using Microsoft.AspNetCore.Builder;
25 | using Microsoft.AspNetCore.Hosting;
26 | using Microsoft.Extensions.Configuration;
27 | using Microsoft.Extensions.DependencyInjection;
28 | using Microsoft.Extensions.Hosting;
29 | using Microsoft.OpenApi.Models;
30 | #endregion
31 |
32 | namespace SyntheticApi
33 | {
34 | public class Startup
35 | {
36 | #region Public Constructor
37 | public Startup(IConfiguration configuration)
38 | {
39 | Configuration = configuration;
40 | }
41 | #endregion
42 |
43 | #region Public Properties
44 | public IConfiguration Configuration { get; }
45 | #endregion
46 |
47 | #region Public Methods
48 | // This method gets called by the runtime. Use this method to add services to the container.
49 | public void ConfigureServices(IServiceCollection services)
50 | {
51 | services.AddControllers();
52 | services.AddApplicationInsightsTelemetry();
53 | services.AddRazorPages();
54 |
55 | // Register the Swagger generator, defining 1 or more Swagger documents
56 | services.AddSwaggerGen(c =>
57 | {
58 | c.SwaggerDoc("v1", new OpenApiInfo
59 | {
60 | Version = "v1",
61 | Title = "Performance Test Backend API",
62 | Description = "This is a simple ASP.NET Core Web API.",
63 | TermsOfService = new Uri("https://www.apache.org/licenses/LICENSE-2.0"),
64 | Contact = new OpenApiContact
65 | {
66 | Name = "Paolo Salvatori",
67 | Email = "paolos@microsoft.com",
68 | Url = new Uri("https://github.com/paolosalvatori"),
69 | },
70 | License = new OpenApiLicense
71 | {
72 | Name = "Use under Apache License 2.0",
73 | Url = new Uri("https://www.apache.org/licenses/LICENSE-2.0"),
74 | }
75 | });
76 | });
77 | }
78 |
79 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
80 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
81 | {
82 | // Enable middleware to serve generated Swagger as a JSON endpoint.
83 | app.UseSwagger();
84 |
85 | //// Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.), specifying the Swagger JSON endpoint.
86 | app.UseSwaggerUI(c =>
87 | {
88 | c.SwaggerEndpoint("/swagger/v1/swagger.json", "Performance Test Backend API V1");
89 | });
90 |
91 | if (env.IsDevelopment())
92 | {
93 | app.UseDeveloperExceptionPage();
94 | }
95 | else
96 | {
97 | app.UseExceptionHandler("/Error");
98 | // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
99 | app.UseHsts();
100 | }
101 |
102 | app.UseHttpsRedirection();
103 | app.UseStaticFiles();
104 | app.UseRouting();
105 | app.UseAuthorization();
106 | app.UseEndpoints(endpoints =>
107 | {
108 | endpoints.MapRazorPages();
109 | endpoints.MapControllers();
110 | });
111 | }
112 | #endregion
113 | }
114 | }
--------------------------------------------------------------------------------
/source/SyntheticApi.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp3.1
5 | /subscriptions/1a45a694-ae23-4650-9774-89a571c462f6/resourcegroups/IndigoRG/providers/microsoft.insights/components/SyntheticApi1
6 | annotations
7 | 7344312a-11c1-4417-a4a2-cf40452459fe
8 | Linux
9 | .
10 |
11 |
12 |
13 | x86
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/source/SyntheticApi.csproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Docker
5 |
6 |
--------------------------------------------------------------------------------
/source/SyntheticApi.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.29424.173
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SyntheticApi", "SyntheticApi.csproj", "{D99566E1-A131-45AF-B738-4720AF24392F}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {D99566E1-A131-45AF-B738-4720AF24392F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {D99566E1-A131-45AF-B738-4720AF24392F}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {D99566E1-A131-45AF-B738-4720AF24392F}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {D99566E1-A131-45AF-B738-4720AF24392F}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {529ABB96-DACE-45E3-B23D-3FDA35A3282B}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/source/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Debug",
5 | "System": "Information",
6 | "Microsoft": "Information"
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/source/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft": "Warning",
6 | "Microsoft.Hosting.Lifetime": "Information"
7 | }
8 | },
9 | "ApplicationInsights": {
10 | "InstrumentationKey": "2130b715-7335-44ea-9695-d25cd0b82a7c"
11 | },
12 | "AllowedHosts": "*"
13 | }
--------------------------------------------------------------------------------
/source/obj/Debug/netcoreapp3.1/.NETCoreApp,Version=v3.1.AssemblyAttributes.cs:
--------------------------------------------------------------------------------
1 | //
2 | using System;
3 | using System.Reflection;
4 | [assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v3.1", FrameworkDisplayName = ".NET Core 3.1")]
5 |
--------------------------------------------------------------------------------
/source/obj/Debug/netcoreapp3.1/SyntheticApi.AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | //
5 | // Changes to this file may cause incorrect behavior and will be lost if
6 | // the code is regenerated.
7 | //
8 | //------------------------------------------------------------------------------
9 |
10 | using System;
11 | using System.Reflection;
12 |
13 | [assembly: Microsoft.Extensions.Configuration.UserSecrets.UserSecretsIdAttribute("7344312a-11c1-4417-a4a2-cf40452459fe")]
14 | [assembly: System.Reflection.AssemblyCompanyAttribute("SyntheticApi")]
15 | [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
16 | [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
17 | [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0")]
18 | [assembly: System.Reflection.AssemblyProductAttribute("SyntheticApi")]
19 | [assembly: System.Reflection.AssemblyTitleAttribute("SyntheticApi")]
20 | [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
21 |
22 | // Generated by the MSBuild WriteCodeFragment class.
23 |
24 |
--------------------------------------------------------------------------------
/source/obj/Debug/netcoreapp3.1/SyntheticApi.AssemblyInfoInputs.cache:
--------------------------------------------------------------------------------
1 | aa7a3a82315990036a3d4cb09e934904725c14d9faaa756e7aa1bb3752e66ae4
2 |
--------------------------------------------------------------------------------
/source/obj/Debug/netcoreapp3.1/SyntheticApi.GeneratedMSBuildEditorConfig.editorconfig:
--------------------------------------------------------------------------------
1 | is_global = true
2 | build_property.RootNamespace = SyntheticApi
3 | build_property.ProjectDir = d:\Projects\AzureProjects\Terraform\azure-devops-aks\azure-devops-aks-azure-sample\source\
4 | build_property.EnableComHosting =
5 | build_property.EnableGeneratedComInterfaceComImportInterop =
6 |
--------------------------------------------------------------------------------
/source/obj/Debug/netcoreapp3.1/SyntheticApi.RazorAssemblyInfo.cache:
--------------------------------------------------------------------------------
1 | 3086df49c155733fa1c208f34762b75f956376723107e07fe4752d1d7166828a
2 |
--------------------------------------------------------------------------------
/source/obj/Debug/netcoreapp3.1/SyntheticApi.RazorAssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | //
5 | // Changes to this file may cause incorrect behavior and will be lost if
6 | // the code is regenerated.
7 | //
8 | //------------------------------------------------------------------------------
9 |
10 | using System;
11 | using System.Reflection;
12 |
13 | [assembly: Microsoft.AspNetCore.Mvc.ApplicationParts.RelatedAssemblyAttribute("SyntheticApi.Views")]
14 |
15 | // Generated by the MSBuild WriteCodeFragment class.
16 |
17 |
--------------------------------------------------------------------------------
/source/obj/Debug/netcoreapp3.1/SyntheticApi.assets.cache:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Azure-Samples/private-aks-cluster-terraform-devops/8bb51322e82bec3f9ab6457ac80633165e1afa3b/source/obj/Debug/netcoreapp3.1/SyntheticApi.assets.cache
--------------------------------------------------------------------------------
/source/obj/Debug/netcoreapp3.1/SyntheticApi.csproj.AssemblyReference.cache:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Azure-Samples/private-aks-cluster-terraform-devops/8bb51322e82bec3f9ab6457ac80633165e1afa3b/source/obj/Debug/netcoreapp3.1/SyntheticApi.csproj.AssemblyReference.cache
--------------------------------------------------------------------------------
/source/obj/SyntheticApi.csproj.nuget.dgspec.json:
--------------------------------------------------------------------------------
1 | {
2 | "format": 1,
3 | "restore": {
4 | "d:\\Projects\\AzureProjects\\Terraform\\azure-devops-aks\\azure-devops-aks-azure-sample\\source\\SyntheticApi.csproj": {}
5 | },
6 | "projects": {
7 | "d:\\Projects\\AzureProjects\\Terraform\\azure-devops-aks\\azure-devops-aks-azure-sample\\source\\SyntheticApi.csproj": {
8 | "version": "1.0.0",
9 | "restore": {
10 | "projectUniqueName": "d:\\Projects\\AzureProjects\\Terraform\\azure-devops-aks\\azure-devops-aks-azure-sample\\source\\SyntheticApi.csproj",
11 | "projectName": "SyntheticApi",
12 | "projectPath": "d:\\Projects\\AzureProjects\\Terraform\\azure-devops-aks\\azure-devops-aks-azure-sample\\source\\SyntheticApi.csproj",
13 | "packagesPath": "C:\\Users\\Paolo\\.nuget\\packages\\",
14 | "outputPath": "d:\\Projects\\AzureProjects\\Terraform\\azure-devops-aks\\azure-devops-aks-azure-sample\\source\\obj\\",
15 | "projectStyle": "PackageReference",
16 | "fallbackFolders": [
17 | "C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages"
18 | ],
19 | "configFilePaths": [
20 | "C:\\Users\\Paolo\\AppData\\Roaming\\NuGet\\NuGet.Config",
21 | "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config",
22 | "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config"
23 | ],
24 | "originalTargetFrameworks": [
25 | "netcoreapp3.1"
26 | ],
27 | "sources": {
28 | "C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {},
29 | "C:\\Program Files\\dotnet\\library-packs": {},
30 | "https://api.nuget.org/v3/index.json": {}
31 | },
32 | "frameworks": {
33 | "netcoreapp3.1": {
34 | "targetAlias": "netcoreapp3.1",
35 | "projectReferences": {}
36 | }
37 | },
38 | "warningProperties": {
39 | "warnAsError": [
40 | "NU1605"
41 | ]
42 | }
43 | },
44 | "frameworks": {
45 | "netcoreapp3.1": {
46 | "targetAlias": "netcoreapp3.1",
47 | "dependencies": {
48 | "Microsoft.ApplicationInsights.AspNetCore": {
49 | "target": "Package",
50 | "version": "[2.18.0, )"
51 | },
52 | "Microsoft.VisualStudio.Azure.Containers.Tools.Targets": {
53 | "target": "Package",
54 | "version": "[1.11.1, )"
55 | },
56 | "Swashbuckle.AspNetCore": {
57 | "target": "Package",
58 | "version": "[6.2.3, )"
59 | },
60 | "System.Text.Encodings.Web": {
61 | "target": "Package",
62 | "version": "[5.0.1, )"
63 | }
64 | },
65 | "imports": [
66 | "net461",
67 | "net462",
68 | "net47",
69 | "net471",
70 | "net472",
71 | "net48",
72 | "net481"
73 | ],
74 | "assetTargetFallback": true,
75 | "warn": true,
76 | "frameworkReferences": {
77 | "Microsoft.AspNetCore.App": {
78 | "privateAssets": "none"
79 | },
80 | "Microsoft.NETCore.App": {
81 | "privateAssets": "all"
82 | }
83 | },
84 | "runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\8.0.100\\RuntimeIdentifierGraph.json"
85 | }
86 | }
87 | }
88 | }
89 | }
--------------------------------------------------------------------------------
/source/obj/SyntheticApi.csproj.nuget.g.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | True
5 | NuGet
6 | $(MSBuildThisFileDirectory)project.assets.json
7 | $(UserProfile)\.nuget\packages\
8 | C:\Users\Paolo\.nuget\packages\;C:\Program Files (x86)\Microsoft Visual Studio\Shared\NuGetPackages
9 | PackageReference
10 | 6.8.0
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | C:\Users\Paolo\.nuget\packages\microsoft.extensions.apidescription.server\3.0.0
23 | C:\Users\Paolo\.nuget\packages\microsoft.visualstudio.azure.containers.tools.targets\1.11.1
24 |
25 |
--------------------------------------------------------------------------------
/source/obj/SyntheticApi.csproj.nuget.g.targets:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/source/wwwroot/css/site.css:
--------------------------------------------------------------------------------
1 | body {
2 | background: #fafafa url(https://jackrugile.com/images/misc/noise-diagonal.png);
3 | color: #444;
4 | font: 100%/30px 'Helvetica Neue', helvetica, arial, sans-serif;
5 | text-shadow: 0 1px 0 #fff;
6 | font-size: 12px;
7 | }
8 |
9 | strong {
10 | font-weight: bold;
11 | }
12 |
13 | em {
14 | font-style: italic;
15 | }
16 |
17 | table {
18 | background: #f5f5f5;
19 | border-collapse: separate;
20 | box-shadow: inset 0 1px 0 #fff;
21 | font-size: 12px;
22 | line-height: 18px;
23 | text-align: left;
24 | width: 800px;
25 | }
26 |
27 | th {
28 | background: url(https://jackrugile.com/images/misc/noise-diagonal.png), linear-gradient(#777, #444);
29 | border-left: 1px solid #555;
30 | border-right: 1px solid #777;
31 | border-top: 1px solid #555;
32 | border-bottom: 1px solid #333;
33 | box-shadow: inset 0 1px 0 #999;
34 | color: #fff;
35 | font-weight: bold;
36 | padding: 10px 15px;
37 | position: relative;
38 | text-shadow: 0 1px 0 #000;
39 | }
40 |
41 | th:after {
42 | background: linear-gradient(rgba(255,255,255,0), rgba(255,255,255,.08));
43 | content: '';
44 | display: block;
45 | height: 25%;
46 | left: 0;
47 | margin: 1px 0 0 0;
48 | position: absolute;
49 | top: 25%;
50 | width: 100%;
51 | }
52 |
53 | th:first-child {
54 | border-left: 1px solid #777;
55 | box-shadow: inset 1px 1px 0 #999;
56 | }
57 |
58 | th:last-child {
59 | box-shadow: inset -1px 1px 0 #999;
60 | }
61 |
62 | td {
63 | border-right: 1px solid #fff;
64 | border-left: 1px solid #e8e8e8;
65 | border-top: 1px solid #fff;
66 | border-bottom: 1px solid #e8e8e8;
67 | padding: 10px 15px;
68 | position: relative;
69 | transition: all 300ms;
70 | }
71 |
72 | td:first-child {
73 | box-shadow: inset 1px 0 0 #fff;
74 | }
75 |
76 | td:last-child {
77 | border-right: 1px solid #e8e8e8;
78 | box-shadow: inset -1px 0 0 #fff;
79 | }
80 |
81 | tr {
82 | background: url(https://jackrugile.com/images/misc/noise-diagonal.png);
83 | }
84 |
85 | tr:nth-child(odd) td {
86 | background: #f1f1f1 url(https://jackrugile.com/images/misc/noise-diagonal.png);
87 | }
88 |
89 | tr:last-of-type td {
90 | box-shadow: inset 0 -1px 0 #fff;
91 | }
92 |
93 | tr:last-of-type td:first-child {
94 | box-shadow: inset 1px -1px 0 #fff;
95 | }
96 |
97 | tr:last-of-type td:last-child {
98 | box-shadow: inset -1px -1px 0 #fff;
99 | }
100 |
101 | tbody:hover td {
102 | color: transparent;
103 | text-shadow: 0 0 3px #aaa;
104 | }
105 |
106 | tbody:hover tr:hover td {
107 | color: #444;
108 | text-shadow: 0 1px 0 #fff;
109 | }
110 |
--------------------------------------------------------------------------------
/source/wwwroot/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Azure-Samples/private-aks-cluster-terraform-devops/8bb51322e82bec3f9ab6457ac80633165e1afa3b/source/wwwroot/favicon.ico
--------------------------------------------------------------------------------
/source/wwwroot/js/site.js:
--------------------------------------------------------------------------------
1 | // Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification
2 | // for details on configuring this project to bundle and minify static web assets.
3 |
4 | // Write your Javascript code.
5 |
--------------------------------------------------------------------------------
/source/wwwroot/lib/bootstrap/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2011-2018 Twitter, Inc.
4 | Copyright (c) 2011-2018 The Bootstrap Authors
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in
14 | all copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | THE SOFTWARE.
23 |
--------------------------------------------------------------------------------
/source/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap Reboot v4.3.1 (https://getbootstrap.com/)
3 | * Copyright 2011-2019 The Bootstrap Authors
4 | * Copyright 2011-2019 Twitter, Inc.
5 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
6 | * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
7 | */
8 | *,
9 | *::before,
10 | *::after {
11 | box-sizing: border-box;
12 | }
13 |
14 | html {
15 | font-family: sans-serif;
16 | line-height: 1.15;
17 | -webkit-text-size-adjust: 100%;
18 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
19 | }
20 |
21 | article, aside, figcaption, figure, footer, header, hgroup, main, nav, section {
22 | display: block;
23 | }
24 |
25 | body {
26 | margin: 0;
27 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
28 | font-size: 1rem;
29 | font-weight: 400;
30 | line-height: 1.5;
31 | color: #212529;
32 | text-align: left;
33 | background-color: #fff;
34 | }
35 |
36 | [tabindex="-1"]:focus {
37 | outline: 0 !important;
38 | }
39 |
40 | hr {
41 | box-sizing: content-box;
42 | height: 0;
43 | overflow: visible;
44 | }
45 |
46 | h1, h2, h3, h4, h5, h6 {
47 | margin-top: 0;
48 | margin-bottom: 0.5rem;
49 | }
50 |
51 | p {
52 | margin-top: 0;
53 | margin-bottom: 1rem;
54 | }
55 |
56 | abbr[title],
57 | abbr[data-original-title] {
58 | text-decoration: underline;
59 | -webkit-text-decoration: underline dotted;
60 | text-decoration: underline dotted;
61 | cursor: help;
62 | border-bottom: 0;
63 | -webkit-text-decoration-skip-ink: none;
64 | text-decoration-skip-ink: none;
65 | }
66 |
67 | address {
68 | margin-bottom: 1rem;
69 | font-style: normal;
70 | line-height: inherit;
71 | }
72 |
73 | ol,
74 | ul,
75 | dl {
76 | margin-top: 0;
77 | margin-bottom: 1rem;
78 | }
79 |
80 | ol ol,
81 | ul ul,
82 | ol ul,
83 | ul ol {
84 | margin-bottom: 0;
85 | }
86 |
87 | dt {
88 | font-weight: 700;
89 | }
90 |
91 | dd {
92 | margin-bottom: .5rem;
93 | margin-left: 0;
94 | }
95 |
96 | blockquote {
97 | margin: 0 0 1rem;
98 | }
99 |
100 | b,
101 | strong {
102 | font-weight: bolder;
103 | }
104 |
105 | small {
106 | font-size: 80%;
107 | }
108 |
109 | sub,
110 | sup {
111 | position: relative;
112 | font-size: 75%;
113 | line-height: 0;
114 | vertical-align: baseline;
115 | }
116 |
117 | sub {
118 | bottom: -.25em;
119 | }
120 |
121 | sup {
122 | top: -.5em;
123 | }
124 |
125 | a {
126 | color: #007bff;
127 | text-decoration: none;
128 | background-color: transparent;
129 | }
130 |
131 | a:hover {
132 | color: #0056b3;
133 | text-decoration: underline;
134 | }
135 |
136 | a:not([href]):not([tabindex]) {
137 | color: inherit;
138 | text-decoration: none;
139 | }
140 |
141 | a:not([href]):not([tabindex]):hover, a:not([href]):not([tabindex]):focus {
142 | color: inherit;
143 | text-decoration: none;
144 | }
145 |
146 | a:not([href]):not([tabindex]):focus {
147 | outline: 0;
148 | }
149 |
150 | pre,
151 | code,
152 | kbd,
153 | samp {
154 | font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
155 | font-size: 1em;
156 | }
157 |
158 | pre {
159 | margin-top: 0;
160 | margin-bottom: 1rem;
161 | overflow: auto;
162 | }
163 |
164 | figure {
165 | margin: 0 0 1rem;
166 | }
167 |
168 | img {
169 | vertical-align: middle;
170 | border-style: none;
171 | }
172 |
173 | svg {
174 | overflow: hidden;
175 | vertical-align: middle;
176 | }
177 |
178 | table {
179 | border-collapse: collapse;
180 | }
181 |
182 | caption {
183 | padding-top: 0.75rem;
184 | padding-bottom: 0.75rem;
185 | color: #6c757d;
186 | text-align: left;
187 | caption-side: bottom;
188 | }
189 |
190 | th {
191 | text-align: inherit;
192 | }
193 |
194 | label {
195 | display: inline-block;
196 | margin-bottom: 0.5rem;
197 | }
198 |
199 | button {
200 | border-radius: 0;
201 | }
202 |
203 | button:focus {
204 | outline: 1px dotted;
205 | outline: 5px auto -webkit-focus-ring-color;
206 | }
207 |
208 | input,
209 | button,
210 | select,
211 | optgroup,
212 | textarea {
213 | margin: 0;
214 | font-family: inherit;
215 | font-size: inherit;
216 | line-height: inherit;
217 | }
218 |
219 | button,
220 | input {
221 | overflow: visible;
222 | }
223 |
224 | button,
225 | select {
226 | text-transform: none;
227 | }
228 |
229 | select {
230 | word-wrap: normal;
231 | }
232 |
233 | button,
234 | [type="button"],
235 | [type="reset"],
236 | [type="submit"] {
237 | -webkit-appearance: button;
238 | }
239 |
240 | button:not(:disabled),
241 | [type="button"]:not(:disabled),
242 | [type="reset"]:not(:disabled),
243 | [type="submit"]:not(:disabled) {
244 | cursor: pointer;
245 | }
246 |
247 | button::-moz-focus-inner,
248 | [type="button"]::-moz-focus-inner,
249 | [type="reset"]::-moz-focus-inner,
250 | [type="submit"]::-moz-focus-inner {
251 | padding: 0;
252 | border-style: none;
253 | }
254 |
255 | input[type="radio"],
256 | input[type="checkbox"] {
257 | box-sizing: border-box;
258 | padding: 0;
259 | }
260 |
261 | input[type="date"],
262 | input[type="time"],
263 | input[type="datetime-local"],
264 | input[type="month"] {
265 | -webkit-appearance: listbox;
266 | }
267 |
268 | textarea {
269 | overflow: auto;
270 | resize: vertical;
271 | }
272 |
273 | fieldset {
274 | min-width: 0;
275 | padding: 0;
276 | margin: 0;
277 | border: 0;
278 | }
279 |
280 | legend {
281 | display: block;
282 | width: 100%;
283 | max-width: 100%;
284 | padding: 0;
285 | margin-bottom: .5rem;
286 | font-size: 1.5rem;
287 | line-height: inherit;
288 | color: inherit;
289 | white-space: normal;
290 | }
291 |
292 | progress {
293 | vertical-align: baseline;
294 | }
295 |
296 | [type="number"]::-webkit-inner-spin-button,
297 | [type="number"]::-webkit-outer-spin-button {
298 | height: auto;
299 | }
300 |
301 | [type="search"] {
302 | outline-offset: -2px;
303 | -webkit-appearance: none;
304 | }
305 |
306 | [type="search"]::-webkit-search-decoration {
307 | -webkit-appearance: none;
308 | }
309 |
310 | ::-webkit-file-upload-button {
311 | font: inherit;
312 | -webkit-appearance: button;
313 | }
314 |
315 | output {
316 | display: inline-block;
317 | }
318 |
319 | summary {
320 | display: list-item;
321 | cursor: pointer;
322 | }
323 |
324 | template {
325 | display: none;
326 | }
327 |
328 | [hidden] {
329 | display: none !important;
330 | }
331 | /*# sourceMappingURL=bootstrap-reboot.css.map */
--------------------------------------------------------------------------------
/source/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap Reboot v4.3.1 (https://getbootstrap.com/)
3 | * Copyright 2011-2019 The Bootstrap Authors
4 | * Copyright 2011-2019 Twitter, Inc.
5 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
6 | * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
7 | */*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus{outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent}a:hover{color:#0056b3;text-decoration:underline}a:not([href]):not([tabindex]){color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus,a:not([href]):not([tabindex]):hover{color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus{outline:0}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}select{word-wrap:normal}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=date],input[type=datetime-local],input[type=month],input[type=time]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important}
8 | /*# sourceMappingURL=bootstrap-reboot.min.css.map */
--------------------------------------------------------------------------------
/source/wwwroot/lib/jquery-validation-unobtrusive/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) .NET Foundation. All rights reserved.
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use
4 | these files except in compliance with the License. You may obtain a copy of the
5 | License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software distributed
10 | under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
11 | CONDITIONS OF ANY KIND, either express or implied. See the License for the
12 | specific language governing permissions and limitations under the License.
13 |
--------------------------------------------------------------------------------
/source/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js:
--------------------------------------------------------------------------------
1 | // Unobtrusive validation support library for jQuery and jQuery Validate
2 | // Copyright (c) .NET Foundation. All rights reserved.
3 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
4 | // @version v3.2.11
5 | !function(a){"function"==typeof define&&define.amd?define("jquery.validate.unobtrusive",["jquery-validation"],a):"object"==typeof module&&module.exports?module.exports=a(require("jquery-validation")):jQuery.validator.unobtrusive=a(jQuery)}(function(a){function e(a,e,n){a.rules[e]=n,a.message&&(a.messages[e]=a.message)}function n(a){return a.replace(/^\s+|\s+$/g,"").split(/\s*,\s*/g)}function t(a){return a.replace(/([!"#$%&'()*+,.\/:;<=>?@\[\\\]^`{|}~])/g,"\\$1")}function r(a){return a.substr(0,a.lastIndexOf(".")+1)}function i(a,e){return 0===a.indexOf("*.")&&(a=a.replace("*.",e)),a}function o(e,n){var r=a(this).find("[data-valmsg-for='"+t(n[0].name)+"']"),i=r.attr("data-valmsg-replace"),o=i?a.parseJSON(i)!==!1:null;r.removeClass("field-validation-valid").addClass("field-validation-error"),e.data("unobtrusiveContainer",r),o?(r.empty(),e.removeClass("input-validation-error").appendTo(r)):e.hide()}function d(e,n){var t=a(this).find("[data-valmsg-summary=true]"),r=t.find("ul");r&&r.length&&n.errorList.length&&(r.empty(),t.addClass("validation-summary-errors").removeClass("validation-summary-valid"),a.each(n.errorList,function(){a(" ").html(this.message).appendTo(r)}))}function s(e){var n=e.data("unobtrusiveContainer");if(n){var t=n.attr("data-valmsg-replace"),r=t?a.parseJSON(t):null;n.addClass("field-validation-valid").removeClass("field-validation-error"),e.removeData("unobtrusiveContainer"),r&&n.empty()}}function l(e){var n=a(this),t="__jquery_unobtrusive_validation_form_reset";if(!n.data(t)){n.data(t,!0);try{n.data("validator").resetForm()}finally{n.removeData(t)}n.find(".validation-summary-errors").addClass("validation-summary-valid").removeClass("validation-summary-errors"),n.find(".field-validation-error").addClass("field-validation-valid").removeClass("field-validation-error").removeData("unobtrusiveContainer").find(">*").removeData("unobtrusiveContainer")}}function u(e){var n=a(e),t=n.data(v),r=a.proxy(l,e),i=f.unobtrusive.options||{},u=function(n,t){var r=i[n];r&&a.isFunction(r)&&r.apply(e,t)};return t||(t={options:{errorClass:i.errorClass||"input-validation-error",errorElement:i.errorElement||"span",errorPlacement:function(){o.apply(e,arguments),u("errorPlacement",arguments)},invalidHandler:function(){d.apply(e,arguments),u("invalidHandler",arguments)},messages:{},rules:{},success:function(){s.apply(e,arguments),u("success",arguments)}},attachValidation:function(){n.off("reset."+v,r).on("reset."+v,r).validate(this.options)},validate:function(){return n.validate(),n.valid()}},n.data(v,t)),t}var m,f=a.validator,v="unobtrusiveValidation";return f.unobtrusive={adapters:[],parseElement:function(e,n){var t,r,i,o=a(e),d=o.parents("form")[0];d&&(t=u(d),t.options.rules[e.name]=r={},t.options.messages[e.name]=i={},a.each(this.adapters,function(){var n="data-val-"+this.name,t=o.attr(n),s={};void 0!==t&&(n+="-",a.each(this.params,function(){s[this]=o.attr(n+this)}),this.adapt({element:e,form:d,message:t,params:s,rules:r,messages:i}))}),a.extend(r,{__dummy__:!0}),n||t.attachValidation())},parse:function(e){var n=a(e),t=n.parents().addBack().filter("form").add(n.find("form")).has("[data-val=true]");n.find("[data-val=true]").each(function(){f.unobtrusive.parseElement(this,!0)}),t.each(function(){var a=u(this);a&&a.attachValidation()})}},m=f.unobtrusive.adapters,m.add=function(a,e,n){return n||(n=e,e=[]),this.push({name:a,params:e,adapt:n}),this},m.addBool=function(a,n){return this.add(a,function(t){e(t,n||a,!0)})},m.addMinMax=function(a,n,t,r,i,o){return this.add(a,[i||"min",o||"max"],function(a){var i=a.params.min,o=a.params.max;i&&o?e(a,r,[i,o]):i?e(a,n,i):o&&e(a,t,o)})},m.addSingleVal=function(a,n,t){return this.add(a,[n||"val"],function(r){e(r,t||a,r.params[n])})},f.addMethod("__dummy__",function(a,e,n){return!0}),f.addMethod("regex",function(a,e,n){var t;return!!this.optional(e)||(t=new RegExp(n).exec(a),t&&0===t.index&&t[0].length===a.length)}),f.addMethod("nonalphamin",function(a,e,n){var t;return n&&(t=a.match(/\W/g),t=t&&t.length>=n),t}),f.methods.extension?(m.addSingleVal("accept","mimtype"),m.addSingleVal("extension","extension")):m.addSingleVal("extension","extension","accept"),m.addSingleVal("regex","pattern"),m.addBool("creditcard").addBool("date").addBool("digits").addBool("email").addBool("number").addBool("url"),m.addMinMax("length","minlength","maxlength","rangelength").addMinMax("range","min","max","range"),m.addMinMax("minlength","minlength").addMinMax("maxlength","minlength","maxlength"),m.add("equalto",["other"],function(n){var o=r(n.element.name),d=n.params.other,s=i(d,o),l=a(n.form).find(":input").filter("[name='"+t(s)+"']")[0];e(n,"equalTo",l)}),m.add("required",function(a){"INPUT"===a.element.tagName.toUpperCase()&&"CHECKBOX"===a.element.type.toUpperCase()||e(a,"required",!0)}),m.add("remote",["url","type","additionalfields"],function(o){var d={url:o.params.url,type:o.params.type||"GET",data:{}},s=r(o.element.name);a.each(n(o.params.additionalfields||o.element.name),function(e,n){var r=i(n,s);d.data[r]=function(){var e=a(o.form).find(":input").filter("[name='"+t(r)+"']");return e.is(":checkbox")?e.filter(":checked").val()||e.filter(":hidden").val()||"":e.is(":radio")?e.filter(":checked").val()||"":e.val()}}),e(o,"remote",d)}),m.add("password",["min","nonalphamin","regex"],function(a){a.params.min&&e(a,"minlength",a.params.min),a.params.nonalphamin&&e(a,"nonalphamin",a.params.nonalphamin),a.params.regex&&e(a,"regex",a.params.regex)}),m.add("fileextensions",["extensions"],function(a){e(a,"extension",a.params.extensions)}),a(function(){f.unobtrusive.parse(document)}),f.unobtrusive});
--------------------------------------------------------------------------------
/source/wwwroot/lib/jquery-validation/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 | =====================
3 |
4 | Copyright Jörn Zaefferer
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in
14 | all copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | THE SOFTWARE.
23 |
--------------------------------------------------------------------------------
/source/wwwroot/lib/jquery/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright JS Foundation and other contributors, https://js.foundation/
2 |
3 | This software consists of voluntary contributions made by many
4 | individuals. For exact contribution history, see the revision history
5 | available at https://github.com/jquery/jquery
6 |
7 | The following license applies to all parts of this software except as
8 | documented below:
9 |
10 | ====
11 |
12 | Permission is hereby granted, free of charge, to any person obtaining
13 | a copy of this software and associated documentation files (the
14 | "Software"), to deal in the Software without restriction, including
15 | without limitation the rights to use, copy, modify, merge, publish,
16 | distribute, sublicense, and/or sell copies of the Software, and to
17 | permit persons to whom the Software is furnished to do so, subject to
18 | the following conditions:
19 |
20 | The above copyright notice and this permission notice shall be
21 | included in all copies or substantial portions of the Software.
22 |
23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 |
31 | ====
32 |
33 | All files located in the node_modules and external directories are
34 | externally maintained libraries used by this software which have their
35 | own licenses; we recommend you read them, as their terms may differ from
36 | the terms above.
37 |
--------------------------------------------------------------------------------
/storage-account/az-remote-backend-main.tf:
--------------------------------------------------------------------------------
1 | # Generate a random storage name
2 | resource "random_string" "tf-name" {
3 | length = 8
4 | upper = false
5 | numeric = true
6 | lower = true
7 | special = false
8 | }
9 |
10 | # Create a Resource Group for the Terraform State File
11 | resource "azurerm_resource_group" "state-rg" {
12 | name = "${lower(var.company)}-tfstate-rg"
13 | location = var.location
14 |
15 | lifecycle {
16 | prevent_destroy = true
17 | }
18 | tags = {
19 | environment = var.environment
20 | }
21 | }
22 |
23 | # Create a Storage Account for the Terraform State File
24 | resource "azurerm_storage_account" "state-sta" {
25 | depends_on = [azurerm_resource_group.state-rg]
26 | name = "${lower(var.company)}tf${random_string.tf-name.result}"
27 | resource_group_name = azurerm_resource_group.state-rg.name
28 | location = azurerm_resource_group.state-rg.location
29 | account_kind = "StorageV2"
30 | account_tier = "Standard"
31 | access_tier = "Hot"
32 | account_replication_type = "ZRS"
33 | enable_https_traffic_only = true
34 |
35 | lifecycle {
36 | prevent_destroy = true
37 | }
38 | tags = {
39 | environment = var.environment
40 | }
41 | }
42 | # Create a Storage Container for the Core State File
43 | resource "azurerm_storage_container" "core-container" {
44 | depends_on = [azurerm_storage_account.state-sta]
45 | name = "core-tfstate"
46 | storage_account_name = azurerm_storage_account.state-sta.name
47 | }
--------------------------------------------------------------------------------
/storage-account/az-remote-backend-output.tf:
--------------------------------------------------------------------------------
1 | # Resource group name
2 | output "terraform_state_resource_group_name" {
3 | value = azurerm_resource_group.state-rg.name
4 | }
5 |
6 | # Storage account name
7 | output "terraform_state_storage_account" {
8 | value = azurerm_storage_account.state-sta.name
9 | }
10 |
11 | # Container name
12 | output "terraform_state_storage_container_core" {
13 | value = azurerm_storage_container.core-container.name
14 | }
--------------------------------------------------------------------------------
/storage-account/az-remote-backend-variables.tf:
--------------------------------------------------------------------------------
1 | # Company
2 | variable "company" {
3 | type = string
4 | description = "This variable defines the name of the company"
5 | default = "CloudArchitecture"
6 | }
7 | # Environment
8 | variable "environment" {
9 | type = string
10 | description = "This variable defines the environment to be built"
11 | default= "Test"
12 | }
13 | # Azure region
14 | variable "location" {
15 | type = string
16 | description = "Azure region where resources will be created"
17 | default = "West Europe"
18 | }
--------------------------------------------------------------------------------
/storage-account/create-storage-account.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | #Variables
4 | resourceGroupName="StorageAccountsRG"
5 | storageAccountName="baboterraform"
6 | containerName="tfstate"
7 | location="WestEurope"
8 | sku="Standard_LRS"
9 | subscriptionName=$(az account show --query name --output tsv)
10 |
11 | # Create resource group
12 | echo "Checking if [$resourceGroupName] resource group actually exists in the [$subscriptionName] subscription..."
13 | az group show --name $resourceGroupName &>/dev/null
14 |
15 | if [[ $? != 0 ]]; then
16 | echo "No [$resourceGroupName] resource group actually exists in the [$subscriptionName] subscription"
17 | echo "Creating [$resourceGroupName] resource group in the [$subscriptionName] subscription..."
18 |
19 | # Create the resource group
20 | az group create \
21 | --name $resourceGroupName \
22 | --location $location 1>/dev/null
23 |
24 | if [[ $? == 0 ]]; then
25 | echo "[$resourceGroupName] resource group successfully created in the [$subscriptionName] subscription"
26 | else
27 | echo "Failed to create [$resourceGroupName] resource group in the [$subscriptionName] subscription"
28 | exit
29 | fi
30 | else
31 | echo "[$resourceGroupName] resource group already exists in the [$subscriptionName] subscription"
32 | fi
33 |
34 | # Create storage account
35 | echo "Checking if [$storageAccountName] storage account actually exists in the [$subscriptionName] subscription..."
36 | az storage account --name $storageAccountName &>/dev/null
37 |
38 | if [[ $? != 0 ]]; then
39 | echo "No [$storageAccountName] storage account actually exists in the [$subscriptionName] subscription"
40 | echo "Creating [$storageAccountName] storage account in the [$subscriptionName] subscription..."
41 |
42 | az storage account create \
43 | --resource-group $resourceGroupName \
44 | --name $storageAccountName \
45 | --sku $sku \
46 | --encryption-services blob 1>/dev/null
47 |
48 | # Create the storage account
49 | if [[ $? == 0 ]]; then
50 | echo "[$storageAccountName] storage account successfully created in the [$subscriptionName] subscription"
51 | else
52 | echo "Failed to create [$storageAccountName] storage account in the [$subscriptionName] subscription"
53 | exit
54 | fi
55 | else
56 | echo "[$storageAccountName] storage account already exists in the [$subscriptionName] subscription"
57 | fi
58 |
59 | # Get storage account key
60 | echo "Retrieving the primary key of the [$storageAccountName] storage account..."
61 | storageAccountKey=$(az storage account keys list --resource-group $resourceGroupName --account-name $storageAccountName --query [0].value -o tsv)
62 |
63 | if [[ -n $storageAccountKey ]]; then
64 | echo "Primary key of the [$storageAccountName] storage account successfully retrieved"
65 | else
66 | echo "Failed to retrieve the primary key of the [$storageAccountName] storage account"
67 | exit
68 | fi
69 |
70 | # Create blob container
71 | echo "Checking if [$containerName] container actually exists in the [$storageAccountName] storage account..."
72 | az storage container show \
73 | --name $containerName \
74 | --account-name $storageAccountName \
75 | --account-key $storageAccountKey &>/dev/null
76 |
77 | if [[ $? != 0 ]]; then
78 | echo "No [$containerName] container actually exists in the [$storageAccountName] storage account"
79 | echo "Creating [$containerName] container in the [$storageAccountName] storage account..."
80 |
81 | # Create the container
82 | az storage container create \
83 | --name $containerName \
84 | --account-name $storageAccountName \
85 | --account-key $storageAccountKey 1>/dev/null
86 |
87 | if [[ $? == 0 ]]; then
88 | echo "[$containerName] container successfully created in the [$storageAccountName] storage account"
89 | else
90 | echo "Failed to create [$containerName] container in the [$storageAccountName] storage account"
91 | exit
92 | fi
93 | else
94 | echo "[$containerName] container already exists in the [$storageAccountName] storage account"
95 | fi
96 |
97 | # Print data
98 | echo "----------------------------------------------------------------------------------------------"
99 | echo "storageAccountName: $storageAccountName"
100 | echo "containerName: $containerName"
101 | echo "access_key: $storageAccountKey"
102 |
--------------------------------------------------------------------------------
/terraform/backend.conf:
--------------------------------------------------------------------------------
1 | resource_group_name = "StorageAccountsRG"
2 | storage_account_name = "baboterraform"
3 | container_name = "tfstate"
4 | key = "terraform.tfstate"
--------------------------------------------------------------------------------
/terraform/modules/aks/main.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_providers {
3 | azurerm = {
4 | source = "hashicorp/azurerm"
5 | }
6 | }
7 |
8 | required_version = ">= 0.14.9"
9 | }
10 |
11 | resource "azurerm_user_assigned_identity" "aks_identity" {
12 | resource_group_name = var.resource_group_name
13 | location = var.location
14 | tags = var.tags
15 |
16 | name = "${var.name}Identity"
17 |
18 | lifecycle {
19 | ignore_changes = [
20 | tags
21 | ]
22 | }
23 | }
24 |
25 | resource "azurerm_kubernetes_cluster" "aks_cluster" {
26 | name = var.name
27 | location = var.location
28 | resource_group_name = var.resource_group_name
29 | kubernetes_version = var.kubernetes_version
30 | dns_prefix = var.dns_prefix
31 | private_cluster_enabled = var.private_cluster_enabled
32 | automatic_channel_upgrade = var.automatic_channel_upgrade
33 | sku_tier = var.sku_tier
34 | workload_identity_enabled = var.workload_identity_enabled
35 | oidc_issuer_enabled = var.oidc_issuer_enabled
36 | open_service_mesh_enabled = var.open_service_mesh_enabled
37 | image_cleaner_enabled = var.image_cleaner_enabled
38 | azure_policy_enabled = var.azure_policy_enabled
39 | http_application_routing_enabled = var.http_application_routing_enabled
40 |
41 | default_node_pool {
42 | name = var.default_node_pool_name
43 | vm_size = var.default_node_pool_vm_size
44 | vnet_subnet_id = var.vnet_subnet_id
45 | pod_subnet_id = var.pod_subnet_id
46 | zones = var.default_node_pool_availability_zones
47 | node_labels = var.default_node_pool_node_labels
48 | node_taints = var.default_node_pool_node_taints
49 | enable_auto_scaling = var.default_node_pool_enable_auto_scaling
50 | enable_host_encryption = var.default_node_pool_enable_host_encryption
51 | enable_node_public_ip = var.default_node_pool_enable_node_public_ip
52 | max_pods = var.default_node_pool_max_pods
53 | max_count = var.default_node_pool_max_count
54 | min_count = var.default_node_pool_min_count
55 | node_count = var.default_node_pool_node_count
56 | os_disk_type = var.default_node_pool_os_disk_type
57 | tags = var.tags
58 | }
59 |
60 | linux_profile {
61 | admin_username = var.admin_username
62 | ssh_key {
63 | key_data = var.ssh_public_key
64 | }
65 | }
66 |
67 | identity {
68 | type = "UserAssigned"
69 | identity_ids = tolist([azurerm_user_assigned_identity.aks_identity.id])
70 | }
71 |
72 | network_profile {
73 | dns_service_ip = var.network_dns_service_ip
74 | network_plugin = var.network_plugin
75 | outbound_type = var.outbound_type
76 | service_cidr = var.network_service_cidr
77 | }
78 |
79 | oms_agent {
80 | msi_auth_for_monitoring_enabled = true
81 | log_analytics_workspace_id = coalesce(var.oms_agent.log_analytics_workspace_id, var.log_analytics_workspace_id)
82 | }
83 |
84 | dynamic "ingress_application_gateway" {
85 | for_each = try(var.ingress_application_gateway.gateway_id, null) == null ? [] : [1]
86 |
87 | content {
88 | gateway_id = var.ingress_application_gateway.gateway_id
89 | subnet_cidr = var.ingress_application_gateway.subnet_cidr
90 | subnet_id = var.ingress_application_gateway.subnet_id
91 | }
92 | }
93 |
94 | azure_active_directory_role_based_access_control {
95 | managed = true
96 | tenant_id = var.tenant_id
97 | admin_group_object_ids = var.admin_group_object_ids
98 | azure_rbac_enabled = var.azure_rbac_enabled
99 | }
100 |
101 | workload_autoscaler_profile {
102 | keda_enabled = var.keda_enabled
103 | vertical_pod_autoscaler_enabled = var.vertical_pod_autoscaler_enabled
104 | }
105 |
106 | lifecycle {
107 | ignore_changes = [
108 | kubernetes_version,
109 | tags
110 | ]
111 | }
112 | }
113 |
114 | resource "azurerm_monitor_diagnostic_setting" "settings" {
115 | name = "DiagnosticsSettings"
116 | target_resource_id = azurerm_kubernetes_cluster.aks_cluster.id
117 | log_analytics_workspace_id = var.log_analytics_workspace_id
118 |
119 | enabled_log {
120 | category = "kube-apiserver"
121 | }
122 |
123 | enabled_log {
124 | category = "kube-audit"
125 | }
126 |
127 | enabled_log {
128 | category = "kube-audit-admin"
129 | }
130 |
131 | enabled_log {
132 | category = "kube-controller-manager"
133 | }
134 |
135 | enabled_log {
136 | category = "kube-scheduler"
137 | }
138 |
139 | enabled_log {
140 | category = "cluster-autoscaler"
141 | }
142 |
143 | enabled_log {
144 | category = "guard"
145 | }
146 |
147 | metric {
148 | category = "AllMetrics"
149 | }
150 | }
151 |
--------------------------------------------------------------------------------
/terraform/modules/aks/outputs.tf:
--------------------------------------------------------------------------------
1 | output "name" {
2 | value = azurerm_kubernetes_cluster.aks_cluster.name
3 | description = "Specifies the name of the AKS cluster."
4 | }
5 |
6 | output "id" {
7 | value = azurerm_kubernetes_cluster.aks_cluster.id
8 | description = "Specifies the resource id of the AKS cluster."
9 | }
10 |
11 |
12 | output "aks_identity_principal_id" {
13 | value = azurerm_user_assigned_identity.aks_identity.principal_id
14 | description = "Specifies the principal id of the managed identity of the AKS cluster."
15 | }
16 |
17 | output "kubelet_identity_object_id" {
18 | value = azurerm_kubernetes_cluster.aks_cluster.kubelet_identity.0.object_id
19 | description = "Specifies the object id of the kubelet identity of the AKS cluster."
20 | }
21 |
22 | output "kube_config_raw" {
23 | value = azurerm_kubernetes_cluster.aks_cluster.kube_config_raw
24 | description = "Contains the Kubernetes config to be used by kubectl and other compatible tools."
25 | }
26 |
27 | output "private_fqdn" {
28 | value = azurerm_kubernetes_cluster.aks_cluster.private_fqdn
29 | description = "The FQDN for the Kubernetes Cluster when private link has been enabled, which is only resolvable inside the Virtual Network used by the Kubernetes Cluster."
30 | }
31 |
32 | output "node_resource_group" {
33 | value = azurerm_kubernetes_cluster.aks_cluster.node_resource_group
34 | description = "Specifies the resource id of the auto-generated Resource Group which contains the resources for this Managed Kubernetes Cluster."
35 | }
--------------------------------------------------------------------------------
/terraform/modules/bastion_host/main.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_providers {
3 | azurerm = {
4 | source = "hashicorp/azurerm"
5 | }
6 | }
7 |
8 | required_version = ">= 0.14.9"
9 | }
10 |
11 | resource "azurerm_public_ip" "public_ip" {
12 | name = "${var.name}PublicIp"
13 | location = var.location
14 | resource_group_name = var.resource_group_name
15 | allocation_method = "Static"
16 | sku = "Standard"
17 |
18 | lifecycle {
19 | ignore_changes = [
20 | tags
21 | ]
22 | }
23 | }
24 |
25 | resource "azurerm_bastion_host" "bastion_host" {
26 | name = var.name
27 | location = var.location
28 | resource_group_name = var.resource_group_name
29 | tags = var.tags
30 |
31 | ip_configuration {
32 | name = "configuration"
33 | subnet_id = var.subnet_id
34 | public_ip_address_id = azurerm_public_ip.public_ip.id
35 | }
36 |
37 | lifecycle {
38 | ignore_changes = [
39 | tags
40 | ]
41 | }
42 | }
43 |
44 | resource "azurerm_monitor_diagnostic_setting" "settings" {
45 | name = "DiagnosticsSettings"
46 | target_resource_id = azurerm_bastion_host.bastion_host.id
47 | log_analytics_workspace_id = var.log_analytics_workspace_id
48 |
49 | enabled_log {
50 | category = "BastionAuditLogs"
51 | }
52 |
53 | metric {
54 | category = "AllMetrics"
55 | }
56 | }
57 |
58 | resource "azurerm_monitor_diagnostic_setting" "pip_settings" {
59 | name = "DiagnosticsSettings"
60 | target_resource_id = azurerm_public_ip.public_ip.id
61 | log_analytics_workspace_id = var.log_analytics_workspace_id
62 |
63 | enabled_log {
64 | category = "DDoSProtectionNotifications"
65 | }
66 |
67 | enabled_log {
68 | category = "DDoSMitigationFlowLogs"
69 | }
70 |
71 | enabled_log {
72 | category = "DDoSMitigationReports"
73 | }
74 |
75 | metric {
76 | category = "AllMetrics"
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/terraform/modules/bastion_host/output.tf:
--------------------------------------------------------------------------------
1 | output "object" {
2 | depends_on = [azurerm_bastion_host.bastion_host]
3 | value = azurerm_bastion_host.bastion_host
4 | description = "Contains the bastion host resource"
5 | }
6 |
7 | output "name" {
8 | depends_on = [azurerm_bastion_host.bastion_host]
9 | value = azurerm_bastion_host.bastion_host.*.name
10 | description = "Specifies the name of the bastion host"
11 | }
12 |
13 | output "id" {
14 | depends_on = [azurerm_bastion_host.bastion_host]
15 | value = azurerm_bastion_host.bastion_host.*.id
16 | description = "Specifies the resource id of the bastion host"
17 | }
--------------------------------------------------------------------------------
/terraform/modules/bastion_host/variables.tf:
--------------------------------------------------------------------------------
1 | variable "resource_group_name" {
2 | description = "(Required) Specifies the resource group name of the bastion host"
3 | type = string
4 | }
5 |
6 | variable "name" {
7 | description = "(Required) Specifies the name of the bastion host"
8 | type = string
9 | }
10 |
11 | variable "location" {
12 | description = "(Required) Specifies the location of the bastion host"
13 | type = string
14 | }
15 |
16 | variable "tags" {
17 | description = "(Optional) Specifies the tags of the bastion host"
18 | default = {}
19 | }
20 |
21 | variable "subnet_id" {
22 | description = "(Required) Specifies subnet id of the bastion host"
23 | type = string
24 | }
25 |
26 | variable "log_analytics_workspace_id" {
27 | description = "Specifies the log analytics workspace id"
28 | type = string
29 | }
30 |
--------------------------------------------------------------------------------
/terraform/modules/container_registry/main.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_providers {
3 | azurerm = {
4 | source = "hashicorp/azurerm"
5 | }
6 | }
7 |
8 | required_version = ">= 0.14.9"
9 | }
10 |
11 | resource "azurerm_container_registry" "acr" {
12 | name = var.name
13 | resource_group_name = var.resource_group_name
14 | location = var.location
15 | sku = var.sku
16 | admin_enabled = var.admin_enabled
17 | tags = var.tags
18 |
19 | identity {
20 | type = "UserAssigned"
21 | identity_ids = [
22 | azurerm_user_assigned_identity.acr_identity.id
23 | ]
24 | }
25 |
26 | dynamic "georeplications" {
27 | for_each = var.georeplication_locations
28 |
29 | content {
30 | location = georeplications.value
31 | tags = var.tags
32 | }
33 | }
34 |
35 | lifecycle {
36 | ignore_changes = [
37 | tags
38 | ]
39 | }
40 | }
41 |
42 | resource "azurerm_user_assigned_identity" "acr_identity" {
43 | resource_group_name = var.resource_group_name
44 | location = var.location
45 | tags = var.tags
46 |
47 | name = "${var.name}Identity"
48 |
49 | lifecycle {
50 | ignore_changes = [
51 | tags
52 | ]
53 | }
54 | }
55 |
56 | resource "azurerm_monitor_diagnostic_setting" "settings" {
57 | name = "DiagnosticsSettings"
58 | target_resource_id = azurerm_container_registry.acr.id
59 | log_analytics_workspace_id = var.log_analytics_workspace_id
60 |
61 | enabled_log {
62 | category = "ContainerRegistryRepositoryEvents"
63 | }
64 |
65 | enabled_log {
66 | category = "ContainerRegistryLoginEvents"
67 | }
68 |
69 | metric {
70 | category = "AllMetrics"
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/terraform/modules/container_registry/outputs.tf:
--------------------------------------------------------------------------------
1 | output "name" {
2 | description = "Specifies the name of the container registry."
3 | value = azurerm_container_registry.acr.name
4 | }
5 |
6 | output "id" {
7 | description = "Specifies the resource id of the container registry."
8 | value = azurerm_container_registry.acr.id
9 | }
10 |
11 | output "resource_group_name" {
12 | description = "Specifies the name of the resource group."
13 | value = var.resource_group_name
14 | }
15 |
16 | output "login_server" {
17 | description = "Specifies the login server of the container registry."
18 | value = azurerm_container_registry.acr.login_server
19 | }
20 |
21 | output "login_server_url" {
22 | description = "Specifies the login server url of the container registry."
23 | value = "https://${azurerm_container_registry.acr.login_server}"
24 | }
25 |
26 | output "admin_username" {
27 | description = "Specifies the admin username of the container registry."
28 | value = azurerm_container_registry.acr.admin_username
29 | }
30 |
--------------------------------------------------------------------------------
/terraform/modules/container_registry/variables.tf:
--------------------------------------------------------------------------------
1 | variable "name" {
2 | description = "(Required) Specifies the name of the Container Registry. Changing this forces a new resource to be created."
3 | type = string
4 | }
5 |
6 | variable "resource_group_name" {
7 | description = "(Required) The name of the resource group in which to create the Container Registry. Changing this forces a new resource to be created."
8 | type = string
9 | }
10 |
11 | variable "location" {
12 | description = "(Required) Specifies the supported Azure location where the resource exists. Changing this forces a new resource to be created."
13 | type = string
14 | }
15 |
16 | variable "admin_enabled" {
17 | description = "(Optional) Specifies whether the admin user is enabled. Defaults to false."
18 | type = string
19 | default = false
20 | }
21 |
22 | variable "sku" {
23 | description = "(Optional) The SKU name of the container registry. Possible values are Basic, Standard and Premium. Defaults to Basic"
24 | type = string
25 | default = "Basic"
26 |
27 | validation {
28 | condition = contains(["Basic", "Standard", "Premium"], var.sku)
29 | error_message = "The container registry sku is invalid."
30 | }
31 | }
32 |
33 | variable "tags" {
34 | description = "(Optional) A mapping of tags to assign to the resource."
35 | type = map(any)
36 | default = {}
37 | }
38 |
39 | variable "georeplication_locations" {
40 | description = "(Optional) A list of Azure locations where the container registry should be geo-replicated."
41 | type = list(string)
42 | default = []
43 | }
44 |
45 | variable "log_analytics_workspace_id" {
46 | description = "Specifies the log analytics workspace id"
47 | type = string
48 | }
49 |
--------------------------------------------------------------------------------
/terraform/modules/diagnostic_setting/main.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_providers {
3 | azurerm = {
4 | source = "hashicorp/azurerm"
5 | }
6 | }
7 |
8 | required_version = ">= 0.14.9"
9 | }
10 |
11 | resource "azurerm_monitor_diagnostic_setting" "settings" {
12 | name = var.name
13 | target_resource_id = var.target_resource_id
14 |
15 | log_analytics_workspace_id = var.log_analytics_workspace_id
16 | log_analytics_destination_type = var.log_analytics_destination_type
17 |
18 | eventhub_name = var.eventhub_name
19 | eventhub_authorization_rule_id = var.eventhub_authorization_rule_id
20 |
21 | storage_account_id = var.storage_account_id
22 |
23 | dynamic "enabled_log" {
24 | for_each = toset(logs)
25 | content {
26 | category = each.key
27 | }
28 | }
29 |
30 | dynamic "metric" {
31 | for_each = toset(metrics)
32 | content {
33 | category = each.key
34 | enabled = true
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/terraform/modules/diagnostic_setting/outputs.tf:
--------------------------------------------------------------------------------
1 | output "name" {
2 | value = azurerm_key_vault.key_vault.name
3 | description = "Specifies the name of the key vault."
4 | }
5 |
6 | output "id" {
7 | value = azurerm_key_vault.key_vault.id
8 | description = "Specifies the resource id of the key vault."
9 | }
--------------------------------------------------------------------------------
/terraform/modules/diagnostic_setting/variables.tf:
--------------------------------------------------------------------------------
1 |
2 | variable "name" {
3 | description = "(Required) Specifies the name of the Container Registry. Changing this forces a new resource to be created."
4 | type = string
5 | }
6 |
7 | variable "resource_group_name" {
8 | description = "(Required) The name of the resource group in which to create the Container Registry. Changing this forces a new resource to be created."
9 | type = string
10 | }
11 |
12 | variable "location" {
13 | description = "(Required) Specifies the supported Azure location where the resource exists. Changing this forces a new resource to be created."
14 | type = string
15 | }
16 |
17 | variable "target_resource_id" {
18 | description = "(Required) The ID of an existing Resource on which to configure Diagnostic Settings. Changing this forces a new resource to be created."
19 | type = string
20 | }
21 |
22 | variable "log_analytics_workspace_id" {
23 | description = "(Optional) Specifies the ID of a Log Analytics Workspace where Diagnostics Data should be sent."
24 | type = string
25 | }
26 |
27 | variable "log_analytics_destination_type" {
28 | description = "(Optional) When set to 'Dedicated' logs sent to a Log Analytics workspace will go into resource specific tables, instead of the legacy AzureDiagnostics table."
29 | type = string
30 | default = null
31 | }
32 |
33 | variable "storage_account_id" {
34 | description = "(Optional) The ID of the Storage Account where logs should be sent. Changing this forces a new resource to be created."
35 | type = string
36 | default = null
37 | }
38 |
39 | variable "eventhub_name" {
40 | description = "(Optional) Specifies the name of the Event Hub where Diagnostics Data should be sent. Changing this forces a new resource to be created."
41 | type = string
42 | default = null
43 | }
44 |
45 | variable "eventhub_authorization_rule_id" {
46 | description = "(Optional) Specifies the ID of an Event Hub Namespace Authorization Rule used to send Diagnostics Data. Changing this forces a new resource to be created."
47 | type = string
48 | default = null
49 | }
50 |
51 | variable "logs" {
52 | description = "(Optional) Specifies a list of log categories to enable."
53 | type = list(string)
54 | default = []
55 | }
56 |
57 | variable "metrics" {
58 | description = "(Optional) Specifies a list of metrics to enable."
59 | type = list(string)
60 | default = []
61 | }
62 |
63 | variable "tags" {
64 | description = "(Optional) A mapping of tags to assign to the resource."
65 | type = map(any)
66 | default = {}
67 | }
68 |
--------------------------------------------------------------------------------
/terraform/modules/firewall/outputs.tf:
--------------------------------------------------------------------------------
1 | output "private_ip_address" {
2 | description = "Specifies the private IP address of the firewall."
3 | value = azurerm_firewall.firewall.ip_configuration[0].private_ip_address
4 | }
--------------------------------------------------------------------------------
/terraform/modules/firewall/variables.tf:
--------------------------------------------------------------------------------
1 | variable "name" {
2 | description = "Specifies the firewall name"
3 | type = string
4 | }
5 |
6 | variable "sku_name" {
7 | description = "(Required) SKU name of the Firewall. Possible values are AZFW_Hub and AZFW_VNet. Changing this forces a new resource to be created."
8 | default = "AZFW_VNet"
9 | type = string
10 |
11 | validation {
12 | condition = contains(["AZFW_Hub", "AZFW_VNet" ], var.sku_name)
13 | error_message = "The value of the sku name property of the firewall is invalid."
14 | }
15 | }
16 |
17 | variable "sku_tier" {
18 | description = "(Required) SKU tier of the Firewall. Possible values are Premium, Standard, and Basic."
19 | default = "Standard"
20 | type = string
21 |
22 | validation {
23 | condition = contains(["Premium", "Standard", "Basic" ], var.sku_tier)
24 | error_message = "The value of the sku tier property of the firewall is invalid."
25 | }
26 | }
27 |
28 | variable "resource_group_name" {
29 | description = "Specifies the resource group name"
30 | type = string
31 | }
32 |
33 | variable "location" {
34 | description = "Specifies the location where firewall will be deployed"
35 | type = string
36 | }
37 |
38 | variable "threat_intel_mode" {
39 | description = "(Optional) The operation mode for threat intelligence-based filtering. Possible values are: Off, Alert, Deny. Defaults to Alert."
40 | default = "Alert"
41 | type = string
42 |
43 | validation {
44 | condition = contains(["Off", "Alert", "Deny"], var.threat_intel_mode)
45 | error_message = "The threat intel mode is invalid."
46 | }
47 | }
48 |
49 | variable "zones" {
50 | description = "Specifies the availability zones of the Azure Firewall"
51 | default = ["1", "2", "3"]
52 | type = list(string)
53 | }
54 |
55 | variable "pip_name" {
56 | description = "Specifies the firewall public IP name"
57 | type = string
58 | default = "azure-fw-ip"
59 | }
60 |
61 | variable "subnet_id" {
62 | description = "Subnet ID"
63 | type = string
64 | }
65 |
66 | variable "tags" {
67 | description = "(Optional) Specifies the tags of the storage account"
68 | default = {}
69 | }
70 |
71 | variable "log_analytics_workspace_id" {
72 | description = "Specifies the log analytics workspace id"
73 | type = string
74 | }
75 |
--------------------------------------------------------------------------------
/terraform/modules/key_vault/main.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_providers {
3 | azurerm = {
4 | source = "hashicorp/azurerm"
5 | }
6 | }
7 |
8 | required_version = ">= 0.14.9"
9 | }
10 |
11 | resource "azurerm_key_vault" "key_vault" {
12 | name = var.name
13 | location = var.location
14 | resource_group_name = var.resource_group_name
15 | tenant_id = var.tenant_id
16 | sku_name = var.sku_name
17 | tags = var.tags
18 | enabled_for_deployment = var.enabled_for_deployment
19 | enabled_for_disk_encryption = var.enabled_for_disk_encryption
20 | enabled_for_template_deployment = var.enabled_for_template_deployment
21 | enable_rbac_authorization = var.enable_rbac_authorization
22 | purge_protection_enabled = var.purge_protection_enabled
23 | soft_delete_retention_days = var.soft_delete_retention_days
24 |
25 | timeouts {
26 | delete = "60m"
27 | }
28 |
29 | network_acls {
30 | bypass = var.bypass
31 | default_action = var.default_action
32 | ip_rules = var.ip_rules
33 | virtual_network_subnet_ids = var.virtual_network_subnet_ids
34 | }
35 |
36 | lifecycle {
37 | ignore_changes = [
38 | tags
39 | ]
40 | }
41 | }
42 |
43 | resource "azurerm_monitor_diagnostic_setting" "settings" {
44 | name = "DiagnosticsSettings"
45 | target_resource_id = azurerm_key_vault.key_vault.id
46 | log_analytics_workspace_id = var.log_analytics_workspace_id
47 |
48 | enabled_log {
49 | category = "AuditEvent"
50 | }
51 |
52 | enabled_log {
53 | category = "AzurePolicyEvaluationDetails"
54 | }
55 |
56 | metric {
57 | category = "AllMetrics"
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/terraform/modules/key_vault/outputs.tf:
--------------------------------------------------------------------------------
1 | output "name" {
2 | value = azurerm_key_vault.key_vault.name
3 | description = "Specifies the name of the key vault."
4 | }
5 |
6 | output "id" {
7 | value = azurerm_key_vault.key_vault.id
8 | description = "Specifies the resource id of the key vault."
9 | }
--------------------------------------------------------------------------------
/terraform/modules/key_vault/variables.tf:
--------------------------------------------------------------------------------
1 | variable "name" {
2 | description = "(Required) Specifies the name of the key vault."
3 | type = string
4 | }
5 |
6 | variable "resource_group_name" {
7 | description = "(Required) Specifies the resource group name of the key vault."
8 | type = string
9 | }
10 |
11 | variable "location" {
12 | description = "(Required) Specifies the location where the key vault will be deployed."
13 | type = string
14 | }
15 |
16 | variable "tenant_id" {
17 | description = "(Required) The Microsoft Entra ID tenant ID that should be used for authenticating requests to the key vault."
18 | type = string
19 | }
20 |
21 | variable "sku_name" {
22 | description = "(Required) The Name of the SKU used for this Key Vault. Possible values are standard and premium."
23 | type = string
24 | default = "standard"
25 |
26 | validation {
27 | condition = contains(["standard", "premium" ], var.sku_name)
28 | error_message = "The value of the sku name property of the key vault is invalid."
29 | }
30 | }
31 |
32 | variable "tags" {
33 | description = "(Optional) Specifies the tags of the log analytics workspace"
34 | type = map(any)
35 | default = {}
36 | }
37 |
38 | variable "enabled_for_deployment" {
39 | description = "(Optional) Boolean flag to specify whether Azure Virtual Machines are permitted to retrieve certificates stored as secrets from the key vault. Defaults to false."
40 | type = bool
41 | default = false
42 | }
43 |
44 | variable "enabled_for_disk_encryption" {
45 | description = " (Optional) Boolean flag to specify whether Azure Disk Encryption is permitted to retrieve secrets from the vault and unwrap keys. Defaults to false."
46 | type = bool
47 | default = false
48 | }
49 |
50 | variable "enabled_for_template_deployment" {
51 | description = "(Optional) Boolean flag to specify whether Azure Resource Manager is permitted to retrieve secrets from the key vault. Defaults to false."
52 | type = bool
53 | default = false
54 | }
55 |
56 | variable "enable_rbac_authorization" {
57 | description = "(Optional) Boolean flag to specify whether Azure Key Vault uses Role Based Access Control (RBAC) for authorization of data actions. Defaults to false."
58 | type = bool
59 | default = false
60 | }
61 |
62 | variable "purge_protection_enabled" {
63 | description = "(Optional) Is Purge Protection enabled for this Key Vault? Defaults to false."
64 | type = bool
65 | default = false
66 | }
67 |
68 | variable "soft_delete_retention_days" {
69 | description = "(Optional) The number of days that items should be retained for once soft-deleted. This value can be between 7 and 90 (the default) days."
70 | type = number
71 | default = 30
72 | }
73 |
74 | variable "bypass" {
75 | description = "(Required) Specifies which traffic can bypass the network rules. Possible values are AzureServices and None."
76 | type = string
77 | default = "AzureServices"
78 |
79 | validation {
80 | condition = contains(["AzureServices", "None" ], var.bypass)
81 | error_message = "The valut of the bypass property of the key vault is invalid."
82 | }
83 | }
84 |
85 | variable "default_action" {
86 | description = "(Required) The Default Action to use when no rules match from ip_rules / virtual_network_subnet_ids. Possible values are Allow and Deny."
87 | type = string
88 | default = "Allow"
89 |
90 | validation {
91 | condition = contains(["Allow", "Deny" ], var.default_action)
92 | error_message = "The value of the default action property of the key vault is invalid."
93 | }
94 | }
95 |
96 | variable "ip_rules" {
97 | description = "(Optional) One or more IP Addresses, or CIDR Blocks which should be able to access the Key Vault."
98 | default = []
99 | }
100 |
101 | variable "virtual_network_subnet_ids" {
102 | description = "(Optional) One or more Subnet ID's which should be able to access this Key Vault."
103 | default = []
104 | }
105 |
106 | variable "log_analytics_workspace_id" {
107 | description = "Specifies the log analytics workspace id"
108 | type = string
109 | }
110 |
--------------------------------------------------------------------------------
/terraform/modules/log_analytics/main.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_providers {
3 | azurerm = {
4 | source = "hashicorp/azurerm"
5 | }
6 | }
7 |
8 | required_version = ">= 0.14.9"
9 | }
10 |
11 | locals {
12 | module_tag = {
13 | "module" = basename(abspath(path.module))
14 | }
15 | tags = merge(var.tags, local.module_tag)
16 | }
17 |
18 | resource "azurerm_log_analytics_workspace" "log_analytics_workspace" {
19 | name = var.name
20 | location = var.location
21 | resource_group_name = var.resource_group_name
22 | sku = var.sku
23 | tags = local.tags
24 | retention_in_days = var.retention_in_days != "" ? var.retention_in_days : null
25 |
26 | lifecycle {
27 | ignore_changes = [
28 | tags
29 | ]
30 | }
31 | }
32 |
33 | resource "azurerm_log_analytics_solution" "la_solution" {
34 | for_each = var.solution_plan_map
35 |
36 | solution_name = each.key
37 | location = var.location
38 | resource_group_name = var.resource_group_name
39 | workspace_resource_id = azurerm_log_analytics_workspace.log_analytics_workspace.id
40 | workspace_name = azurerm_log_analytics_workspace.log_analytics_workspace.name
41 |
42 | plan {
43 | product = each.value.product
44 | publisher = each.value.publisher
45 | }
46 |
47 | lifecycle {
48 | ignore_changes = [
49 | tags
50 | ]
51 | }
52 | }
--------------------------------------------------------------------------------
/terraform/modules/log_analytics/output.tf:
--------------------------------------------------------------------------------
1 | output "id" {
2 | value = azurerm_log_analytics_workspace.log_analytics_workspace.id
3 | description = "Specifies the resource id of the log analytics workspace"
4 | }
5 |
6 | output "location" {
7 | value = azurerm_log_analytics_workspace.log_analytics_workspace.location
8 | description = "Specifies the location of the log analytics workspace"
9 | }
10 |
11 | output "name" {
12 | value = azurerm_log_analytics_workspace.log_analytics_workspace.name
13 | description = "Specifies the name of the log analytics workspace"
14 | }
15 |
16 | output "resource_group_name" {
17 | value = azurerm_log_analytics_workspace.log_analytics_workspace.resource_group_name
18 | description = "Specifies the name of the resource group that contains the log analytics workspace"
19 | }
20 |
21 | output "workspace_id" {
22 | value = azurerm_log_analytics_workspace.log_analytics_workspace.workspace_id
23 | description = "Specifies the workspace id of the log analytics workspace"
24 | }
25 |
26 | output "primary_shared_key" {
27 | value = azurerm_log_analytics_workspace.log_analytics_workspace.primary_shared_key
28 | description = "Specifies the workspace key of the log analytics workspace"
29 | sensitive = true
30 | }
31 |
--------------------------------------------------------------------------------
/terraform/modules/log_analytics/variables.tf:
--------------------------------------------------------------------------------
1 | variable "resource_group_name" {
2 | description = "(Required) Specifies the resource group name"
3 | type = string
4 | }
5 |
6 | variable "location" {
7 | description = "(Required) Specifies the location of the log analytics workspace"
8 | type = string
9 | }
10 |
11 | variable "name" {
12 | description = "(Required) Specifies the name of the log analytics workspace"
13 | type = string
14 | }
15 |
16 | variable "sku" {
17 | description = "(Optional) Specifies the sku of the log analytics workspace"
18 | type = string
19 | default = "PerGB2018"
20 |
21 | validation {
22 | condition = contains(["Free", "Standalone", "PerNode", "PerGB2018"], var.sku)
23 | error_message = "The log analytics sku is incorrect."
24 | }
25 | }
26 |
27 | variable "solution_plan_map" {
28 | description = "(Optional) Specifies the map structure containing the list of solutions to be enabled."
29 | type = map(any)
30 | default = {}
31 | }
32 |
33 | variable "tags" {
34 | description = "(Optional) Specifies the tags of the log analytics workspace"
35 | type = map(any)
36 | default = {}
37 | }
38 |
39 | variable "retention_in_days" {
40 | description = " (Optional) Specifies the workspace data retention in days. Possible values are either 7 (Free Tier only) or range between 30 and 730."
41 | type = number
42 | default = 30
43 | }
--------------------------------------------------------------------------------
/terraform/modules/network_security_group/main.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_providers {
3 | azurerm = {
4 | source = "hashicorp/azurerm"
5 | }
6 | }
7 |
8 | required_version = ">= 0.14.9"
9 | }
10 |
11 | resource "azurerm_network_security_group" "nsg" {
12 | name = var.name
13 | resource_group_name = var.resource_group_name
14 | location = var.location
15 | tags = var.tags
16 |
17 | dynamic "security_rule" {
18 | for_each = try(var.security_rules, [])
19 | content {
20 | name = try(security_rule.value.name, null)
21 | priority = try(security_rule.value.priority, null)
22 | direction = try(security_rule.value.direction, null)
23 | access = try(security_rule.value.access, null)
24 | protocol = try(security_rule.value.protocol, null)
25 | source_port_range = try(security_rule.value.source_port_range, null)
26 | source_port_ranges = try(security_rule.value.source_port_ranges, null)
27 | destination_port_range = try(security_rule.value.destination_port_range, null)
28 | destination_port_ranges = try(security_rule.value.destination_port_ranges, null)
29 | source_address_prefix = try(security_rule.value.source_address_prefix, null)
30 | source_address_prefixes = try(security_rule.value.source_address_prefixes, null)
31 | destination_address_prefix = try(security_rule.value.destination_address_prefix, null)
32 | destination_address_prefixes = try(security_rule.value.destination_address_prefixes, null)
33 | source_application_security_group_ids = try(security_rule.value.source_application_security_group_ids, null)
34 | destination_application_security_group_ids = try(security_rule.value.destination_application_security_group_ids, null)
35 | }
36 | }
37 |
38 | lifecycle {
39 | ignore_changes = [
40 | tags
41 | ]
42 | }
43 | }
44 |
45 | resource "azurerm_monitor_diagnostic_setting" "settings" {
46 | name = "DiagnosticsSettings"
47 | target_resource_id = azurerm_network_security_group.nsg.id
48 | log_analytics_workspace_id = var.log_analytics_workspace_id
49 |
50 | enabled_log {
51 | category = "NetworkSecurityGroupEvent"
52 | }
53 |
54 | enabled_log {
55 | category = "NetworkSecurityGroupRuleCounter"
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/terraform/modules/network_security_group/outputs.tf:
--------------------------------------------------------------------------------
1 | output "id" {
2 | description = "Specifies the resource id of the network security group"
3 | value = azurerm_network_security_group.nsg.id
4 | }
--------------------------------------------------------------------------------
/terraform/modules/network_security_group/variables.tf:
--------------------------------------------------------------------------------
1 | variable "name" {
2 | description = "(Required) Specifies the name of the network security group"
3 | type = string
4 | }
5 |
6 | variable "resource_group_name" {
7 | description = "(Required) Specifies the resource group name of the network security group"
8 | type = string
9 | }
10 |
11 | variable "location" {
12 | description = "(Required) Specifies the location of the network security group"
13 | type = string
14 | }
15 |
16 | variable "security_rules" {
17 | description = "(Optional) Specifies the security rules of the network security group"
18 | type = list(object)
19 | default = []
20 | }
21 |
22 | variable "tags" {
23 | description = "(Optional) Specifies the tags of the network security group"
24 | default = {}
25 | }
26 |
27 | variable "log_analytics_workspace_id" {
28 | description = "Specifies the log analytics workspace resource id"
29 | type = string
30 | }
31 |
--------------------------------------------------------------------------------
/terraform/modules/node_pool/main.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_providers {
3 | azurerm = {
4 | source = "hashicorp/azurerm"
5 | }
6 | }
7 |
8 | required_version = ">= 0.14.9"
9 | }
10 |
11 | resource "azurerm_kubernetes_cluster_node_pool" "node_pool" {
12 | kubernetes_cluster_id = var.kubernetes_cluster_id
13 | name = var.name
14 | vm_size = var.vm_size
15 | mode = var.mode
16 | node_labels = var.node_labels
17 | node_taints = var.node_taints
18 | zones = var.availability_zones
19 | vnet_subnet_id = var.vnet_subnet_id
20 | pod_subnet_id = var.pod_subnet_id
21 | enable_auto_scaling = var.enable_auto_scaling
22 | enable_host_encryption = var.enable_host_encryption
23 | enable_node_public_ip = var.enable_node_public_ip
24 | proximity_placement_group_id = var.proximity_placement_group_id
25 | orchestrator_version = var.orchestrator_version
26 | max_pods = var.max_pods
27 | max_count = var.max_count
28 | min_count = var.min_count
29 | node_count = var.node_count
30 | os_disk_size_gb = var.os_disk_size_gb
31 | os_disk_type = var.os_disk_type
32 | os_type = var.os_type
33 | priority = var.priority
34 | tags = var.tags
35 |
36 | lifecycle {
37 | ignore_changes = [
38 | tags
39 | ]
40 | }
41 | }
--------------------------------------------------------------------------------
/terraform/modules/node_pool/outputs.tf:
--------------------------------------------------------------------------------
1 | output "id" {
2 | description = "Specifies the resource id of the node pool"
3 | value = azurerm_kubernetes_cluster_node_pool.node_pool.id
4 | }
--------------------------------------------------------------------------------
/terraform/modules/node_pool/variables.tf:
--------------------------------------------------------------------------------
1 | variable "name" {
2 | description = "(Required) Specifies the name of the node pool."
3 | type = string
4 | }
5 |
6 | variable "kubernetes_cluster_id" {
7 | description = "(Required) Specifies the resource id of the AKS cluster."
8 | type = string
9 | }
10 |
11 | variable "vm_size" {
12 | description = "(Required) The SKU which should be used for the Virtual Machines used in this Node Pool. Changing this forces a new resource to be created."
13 | type = string
14 | }
15 |
16 | variable "availability_zones" {
17 | description = "(Optional) A list of Availability Zones where the Nodes in this Node Pool should be created in. Changing this forces a new resource to be created."
18 | type = list(string)
19 | default = ["1", "2", "3"]
20 | }
21 |
22 | variable "enable_auto_scaling" {
23 | description = "(Optional) Whether to enable auto-scaler. Defaults to false."
24 | type = bool
25 | default = false
26 | }
27 |
28 | variable "enable_host_encryption" {
29 | description = "(Optional) Should the nodes in this Node Pool have host encryption enabled? Defaults to false."
30 | type = bool
31 | default = false
32 | }
33 |
34 | variable "enable_node_public_ip" {
35 | description = "(Optional) Should each node have a Public IP Address? Defaults to false. Changing this forces a new resource to be created."
36 | type = bool
37 | default = false
38 | }
39 |
40 | variable "max_pods" {
41 | description = "(Optional) The maximum number of pods that can run on each agent. Changing this forces a new resource to be created."
42 | type = number
43 | default = 250
44 | }
45 |
46 | variable "mode" {
47 | description = "(Optional) Should this Node Pool be used for System or User resources? Possible values are System and User. Defaults to User."
48 | type = string
49 | default = "User"
50 | }
51 |
52 | variable "node_labels" {
53 | description = "(Optional) A map of Kubernetes labels which should be applied to nodes in this Node Pool. Changing this forces a new resource to be created."
54 | type = map(any)
55 | default = {}
56 | }
57 |
58 | variable "node_taints" {
59 | description = "(Optional) A list of Kubernetes taints which should be applied to nodes in the agent pool (e.g key=value:NoSchedule). Changing this forces a new resource to be created."
60 | type = list(string)
61 | default = []
62 | }
63 |
64 | variable "tags" {
65 | description = "(Optional) Specifies the tags of the network security group"
66 | default = {}
67 | }
68 |
69 | variable "orchestrator_version" {
70 | description = "(Optional) Version of Kubernetes used for the Agents. If not specified, the latest recommended version will be used at provisioning time (but won't auto-upgrade)"
71 | type = string
72 | default = null
73 | }
74 |
75 | variable "os_disk_size_gb" {
76 | description = "(Optional) The Agent Operating System disk size in GB. Changing this forces a new resource to be created."
77 | type = number
78 | default = null
79 | }
80 |
81 | variable "os_disk_type" {
82 | description = "(Optional) The type of disk which should be used for the Operating System. Possible values are Ephemeral and Managed. Defaults to Managed. Changing this forces a new resource to be created."
83 | type = string
84 | default = "Ephemeral"
85 | }
86 |
87 | variable "os_type" {
88 | description = "(Optional) The Operating System which should be used for this Node Pool. Changing this forces a new resource to be created. Possible values are Linux and Windows. Defaults to Linux."
89 | type = string
90 | default = "Linux"
91 | }
92 |
93 | variable "priority" {
94 | description = "(Optional) The Priority for Virtual Machines within the Virtual Machine Scale Set that powers this Node Pool. Possible values are Regular and Spot. Defaults to Regular. Changing this forces a new resource to be created."
95 | type = string
96 | default = "Regular"
97 | }
98 |
99 | variable "proximity_placement_group_id" {
100 | description = "(Optional) The ID of the Proximity Placement Group where the Virtual Machine Scale Set that powers this Node Pool will be placed. Changing this forces a new resource to be created."
101 | type = string
102 | default = null
103 | }
104 |
105 | variable "vnet_subnet_id" {
106 | description = "(Optional) The ID of the Subnet where this Node Pool should exist."
107 | type = string
108 | default = null
109 | }
110 |
111 | variable "pod_subnet_id" {
112 | description = "(Optional) The ID of the Subnet where the pods in the default Node Pool should exist. Changing this forces a new resource to be created."
113 | type = string
114 | default = null
115 | }
116 |
117 | variable "max_count" {
118 | description = "(Required) The maximum number of nodes which should exist within this Node Pool. Valid values are between 0 and 1000 and must be greater than or equal to min_count."
119 | type = number
120 | default = 10
121 | }
122 |
123 | variable "min_count" {
124 | description = "(Required) The minimum number of nodes which should exist within this Node Pool. Valid values are between 0 and 1000 and must be less than or equal to max_count."
125 | type = number
126 | default = 3
127 | }
128 |
129 | variable "node_count" {
130 | description = "(Optional) The initial number of nodes which should exist within this Node Pool. Valid values are between 0 and 1000 and must be a value in the range min_count - max_count."
131 | type = number
132 | default = 3
133 | }
134 |
135 | variable resource_group_name {
136 | description = "Specifies the resource group name"
137 | type = string
138 | }
139 |
140 | variable "oidc_issuer_enabled" {
141 | description = " (Optional) Enable or Disable the OIDC issuer URL."
142 | type = bool
143 | default = true
144 | }
145 |
--------------------------------------------------------------------------------
/terraform/modules/private_dns_zone/main.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_providers {
3 | azurerm = {
4 | source = "hashicorp/azurerm"
5 | }
6 | }
7 |
8 | required_version = ">= 0.14.9"
9 | }
10 |
11 | resource "azurerm_private_dns_zone" "private_dns_zone" {
12 | name = var.name
13 | resource_group_name = var.resource_group_name
14 | tags = var.tags
15 |
16 | lifecycle {
17 | ignore_changes = [
18 | tags
19 | ]
20 | }
21 | }
22 |
23 | resource "azurerm_private_dns_zone_virtual_network_link" "link" {
24 | for_each = var.virtual_networks_to_link
25 |
26 | name = "link_to_${lower(basename(each.key))}"
27 | resource_group_name = var.resource_group_name
28 | private_dns_zone_name = azurerm_private_dns_zone.private_dns_zone.name
29 | virtual_network_id = "/subscriptions/${each.value.subscription_id}/resourceGroups/${each.value.resource_group_name}/providers/Microsoft.Network/virtualNetworks/${each.key}"
30 |
31 | lifecycle {
32 | ignore_changes = [
33 | tags
34 | ]
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/terraform/modules/private_dns_zone/outputs.tf:
--------------------------------------------------------------------------------
1 | output "id" {
2 | description = "Specifies the resource id of the private dns zone"
3 | value = azurerm_private_dns_zone.private_dns_zone.id
4 | }
--------------------------------------------------------------------------------
/terraform/modules/private_dns_zone/variables.tf:
--------------------------------------------------------------------------------
1 | variable "name" {
2 | description = "(Required) Specifies the name of the private dns zone"
3 | type = string
4 | }
5 |
6 | variable "resource_group_name" {
7 | description = "(Required) Specifies the resource group name of the private dns zone"
8 | type = string
9 | }
10 |
11 | variable "tags" {
12 | description = "(Optional) Specifies the tags of the private dns zone"
13 | default = {}
14 | }
15 |
16 | variable "virtual_networks_to_link" {
17 | description = "(Optional) Specifies the subscription id, resource group name, and name of the virtual networks to which create a virtual network link"
18 | type = map(any)
19 | default = {}
20 | }
--------------------------------------------------------------------------------
/terraform/modules/private_endpoint/main.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_providers {
3 | azurerm = {
4 | source = "hashicorp/azurerm"
5 | }
6 | }
7 |
8 | required_version = ">= 0.14.9"
9 | }
10 |
11 | resource "azurerm_private_endpoint" "private_endpoint" {
12 | name = var.name
13 | location = var.location
14 | resource_group_name = var.resource_group_name
15 | subnet_id = var.subnet_id
16 | tags = var.tags
17 |
18 | private_service_connection {
19 | name = "${var.name}Connection"
20 | private_connection_resource_id = var.private_connection_resource_id
21 | is_manual_connection = var.is_manual_connection
22 | subresource_names = try([var.subresource_name], null)
23 | request_message = try(var.request_message, null)
24 | }
25 |
26 | private_dns_zone_group {
27 | name = var.private_dns_zone_group_name
28 | private_dns_zone_ids = var.private_dns_zone_group_ids
29 | }
30 |
31 | lifecycle {
32 | ignore_changes = [
33 | tags
34 | ]
35 | }
36 | }
--------------------------------------------------------------------------------
/terraform/modules/private_endpoint/outputs.tf:
--------------------------------------------------------------------------------
1 | output "id" {
2 | description = "Specifies the resource id of the private endpoint."
3 | value = azurerm_private_endpoint.private_endpoint.id
4 | }
5 |
6 | output "private_dns_zone_group" {
7 | description = "Specifies the private dns zone group of the private endpoint."
8 | value = azurerm_private_endpoint.private_endpoint.private_dns_zone_group
9 | }
10 |
11 | output "private_dns_zone_configs" {
12 | description = "Specifies the private dns zone(s) configuration"
13 | value = azurerm_private_endpoint.private_endpoint.private_dns_zone_configs
14 | }
--------------------------------------------------------------------------------
/terraform/modules/private_endpoint/variables.tf:
--------------------------------------------------------------------------------
1 | variable "name" {
2 | description = "(Required) Specifies the name of the private endpoint. Changing this forces a new resource to be created."
3 | type = string
4 | }
5 |
6 | variable "resource_group_name" {
7 | description = "(Required) The name of the resource group. Changing this forces a new resource to be created."
8 | type = string
9 | }
10 |
11 | variable "private_connection_resource_id" {
12 | description = "(Required) Specifies the resource id of the private link service"
13 | type = string
14 | }
15 |
16 | variable "location" {
17 | description = "(Required) Specifies the supported Azure location where the resource exists. Changing this forces a new resource to be created."
18 | type = string
19 | }
20 |
21 | variable "subnet_id" {
22 | description = "(Required) Specifies the resource id of the subnet"
23 | type = string
24 | }
25 |
26 | variable "is_manual_connection" {
27 | description = "(Optional) Specifies whether the private endpoint connection requires manual approval from the remote resource owner."
28 | type = string
29 | default = false
30 | }
31 |
32 | variable "subresource_name" {
33 | description = "(Optional) Specifies a subresource name which the Private Endpoint is able to connect to."
34 | type = string
35 | default = null
36 | }
37 |
38 | variable "request_message" {
39 | description = "(Optional) Specifies a message passed to the owner of the remote resource when the private endpoint attempts to establish the connection to the remote resource."
40 | type = string
41 | default = null
42 | }
43 |
44 | variable "private_dns_zone_group_name" {
45 | description = "(Required) Specifies the Name of the Private DNS Zone Group. Changing this forces a new private_dns_zone_group resource to be created."
46 | type = string
47 | }
48 |
49 | variable "private_dns_zone_group_ids" {
50 | description = "(Required) Specifies the list of Private DNS Zones to include within the private_dns_zone_group."
51 | type = list(string)
52 | }
53 |
54 | variable "tags" {
55 | description = "(Optional) Specifies the tags of the network security group"
56 | default = {}
57 | }
58 |
59 | variable "private_dns" {
60 | default = {}
61 | }
--------------------------------------------------------------------------------
/terraform/modules/route_table/main.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_providers {
3 | azurerm = {
4 | source = "hashicorp/azurerm"
5 | }
6 | }
7 |
8 | required_version = ">= 0.14.9"
9 | }
10 |
11 | data "azurerm_client_config" "current" {
12 | }
13 |
14 | resource "azurerm_route_table" "rt" {
15 | name = var.route_table_name
16 | location = var.location
17 | resource_group_name = var.resource_group_name
18 | tags = var.tags
19 |
20 | route {
21 | name = "kubenetfw_fw_r"
22 | address_prefix = "0.0.0.0/0"
23 | next_hop_type = "VirtualAppliance"
24 | next_hop_in_ip_address = var.firewall_private_ip
25 | }
26 |
27 | lifecycle {
28 | ignore_changes = [
29 | tags,
30 | route
31 | ]
32 | }
33 | }
34 |
35 | resource "azurerm_subnet_route_table_association" "subnet_association" {
36 | for_each = var.subnets_to_associate
37 |
38 | subnet_id = "/subscriptions/${each.value.subscription_id}/resourceGroups/${each.value.resource_group_name}/providers/Microsoft.Network/virtualNetworks/${each.value.virtual_network_name}/subnets/${each.key}"
39 | route_table_id = azurerm_route_table.rt.id
40 | }
--------------------------------------------------------------------------------
/terraform/modules/route_table/variables.tf:
--------------------------------------------------------------------------------
1 | variable "resource_group_name" {
2 | description = "Resource group where RouteTable will be deployed"
3 | type = string
4 | }
5 |
6 | variable "location" {
7 | description = "Location where RouteTable will be deployed"
8 | type = string
9 | }
10 |
11 | variable "route_table_name" {
12 | description = "RouteTable name"
13 | type = string
14 | }
15 |
16 | variable "route_name" {
17 | description = "AKS route name"
18 | type = string
19 | }
20 |
21 | variable "firewall_private_ip" {
22 | description = "Firewall private IP"
23 | type = string
24 | }
25 |
26 | variable "subnets_to_associate" {
27 | description = "(Optional) Specifies the subscription id, resource group name, and name of the subnets to associate"
28 | type = map(any)
29 | default = {}
30 | }
31 |
32 | variable "tags" {
33 | description = "(Optional) Specifies the tags of the storage account"
34 | default = {}
35 | }
--------------------------------------------------------------------------------
/terraform/modules/storage_account/main.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_providers {
3 | azurerm = {
4 | source = "hashicorp/azurerm"
5 | }
6 | }
7 |
8 | required_version = ">= 0.14.9"
9 | }
10 |
11 | resource "azurerm_storage_account" "storage_account" {
12 | name = var.name
13 | resource_group_name = var.resource_group_name
14 |
15 | location = var.location
16 | account_kind = var.account_kind
17 | account_tier = var.account_tier
18 | account_replication_type = var.replication_type
19 | is_hns_enabled = var.is_hns_enabled
20 | tags = var.tags
21 |
22 | network_rules {
23 | default_action = (length(var.ip_rules) + length(var.virtual_network_subnet_ids)) > 0 ? "Deny" : var.default_action
24 | ip_rules = var.ip_rules
25 | virtual_network_subnet_ids = var.virtual_network_subnet_ids
26 | }
27 |
28 | identity {
29 | type = "SystemAssigned"
30 | }
31 |
32 | lifecycle {
33 | ignore_changes = [
34 | tags
35 | ]
36 | }
37 | }
--------------------------------------------------------------------------------
/terraform/modules/storage_account/outputs.tf:
--------------------------------------------------------------------------------
1 | output "name" {
2 | description = "Specifies the name of the storage account"
3 | value = azurerm_storage_account.storage_account.name
4 | }
5 |
6 | output "id" {
7 | description = "Specifies the resource id of the storage account"
8 | value = azurerm_storage_account.storage_account.id
9 | }
10 |
11 | output "primary_access_key" {
12 | description = "Specifies the primary access key of the storage account"
13 | value = azurerm_storage_account.storage_account.primary_access_key
14 | }
15 |
16 | output "principal_id" {
17 | description = "Specifies the principal id of the system assigned managed identity of the storage account"
18 | value = azurerm_storage_account.storage_account.identity[0].principal_id
19 | }
20 |
21 | output "primary_blob_endpoint" {
22 | description = "Specifies the primary blob endpoint of the storage account"
23 | value = azurerm_storage_account.storage_account.primary_blob_endpoint
24 | }
--------------------------------------------------------------------------------
/terraform/modules/storage_account/variables.tf:
--------------------------------------------------------------------------------
1 | variable "resource_group_name" {
2 | description = "(Required) Specifies the resource group name of the storage account"
3 | type = string
4 | }
5 |
6 | variable "name" {
7 | description = "(Required) Specifies the name of the storage account"
8 | type = string
9 | }
10 |
11 | variable "location" {
12 | description = "(Required) Specifies the location of the storage account"
13 | type = string
14 | }
15 |
16 | variable "account_kind" {
17 | description = "(Optional) Specifies the account kind of the storage account"
18 | default = "StorageV2"
19 | type = string
20 |
21 | validation {
22 | condition = contains(["Storage", "StorageV2"], var.account_kind)
23 | error_message = "The account kind of the storage account is invalid."
24 | }
25 | }
26 |
27 | variable "account_tier" {
28 | description = "(Optional) Specifies the account tier of the storage account"
29 | default = "Standard"
30 | type = string
31 |
32 | validation {
33 | condition = contains(["Standard", "Premium"], var.account_tier)
34 | error_message = "The account tier of the storage account is invalid."
35 | }
36 | }
37 |
38 | variable "replication_type" {
39 | description = "(Optional) Specifies the replication type of the storage account"
40 | default = "LRS"
41 | type = string
42 |
43 | validation {
44 | condition = contains(["LRS", "ZRS", "GRS", "GZRS", "RA-GRS", "RA-GZRS"], var.replication_type)
45 | error_message = "The replication type of the storage account is invalid."
46 | }
47 | }
48 |
49 | variable "is_hns_enabled" {
50 | description = "(Optional) Specifies the replication type of the storage account"
51 | default = false
52 | type = bool
53 | }
54 |
55 | variable "default_action" {
56 | description = "Allow or disallow public access to all blobs or containers in the storage accounts. The default interpretation is true for this property."
57 | default = "Allow"
58 | type = string
59 | }
60 |
61 | variable "ip_rules" {
62 | description = "Specifies IP rules for the storage account"
63 | default = []
64 | type = list(string)
65 | }
66 |
67 | variable "virtual_network_subnet_ids" {
68 | description = "Specifies a list of resource ids for subnets"
69 | default = []
70 | type = list(string)
71 | }
72 |
73 | variable "kind" {
74 | description = "(Optional) Specifies the kind of the storage account"
75 | default = ""
76 | }
77 |
78 | variable "tags" {
79 | description = "(Optional) Specifies the tags of the storage account"
80 | default = {}
81 | }
--------------------------------------------------------------------------------
/terraform/modules/virtual_machine/outputs.tf:
--------------------------------------------------------------------------------
1 | output "public_ip" {
2 | description = "Specifies the public IP address of the virtual machine"
3 | value = azurerm_linux_virtual_machine.virtual_machine.public_ip_address
4 | }
5 |
6 | output "username" {
7 | description = "Specifies the username of the virtual machine"
8 | value = var.vm_user
9 | }
10 |
--------------------------------------------------------------------------------
/terraform/modules/virtual_machine/variables.tf:
--------------------------------------------------------------------------------
1 | variable resource_group_name {
2 | description = "(Required) Specifies the resource group name of the virtual machine"
3 | type = string
4 | }
5 |
6 | variable name {
7 | description = "(Required) Specifies the name of the virtual machine"
8 | type = string
9 | }
10 |
11 | variable size {
12 | description = "(Required) Specifies the size of the virtual machine"
13 | type = string
14 | }
15 |
16 | variable "os_disk_image" {
17 | type = map(string)
18 | description = "(Optional) Specifies the os disk image of the virtual machine"
19 | default = {
20 | publisher = "Canonical"
21 | offer = "0001-com-ubuntu-server-jammy"
22 | sku = "22_04-lts-gen2"
23 | version = "latest"
24 | }
25 | }
26 |
27 | variable "os_disk_storage_account_type" {
28 | description = "(Optional) Specifies the storage account type of the os disk of the virtual machine"
29 | default = "StandardSSD_LRS"
30 | type = string
31 |
32 | validation {
33 | condition = contains(["Premium_LRS", "Premium_ZRS", "StandardSSD_LRS", "StandardSSD_ZRS", "Standard_LRS"], var.os_disk_storage_account_type)
34 | error_message = "The storage account type of the OS disk is invalid."
35 | }
36 | }
37 |
38 | variable public_ip {
39 | description = "(Optional) Specifies whether create a public IP for the virtual machine"
40 | type = bool
41 | default = false
42 | }
43 |
44 | variable location {
45 | description = "(Required) Specifies the location of the virtual machine"
46 | type = string
47 | }
48 |
49 | variable domain_name_label {
50 | description = "(Required) Specifies the DNS domain name of the virtual machine"
51 | type = string
52 | }
53 |
54 | variable subnet_id {
55 | description = "(Required) Specifies the resource id of the subnet hosting the virtual machine"
56 | type = string
57 | }
58 |
59 | variable vm_user {
60 | description = "(Required) Specifies the username of the virtual machine"
61 | type = string
62 | default = "azadmin"
63 | }
64 |
65 | variable "boot_diagnostics_storage_account" {
66 | description = "(Optional) The Primary/Secondary Endpoint for the Azure Storage Account (general purpose) which should be used to store Boot Diagnostics, including Console Output and Screenshots from the Hypervisor."
67 | default = null
68 | }
69 |
70 | variable "tags" {
71 | description = "(Optional) Specifies the tags of the storage account"
72 | default = {}
73 | }
74 |
75 | variable "log_analytics_workspace_id" {
76 | description = "Specifies the log analytics workspace id"
77 | type = string
78 | }
79 |
80 | variable "log_analytics_workspace_key" {
81 | description = "Specifies the log analytics workspace key"
82 | type = string
83 | }
84 |
85 | variable "log_analytics_workspace_resource_id" {
86 | description = "Specifies the log analytics workspace resource id"
87 | type = string
88 | }
89 |
90 |
91 | variable "admin_ssh_public_key" {
92 | description = "Specifies the public SSH key"
93 | type = string
94 | }
95 |
96 | variable "script_storage_account_name" {
97 | description = "(Required) Specifies the name of the storage account that contains the custom script."
98 | type = string
99 | }
100 |
101 | variable "script_storage_account_key" {
102 | description = "(Required) Specifies the name of the storage account that contains the custom script."
103 | type = string
104 | }
105 |
106 | variable "container_name" {
107 | description = "(Required) Specifies the name of the container that contains the custom script."
108 | type = string
109 | }
110 |
111 | variable "script_name" {
112 | description = "(Required) Specifies the name of the custom script."
113 | type = string
114 | }
115 |
--------------------------------------------------------------------------------
/terraform/modules/virtual_network/main.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_providers {
3 | azurerm = {
4 | source = "hashicorp/azurerm"
5 | }
6 | }
7 |
8 | required_version = ">= 0.14.9"
9 | }
10 |
11 | resource "azurerm_virtual_network" "vnet" {
12 | name = var.vnet_name
13 | address_space = var.address_space
14 | location = var.location
15 | resource_group_name = var.resource_group_name
16 | tags = var.tags
17 |
18 | lifecycle {
19 | ignore_changes = [
20 | tags
21 | ]
22 | }
23 | }
24 |
25 | resource "azurerm_subnet" "subnet" {
26 | for_each = { for subnet in var.subnets : subnet.name => subnet }
27 |
28 | name = each.key
29 | resource_group_name = var.resource_group_name
30 | virtual_network_name = azurerm_virtual_network.vnet.name
31 | address_prefixes = each.value.address_prefixes
32 | private_endpoint_network_policies_enabled = each.value.private_endpoint_network_policies_enabled
33 | private_link_service_network_policies_enabled = each.value.private_link_service_network_policies_enabled
34 | }
35 |
36 | resource "azurerm_monitor_diagnostic_setting" "settings" {
37 | name = "DiagnosticsSettings"
38 | target_resource_id = azurerm_virtual_network.vnet.id
39 | log_analytics_workspace_id = var.log_analytics_workspace_id
40 |
41 | enabled_log {
42 | category = "VMProtectionAlerts"
43 | }
44 |
45 | metric {
46 | category = "AllMetrics"
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/terraform/modules/virtual_network/outputs.tf:
--------------------------------------------------------------------------------
1 | output name {
2 | description = "Specifies the name of the virtual network"
3 | value = azurerm_virtual_network.vnet.name
4 | }
5 |
6 | output vnet_id {
7 | description = "Specifies the resource id of the virtual network"
8 | value = azurerm_virtual_network.vnet.id
9 | }
10 |
11 | output subnet_ids {
12 | description = "Contains a list of the the resource id of the subnets"
13 | value = { for subnet in azurerm_subnet.subnet : subnet.name => subnet.id }
14 | }
--------------------------------------------------------------------------------
/terraform/modules/virtual_network/variables.tf:
--------------------------------------------------------------------------------
1 | variable "resource_group_name" {
2 | description = "Resource Group name"
3 | type = string
4 | }
5 |
6 | variable "location" {
7 | description = "Location in which to deploy the network"
8 | type = string
9 | }
10 |
11 | variable "vnet_name" {
12 | description = "VNET name"
13 | type = string
14 | }
15 |
16 | variable "address_space" {
17 | description = "VNET address space"
18 | type = list(string)
19 | }
20 |
21 | variable "subnets" {
22 | description = "Subnets configuration"
23 | type = list(object({
24 | name = string
25 | address_prefixes = list(string)
26 | private_endpoint_network_policies_enabled = bool
27 | private_link_service_network_policies_enabled = bool
28 | }))
29 | }
30 |
31 | variable "tags" {
32 | description = "(Optional) Specifies the tags of the storage account"
33 | default = {}
34 | }
35 |
36 | variable "log_analytics_workspace_id" {
37 | description = "Specifies the log analytics workspace id"
38 | type = string
39 | }
40 |
--------------------------------------------------------------------------------
/terraform/modules/virtual_network_peering/main.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_providers {
3 | azurerm = {
4 | source = "hashicorp/azurerm"
5 | version = "~>3.50.0"
6 | }
7 | }
8 |
9 | required_version = ">= 0.14.9"
10 | }
11 |
12 | resource "azurerm_virtual_network_peering" "peering" {
13 | name = var.peering_name_1_to_2
14 | resource_group_name = var.vnet_1_rg
15 | virtual_network_name = var.vnet_1_name
16 | remote_virtual_network_id = var.vnet_2_id
17 | allow_virtual_network_access = true
18 | allow_forwarded_traffic = true
19 | }
20 |
21 | resource "azurerm_virtual_network_peering" "peering-back" {
22 | name = var.peering_name_2_to_1
23 | resource_group_name = var.vnet_2_rg
24 | virtual_network_name = var.vnet_2_name
25 | remote_virtual_network_id = var.vnet_1_id
26 | allow_virtual_network_access = true
27 | allow_forwarded_traffic = true
28 | }
--------------------------------------------------------------------------------
/terraform/modules/virtual_network_peering/variables.tf:
--------------------------------------------------------------------------------
1 | variable "vnet_1_name" {
2 | description = "Specifies the name of the first virtual network"
3 | type = string
4 | }
5 |
6 | variable "vnet_1_id" {
7 | description = "Specifies the resource id of the first virtual network"
8 | type = string
9 | }
10 |
11 | variable "vnet_1_rg" {
12 | description = "Specifies the resource group name of the first virtual network"
13 | type = string
14 | }
15 |
16 | variable "vnet_2_name" {
17 | description = "Specifies the name of the second virtual network"
18 | type = string
19 | }
20 |
21 | variable "vnet_2_id" {
22 | description = "Specifies the resource id of the second virtual network"
23 | type = string
24 | }
25 |
26 | variable "vnet_2_rg" {
27 | description = "Specifies the resource group name of the second virtual network"
28 | type = string
29 | }
30 |
31 | variable "peering_name_1_to_2" {
32 | description = "(Optional) Specifies the name of the first to second virtual network peering"
33 | type = string
34 | default = "peering1to2"
35 | }
36 |
37 | variable "peering_name_2_to_1" {
38 | description = "(Optional) Specifies the name of the second to first virtual network peering"
39 | type = string
40 | default = "peering2to1"
41 | }
--------------------------------------------------------------------------------
/terraform/outputs.tf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Azure-Samples/private-aks-cluster-terraform-devops/8bb51322e82bec3f9ab6457ac80633165e1afa3b/terraform/outputs.tf
--------------------------------------------------------------------------------
/terraform/scripts/configure-jumpbox-vm.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Eliminate debconf warnings
4 | echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections
5 |
6 | # Update the system
7 | sudo apt-get update -y
8 |
9 | # Upgrade packages
10 | sudo apt-get upgrade -y
11 |
12 | # Install kubectl (latest)
13 | sudo curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl &&
14 | chmod +x ./kubectl &&
15 | mv ./kubectl /usr/local/bin/kubectl
16 |
17 | # Install helm v3 (latest)
18 | sudo curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 &&
19 | chmod 700 get_helm.sh &&
20 | ./get_helm.sh
21 |
22 | # Install Azure CLI (latest)
23 | curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
--------------------------------------------------------------------------------
/tfvars/agent/agent.tfvars:
--------------------------------------------------------------------------------
1 | vm_name="BabosbirdAdoAgentVm"
2 | log_analytics_workspace_name="BabosbirdAksWorkspace"
3 | log_analytics_resource_group_name="BabosbirdRG"
4 | virtual_network_resource_group_name="BabosbirdRG"
5 | virtual_network_name="BabosbirdAksVNet"
6 | subnet_name="VmSubnet"
--------------------------------------------------------------------------------
/tfvars/production/production.tfvars:
--------------------------------------------------------------------------------
1 | resource_group_name = "ContosoProdRG"
2 | aks_cluster_name = "ContosoProdAks"
3 | log_analytics_workspace_name = "ContosoProdAksWorkspace"
4 | domain_name_label = "contosoprodtestvm"
5 | firewall_name = "ContosoProdFirewall"
6 | acr_name = "ContosoProdAcr"
7 | bastion_host_name = "ContosoProdBastionHost"
8 | key_vault_name = "ContosoProdAksKeyVault"
9 | vm_name = "ContosoProdVm"
10 | hub_vnet_name = "ContosoProdHubVNet"
11 | aks_vnet_name = "ContosoProdAksVNet"
--------------------------------------------------------------------------------
/tfvars/staging/staging.tfvars:
--------------------------------------------------------------------------------
1 | resource_group_name = "ContosoStagRG"
2 | aks_cluster_name = "ContosoStagAks"
3 | log_analytics_workspace_name = "ContosoStagAksWorkspace"
4 | domain_name_label = "contosostagestvm"
5 | firewall_name = "ContosoStagFirewall"
6 | acr_name = "ContosoStagAcr"
7 | bastion_host_name = "ContosoStagBastionHost"
8 | key_vault_name = "ContosoStagAksKeyVault"
9 | vm_name = "ContosoStagVm"
10 | hub_vnet_name = "ContosoStagHubVNet"
11 | aks_vnet_name = "ContosoStagAksVNet"
--------------------------------------------------------------------------------
/tfvars/test/test.tfvars:
--------------------------------------------------------------------------------
1 | resource_group_name = "ContosoTestRG"
2 | aks_cluster_name = "ContosoTestAks"
3 | log_analytics_workspace_name = "ContosoTestAksWorkspace"
4 | domain_name_label = "contosotesttestvm"
5 | firewall_name = "ContosoTestFirewall"
6 | acr_name = "ContosoTestAcr"
7 | bastion_host_name = "ContosoTestBastionHost"
8 | key_vault_name = "ContosoTestAksKeyVault"
9 | hub_vnet_name = "ContosoTestHubVNet"
10 | aks_vnet_name = "ContosoTestAksVNet"
--------------------------------------------------------------------------------
/visio/architecture.vsdx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Azure-Samples/private-aks-cluster-terraform-devops/8bb51322e82bec3f9ab6457ac80633165e1afa3b/visio/architecture.vsdx
--------------------------------------------------------------------------------