Skip to content

Commit

Permalink
Merge pull request mspnp#21 from mspnp/dev
Browse files Browse the repository at this point in the history
2023-09-19 - BryanSoltis - v3.1.0 Updates
  • Loading branch information
BryanSoltis authored Sep 20, 2023
2 parents 5f077c5 + 55dbab5 commit 4c2d1f8
Show file tree
Hide file tree
Showing 33 changed files with 645 additions and 292 deletions.
29 changes: 23 additions & 6 deletions src/Attributes/ApiKeyAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,31 @@ public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionE
var config = ConfigurationHelper.GetConfigurationData();
if (GeneralHelper.IsNotNull(config))
{
if (!GeneralHelper.DecryptString(config.APIKey!, config.SALTKey!).Equals(extractedApiKey))
// Determine if the request is read-only
if (context.HttpContext.Request.Method == "GET")
{
context.Result = new ContentResult()
if ((!GeneralHelper.DecryptString(config.APIKey!, config.SALTKey!).Equals(extractedApiKey)) && (!GeneralHelper.DecryptString(config.ReadOnlyAPIKey!, config.SALTKey!).Equals(extractedApiKey)))
{
StatusCode = 401,
Content = "Api Key is not valid!"
};
return;
context.Result = new ContentResult()
{
StatusCode = 401,
Content = "Api Key is not valid!"
};
return;
}
}
else
{
// Request is a POST. Make sure the provided API Key is for full access
if (!GeneralHelper.DecryptString(config.APIKey!, config.SALTKey!).Equals(extractedApiKey))
{
context.Result = new ContentResult()
{
StatusCode = 401,
Content = "Full Access Api Key is not valid!"
};
return;
}
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/AzureNamingTool.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<Version>3.0.2</Version>
<Version>3.1.0</Version>
<TargetFramework>net7.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
Expand Down Expand Up @@ -63,7 +63,7 @@
<PackageReference Include="BlazorDownloadFile" Version="2.4.0.2" />
<PackageReference Include="Blazored.Modal" Version="7.1.0" />
<PackageReference Include="Blazored.Toast" Version="4.1.0" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.18.1" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.19.5" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="6.5.0" />
<PackageReference Include="System.Collections" Version="4.3.0" />
Expand Down
93 changes: 85 additions & 8 deletions src/Controllers/AdminController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,9 @@ public async Task<IActionResult> UpdatePassword([BindRequired][FromHeader(Name =

// POST api/<AdminController>
/// <summary>
/// This function will update the API Key.
/// This function will update the Full Access API Key.
/// </summary>
/// <param name="apikey">string - New API Key</param>
/// <param name="apikey">string - New Full Access API Key</param>
/// <param name="adminpassword">string - Current Global Admin Password</param>
/// <returns>dttring - Successful update</returns>
[HttpPost]
Expand All @@ -79,8 +79,8 @@ public async Task<IActionResult> UpdateAPIKey([BindRequired][FromHeader(Name = "
{
if (adminpassword == GeneralHelper.DecryptString(config.AdminPassword!, config.SALTKey!))
{
serviceResponse = await AdminService.UpdateAPIKey(apikey);
return (serviceResponse.Success ? Ok("SUCCESS") : Ok("FAILURE - There was a problem updating the API Key."));
serviceResponse = await AdminService.UpdateAPIKey(apikey, "fullaccess");
return (serviceResponse.Success ? Ok("SUCCESS") : Ok("FAILURE - There was a problem updating the Full Access API Key."));
}
else
{
Expand All @@ -102,10 +102,10 @@ public async Task<IActionResult> UpdateAPIKey([BindRequired][FromHeader(Name = "

// POST api/<AdminController>
/// <summary>
/// This function will generate a new API Key.
/// This function will generate a new Full Access API Key.
/// </summary>
/// <param name="adminpassword">string - Current Global Admin Password</param>
/// <returns>string - Successful update / Generated API Key</returns>
/// <returns>string - Successful update / Generated Full Access API Key</returns>

[HttpPost]
[Route("[action]")]
Expand All @@ -118,8 +118,85 @@ public async Task<IActionResult> GenerateAPIKey([BindRequired][FromHeader(Name =
{
if (adminpassword == GeneralHelper.DecryptString(config.AdminPassword!, config.SALTKey!))
{
serviceResponse = await AdminService.GenerateAPIKey();
return (serviceResponse.Success ? Ok("SUCCESS") : Ok("FAILURE - There was a problem generating the API Key."));
serviceResponse = await AdminService.GenerateAPIKey("fullaccess");
return (serviceResponse.Success ? Ok("SUCCESS") : Ok("FAILURE - There was a problem generating the Full Access API Key."));
}
else
{
return Ok("FAILURE - Incorrect Global Admin Password.");
}

}
else
{
return Ok("FAILURE - You must provide the Global Admin Password.");
}
}
catch (Exception ex)
{
AdminLogService.PostItem(new AdminLogMessage() { Title = "ERROR", Message = ex.Message });
return BadRequest(ex);
}
}

// POST api/<AdminController>
/// <summary>
/// This function will update the Read-Only API Key.
/// </summary>
/// <param name="apikey">string - New Read-Only API Key</param>
/// <param name="adminpassword">string - Current Global Admin Password</param>
/// <returns>dttring - Successful update</returns>
[HttpPost]
[Route("[action]")]
public async Task<IActionResult> UpdateReadOnlyAPIKey([BindRequired][FromHeader(Name = "AdminPassword")] string adminpassword, [FromBody] string apikey)
{
ServiceResponse serviceResponse = new();
try
{
if (GeneralHelper.IsNotNull(adminpassword))
{
if (adminpassword == GeneralHelper.DecryptString(config.AdminPassword!, config.SALTKey!))
{
serviceResponse = await AdminService.UpdateAPIKey(apikey, "readonly");
return (serviceResponse.Success ? Ok("SUCCESS") : Ok("FAILURE - There was a problem updating the Read-Only API Key."));
}
else
{
return Ok("FAILURE - Incorrect Global Admin Password.");
}

}
else
{
return Ok("FAILURE - You must provide the Global Admin Password.");
}
}
catch (Exception ex)
{
AdminLogService.PostItem(new AdminLogMessage() { Title = "ERROR", Message = ex.Message });
return BadRequest(ex);
}
}

// POST api/<AdminController>
/// <summary>
/// This function will generate a new Read-Only API Key.
/// </summary>
/// <param name="adminpassword">string - Current Global Admin Password</param>
/// <returns>string - Successful update / Generated Read-Only API Key</returns>
[HttpPost]
[Route("[action]")]
public async Task<IActionResult> GenerateReadOnlyAPIKey([BindRequired][FromHeader(Name = "AdminPassword")] string adminpassword)
{
ServiceResponse serviceResponse = new();
try
{
if (GeneralHelper.IsNotNull(adminpassword))
{
if (adminpassword == GeneralHelper.DecryptString(config.AdminPassword!, config.SALTKey!))
{
serviceResponse = await AdminService.GenerateAPIKey("readonly");
return (serviceResponse.Success ? Ok("SUCCESS") : Ok("FAILURE - There was a problem generating the Read-Only API Key."));
}
else
{
Expand Down
4 changes: 2 additions & 2 deletions src/Helpers/CacheHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,13 @@ public static string GetAllCacheData()
var cacheKeys = memoryCache.Select(kvp => kvp.Key).ToList();
foreach (var key in cacheKeys.OrderBy(x => x))
{
data.Append("<p><strong>" + key + "</strong></p><div class=\"alert alert-secondary\" style=\"word-wrap:break-word;\">" + MemoryCache.Default[key].ToString() + "</div>");
data.Append("<p><span class=\"fw-bold\">" + key + "</span></p><div class=\"alert alert-secondary\" style=\"word-wrap:break-word;\">" + MemoryCache.Default[key].ToString() + "</div>");
}
}
catch (Exception ex)
{
AdminLogService.PostItem(new AdminLogMessage() { Title = "ERROR", Message = ex.Message });
data.Append("<p><strong>No data currently cached.</strong></p>");
data.Append("<p><span class=\"fw-bold\">No data currently cached.</span></p>");
}
return data.ToString();
}
Expand Down
83 changes: 40 additions & 43 deletions src/Helpers/ConfigurationHelper.cs
Original file line number Diff line number Diff line change
@@ -1,21 +1,13 @@
using AzureNamingTool.Models;
using System.Text.Json.Serialization;
using System.Text.Json;
using AzureNamingTool.Services;
using System.Xml.Linq;
using System.Net.NetworkInformation;
using System.Collections;
using System.Data.SqlTypes;
using System.Net;
using System.Runtime.Caching;
using System.Net.NetworkInformation;
using System.Reflection;
using System.Net.Http;
using System.Text;
using System.Net.Http.Json;
using System.Net.Http.Headers;
using System;
using Blazored.Toast.Services;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Collections;
using System.Runtime.Caching;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace AzureNamingTool.Helpers
{
Expand Down Expand Up @@ -158,6 +150,7 @@ public static async void VerifySecurity(StateContainer state)

config.SALTKey = salt.ToString();
config.APIKey = GeneralHelper.EncryptString(config.APIKey!, salt.ToString());
config.ReadOnlyAPIKey = GeneralHelper.EncryptString(config.ReadOnlyAPIKey!, salt.ToString());

if (!String.IsNullOrEmpty(config.AdminPassword))
{
Expand Down Expand Up @@ -468,13 +461,13 @@ public static async Task<List<string>> VerifyConfigurationFileVersionData()
// Resource Types
if (officialversiondata.resourcetypes != currentversiondata.resourcetypes)
{
versiondata.Add("<h5>Resource Types</h5><hr /><div>The Resource Types Configuration is out of date!<br /><br />It is recommended that you refresh your resource types to the latest configuration.<br /><br /><strong>To Refresh:</strong><ul><li>Expand the <strong>Types</strong> section</li><li>Expand the <strong>Configuration</strong> section</li><li>Select the <strong>Refresh</strong> option</li></ul></div><br />");
versiondata.Add("<h5>Resource Types</h5><hr /><div>The Resource Types Configuration is out of date!<br /><br />It is recommended that you refresh your resource types to the latest configuration.<br /><br /><span class=\"fw-bold\">To Refresh:</span><ul><li>Expand the <span class=\"fw-bold\">Types</span> section</li><li>Expand the <span class=\"fw-bold\">Configuration</span> section</li><li>Select the <span class=\"fw-bold\">Refresh</span> option</li></ul></div><br />");
}

// Resource Locations
if (officialversiondata.resourcelocations != currentversiondata.resourcelocations)
{
versiondata.Add("<h5>Resource Locations</h5><hr /><div>The Resource Locations Configuration is out of date!<br /><br />It is recommended that you refresh your resource locations to the latest configuration.<br /><br /><strong>To Refresh:</strong><ul><li>Expand the <strong>Locations</strong> section</li><li>Expand the <strong>Configuration</strong> section</li><li>Select the <strong>Refresh</strong> option</li></ul></div><br />");
versiondata.Add("<h5>Resource Locations</h5><hr /><div>The Resource Locations Configuration is out of date!<br /><br />It is recommended that you refresh your resource locations to the latest configuration.<br /><br /><span class=\"fw-bold\">To Refresh:</span><ul><li>Expand the <span class=\"fw-bold\">Locations</span> section</li><li>Expand the <span class=\"fw-bold\">Configuration</span> section</li><li>Select the <span class=\"fw-bold\">Refresh</span> option</li></ul></div><br />");
}
}
}
Expand Down Expand Up @@ -670,33 +663,6 @@ public static void DismissVersionAlert()
}
}

public static bool VerifyDuplicateNamesAllowed()
{
bool result = false;
try
{
// Check if the data is cached
var cacheddata = CacheHelper.GetCacheObject("duplicatenamesallowed");
if (cacheddata == null)
{
// Check if version alert has been dismissed
var allowed = GetAppSetting("DuplicateNamesAllowed");
result = Convert.ToBoolean(allowed);
// Set the result to cache
CacheHelper.SetCacheObject("duplicatenamesallowed", result);
}
else
{
result = Convert.ToBoolean(cacheddata);
}
}
catch (Exception ex)
{
AdminLogService.PostItem(new AdminLogMessage() { Title = "ERROR", Message = ex.Message });
}
return result;
}

public static async Task<bool> PostToGenerationWebhook(string URL, GeneratedName generatedName)
{
bool result = false;
Expand Down Expand Up @@ -855,5 +821,36 @@ public static List<KeyValuePair<string,string>> GetEnvironmentVariables()
}
return result;
}


public static async Task<bool> CheckIfGeneratedNameExists(string name)
{
bool nameexists = false;
// Check if the name already exists
ServiceResponse serviceResponse = new();
serviceResponse = await GeneratedNamesService.GetItems();
if (serviceResponse.Success)
{
if (GeneralHelper.IsNotNull(serviceResponse.ResponseObject))
{
var names = (List<GeneratedName>)serviceResponse.ResponseObject!;
if (GeneralHelper.IsNotNull(names))
{
if (names.Where(x => x.ResourceName == name).Any())
{
nameexists = true;
}
}
}
}
return nameexists;
}

public static string AutoIncremenetResourceInstance(string resourcetype)
{
string resourcetypeupdated = String.Empty;

return resourcetypeupdated;
}
}
}
17 changes: 11 additions & 6 deletions src/Helpers/GeneralHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -121,31 +121,36 @@ public static string SetTextEnabledClass(bool enabled)

public static bool IsNotNull([NotNullWhen(true)] object? obj) => obj != null;


public static string[] FormatResoureType(string type)
{
String[] returntype = new String[3];
String[] returntype = new String[4];
returntype[0] = type;
// Make sure it is a full resource type name
if (type.Contains("("))
if (type.Contains('('))
{
returntype[0] = type.Substring(0, type.IndexOf("(")).Trim();
returntype[0] = type[..type.IndexOf("(")].Trim();
}
try
{
if ((GeneralHelper.IsNotNull(type)) && (GeneralHelper.IsNotNull(returntype[0])))
{
// trim any details out of the value
// Get the base resource type name
if (returntype[0].Contains(" -"))
{
returntype[1] = returntype[0].Substring(0, returntype[0].IndexOf(" -")).Trim();
// Get all text before the dash
returntype[1] = returntype[0][..returntype[0].IndexOf(" -")].Trim();
// Get all text after the dash
returntype[3] = returntype[0].Substring(returntype[0].IndexOf("-") + 1).Trim();
}

// trim any details out of the value
if ((type.Contains("(")) && (type.Contains(")")))
if (type.Contains('(') && type.Contains(')'))
{
{
int intstart = type.IndexOf("(") + 1;
returntype[2] = String.Concat(type.Substring(intstart).TakeWhile(x => x != ')'));
returntype[2] = String.Concat(type[intstart..].TakeWhile(x => x != ')'));
}
}
}
Expand Down
8 changes: 5 additions & 3 deletions src/Models/ConfigurationData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,13 @@ public class ConfigurationData
public string? SALTKey { get; set; }
public string? AdminPassword { get; set; }
public string? APIKey { get; set; }
public string? ReadOnlyAPIKey { get; set; }
public string? DismissedAlerts { get; set; }
public string? DuplicateNamesAllowed { get; set; }
public string? DuplicateNamesAllowed { get; set; } = "False";
public string? GenerationWebhook { get; set; }
public string? ConnectivityCheckEnabled { get; set; }
public string? ConnectivityCheckEnabled { get; set; } = "True";
public string? IdentityHeaderName { get; set; }
public string? ResourceTypeEditingAllowed { get; set; }
public string? ResourceTypeEditingAllowed { get; set; } = "False";
public string? AutoIncrementResourceInstance { get; set; } = "False";
}
}
1 change: 1 addition & 0 deletions src/Models/GeneratedName.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ public class GeneratedName
public string ResourceTypeName { get; set; } = String.Empty;
public List<string[]> Components { get; set; } = new();
public string User { get; set; } = "General";
public string? Message { get; set; }
}
}
Loading

0 comments on commit 4c2d1f8

Please sign in to comment.