aboutsummaryrefslogtreecommitdiff
path: root/plugins/VNLib.Plugins.Essentials.Accounts/src
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/VNLib.Plugins.Essentials.Accounts/src')
-rw-r--r--plugins/VNLib.Plugins.Essentials.Accounts/src/AccountsEntryPoint.cs59
-rw-r--r--plugins/VNLib.Plugins.Essentials.Accounts/src/Endpoints/LoginEndpoint.cs4
-rw-r--r--plugins/VNLib.Plugins.Essentials.Accounts/src/Endpoints/PkiLoginEndpoint.cs6
-rw-r--r--plugins/VNLib.Plugins.Essentials.Accounts/src/SecurityProvider/AccountSecProvider.cs3
4 files changed, 66 insertions, 6 deletions
diff --git a/plugins/VNLib.Plugins.Essentials.Accounts/src/AccountsEntryPoint.cs b/plugins/VNLib.Plugins.Essentials.Accounts/src/AccountsEntryPoint.cs
index 96b56b4..5f171cd 100644
--- a/plugins/VNLib.Plugins.Essentials.Accounts/src/AccountsEntryPoint.cs
+++ b/plugins/VNLib.Plugins.Essentials.Accounts/src/AccountsEntryPoint.cs
@@ -26,6 +26,8 @@ using System;
using System.Text.Json;
using System.ComponentModel.Design;
+using FluentValidation.Results;
+
using VNLib.Utils;
using VNLib.Utils.Memory;
using VNLib.Utils.Logging;
@@ -46,14 +48,14 @@ namespace VNLib.Plugins.Essentials.Accounts
public override string PluginName => "Essentials.Accounts";
- private bool SetupMode => PluginConfig.TryGetProperty("setup_mode", out JsonElement el) && el.GetBoolean();
+ private bool SetupMode => HostArgs.HasArgument("--account-setup");
private AccountSecProvider? _securityProvider;
[ServiceConfigurator]
public void ConfigureServices(IServiceContainer services)
{
- //Export the build in security provider
+ //Export the built in security provider and add it as a middleware item as well
if (_securityProvider != null)
{
services.AddService(typeof(IAccountSecurityProvider), _securityProvider);
@@ -164,6 +166,7 @@ Commands:
disable-mfa -u <username> Disable a user's MFA configuration
enable-totp -u <username> -s <base32 secret> Enable TOTP MFA for a user
set-privilege -u <username> -l <priv level> Set a user's privilege level
+ add-pubkey -u <username> Add a JWK public key to a user's profile
help Display this help message
";
Log.Information(help, PluginName);
@@ -309,6 +312,58 @@ Commands:
Log.Information("Successfully set TOTP secret for {id}", username);
}
break;
+ case "add-pubkey":
+ {
+
+ if (string.IsNullOrWhiteSpace(username))
+ {
+ Log.Warn("You are missing required argument values. Format 'add-pubkey -u <username>");
+ break;
+ }
+
+ Console.WriteLine("Enter public key JWK...");
+
+ //Wait for pubkey
+ string? pubkeyJwk = Console.ReadLine();
+
+ if(string.IsNullOrWhiteSpace(pubkeyJwk))
+ {
+ Log.Warn("No public key supplied.");
+ break;
+ }
+
+ //Get user
+ using IUser? user = await Users.GetUserFromEmailAsync(username);
+
+ if (user == null)
+ {
+ Log.Warn("The specified user does not exist");
+ break;
+ }
+
+ PkiAuthPublicKey? pubkey = JsonSerializer.Deserialize<PkiAuthPublicKey>(pubkeyJwk);
+ if (pubkey == null)
+ {
+ Log.Error("You public key is not a JSON object");
+ break;
+ }
+
+ //Validate
+ ValidationResult res = PkiLoginEndpoint.UserJwkValidator.Validate(pubkey);
+ if (!res.IsValid)
+ {
+ Log.Error("The public key JWK is not valid:\n{errors}", res.ToDictionary());
+ break;
+ }
+
+
+ //Add/update the public key and flush changes
+ user.PKIAddPublicKey(pubkey);
+ await user.ReleaseAsync();
+
+ Log.Information("Successfully set TOTP secret for {id}", username);
+ }
+ break;
case "set-privilege":
{
if (username == null)
diff --git a/plugins/VNLib.Plugins.Essentials.Accounts/src/Endpoints/LoginEndpoint.cs b/plugins/VNLib.Plugins.Essentials.Accounts/src/Endpoints/LoginEndpoint.cs
index b01cc3d..66a099e 100644
--- a/plugins/VNLib.Plugins.Essentials.Accounts/src/Endpoints/LoginEndpoint.cs
+++ b/plugins/VNLib.Plugins.Essentials.Accounts/src/Endpoints/LoginEndpoint.cs
@@ -80,8 +80,8 @@ namespace VNLib.Plugins.Essentials.Accounts.Endpoints
public LoginEndpoint(PluginBase pbase, IConfigScope config)
{
string path = config.GetRequiredProperty("path", p => p.GetString()!);
- TimeSpan duration = config["failed_count_timeout_sec"].GetTimeSpan(TimeParseType.Seconds);
- uint maxLogins = config["failed_count_max"].GetUInt32();
+ TimeSpan duration = config["failed_attempt_timeout_sec"].GetTimeSpan(TimeParseType.Seconds);
+ uint maxLogins = config["max_login_attempts"].GetUInt32();
InitPathAndLog(path, pbase.Log);
diff --git a/plugins/VNLib.Plugins.Essentials.Accounts/src/Endpoints/PkiLoginEndpoint.cs b/plugins/VNLib.Plugins.Essentials.Accounts/src/Endpoints/PkiLoginEndpoint.cs
index 6d9e049..0abe657 100644
--- a/plugins/VNLib.Plugins.Essentials.Accounts/src/Endpoints/PkiLoginEndpoint.cs
+++ b/plugins/VNLib.Plugins.Essentials.Accounts/src/Endpoints/PkiLoginEndpoint.cs
@@ -63,7 +63,11 @@ namespace VNLib.Plugins.Essentials.Accounts.Endpoints
private static JwtLoginValidator LwValidator { get; } = new();
private static IValidator<AuthenticationInfo> AuthValidator { get; } = AuthenticationInfo.GetValidator();
- private static IValidator<PkiAuthPublicKey> UserJwkValidator { get; } = GetKeyValidator();
+
+ /// <summary>
+ /// A validator used to validate <see cref="PkiAuthPublicKey"/> instances
+ /// </summary>
+ public static IValidator<PkiAuthPublicKey> UserJwkValidator { get; } = GetKeyValidator();
private readonly JwtEndpointConfig _config;
private readonly IUserManager _users;
diff --git a/plugins/VNLib.Plugins.Essentials.Accounts/src/SecurityProvider/AccountSecProvider.cs b/plugins/VNLib.Plugins.Essentials.Accounts/src/SecurityProvider/AccountSecProvider.cs
index 878a63a..d9c1703 100644
--- a/plugins/VNLib.Plugins.Essentials.Accounts/src/SecurityProvider/AccountSecProvider.cs
+++ b/plugins/VNLib.Plugins.Essentials.Accounts/src/SecurityProvider/AccountSecProvider.cs
@@ -58,6 +58,7 @@ namespace VNLib.Plugins.Essentials.Accounts.SecurityProvider
{
[ConfigurationName("account_security", Required = false)]
+ [MiddlewareImpl(MiddlewareImplOptions.SecurityCritical)]
internal class AccountSecProvider : IAccountSecurityProvider, IHttpMiddleware
{
private const int PUB_KEY_JWT_NONCE_SIZE = 16;
@@ -125,7 +126,7 @@ namespace VNLib.Plugins.Essentials.Accounts.SecurityProvider
//If the session stored a user-agent, make sure it matches the connection
if (session.UserAgent != null && !session.UserAgent.Equals(entity.Server.UserAgent, StringComparison.Ordinal))
{
- _logger.Debug("Denied authorized connection from {ip} because user-agent changed");
+ _logger.Debug("Denied authorized connection from {ip} because user-agent changed", entity.TrustedRemoteIp);
return ValueTask.FromResult(FileProcessArgs.Deny);
}
}