diff --git a/src/NuGetGallery.Core/Auditing/AuditActor.cs b/src/NuGetGallery.Core/Auditing/AuditActor.cs index 160604e4b4..af7ab1d6f3 100644 --- a/src/NuGetGallery.Core/Auditing/AuditActor.cs +++ b/src/NuGetGallery.Core/Auditing/AuditActor.cs @@ -8,6 +8,7 @@ using System.Net.NetworkInformation; using System.Net.Sockets; using System.Threading.Tasks; +using System.Web; namespace NuGetGallery.Auditing { @@ -17,25 +18,70 @@ public class AuditActor public string MachineIP { get; set; } public string UserName { get; set; } public string AuthenticationType { get; set; } - public string CredentialKey { get; set; } public DateTime TimestampUtc { get; set; } public AuditActor OnBehalfOf { get; set; } - public AuditActor(string machineName, string machineIP, string userName, string authenticationType, string credentialKey, DateTime timeStampUtc) - : this(machineName, machineIP, userName, authenticationType, credentialKey, timeStampUtc, null) { } + public AuditActor(string machineName, string machineIP, string userName, string authenticationType, DateTime timeStampUtc) + : this(machineName, machineIP, userName, authenticationType, timeStampUtc, null) { } - public AuditActor(string machineName, string machineIP, string userName, string authenticationType, string credentialKey, DateTime timeStampUtc, AuditActor onBehalfOf) + public AuditActor(string machineName, string machineIP, string userName, string authenticationType, DateTime timeStampUtc, AuditActor onBehalfOf) { MachineName = machineName; MachineIP = machineIP; UserName = userName; AuthenticationType = authenticationType; - CredentialKey = credentialKey; TimestampUtc = timeStampUtc; OnBehalfOf = onBehalfOf; } + public static Task GetAspNetOnBehalfOfAsync() + { + // Use HttpContext to build an actor representing the user performing the action + var context = HttpContext.Current; + if (context == null) + { + return Task.FromResult(null); + } + + return GetAspNetOnBehalfOfAsync(new HttpContextWrapper(context)); + } + + public static Task GetAspNetOnBehalfOfAsync(HttpContextBase context) + { + // Try to identify the client IP using various server variables + var clientIpAddress = context.Request.ServerVariables["HTTP_X_FORWARDED_FOR"]; + if (string.IsNullOrEmpty(clientIpAddress)) // Try REMOTE_ADDR server variable + { + clientIpAddress = context.Request.ServerVariables["REMOTE_ADDR"]; + } + + if (string.IsNullOrEmpty(clientIpAddress)) // Try UserHostAddress property + { + clientIpAddress = context.Request.UserHostAddress; + } + + if (!string.IsNullOrEmpty(clientIpAddress) && clientIpAddress.IndexOf(".", StringComparison.Ordinal) > 0) + { + clientIpAddress = clientIpAddress.Substring(0, clientIpAddress.LastIndexOf(".", StringComparison.Ordinal)) + ".0"; + } + + string user = null; + string authType = null; + if (context.User != null) + { + user = context.User.Identity.Name; + authType = context.User.Identity.AuthenticationType; + } + + return Task.FromResult(new AuditActor( + null, + clientIpAddress, + user, + authType, + DateTime.UtcNow)); + } + public static Task GetCurrentMachineActorAsync() { return GetCurrentMachineActorAsync(null); @@ -51,7 +97,6 @@ public static async Task GetCurrentMachineActorAsync(AuditActor onBe ipAddress, $@"{Environment.UserDomainName}\{Environment.UserName}", "MachineUser", - string.Empty, DateTime.UtcNow, onBehalfOf); } diff --git a/src/NuGetGallery/App_Start/DefaultDependenciesModule.cs b/src/NuGetGallery/App_Start/DefaultDependenciesModule.cs index f3e7793802..847d37c549 100644 --- a/src/NuGetGallery/App_Start/DefaultDependenciesModule.cs +++ b/src/NuGetGallery/App_Start/DefaultDependenciesModule.cs @@ -472,7 +472,7 @@ private static IAuditingService GetAuditingServiceForLocalFileSystem(IGalleryCon FileSystemFileStorageService.ResolvePath(configuration.Current.FileStorageDirectory), FileSystemAuditingService.DefaultContainerName); - return new FileSystemAuditingService(auditingPath, AuditingHelper.GetAspNetOnBehalfOfAsync); + return new FileSystemAuditingService(auditingPath, AuditActor.GetAspNetOnBehalfOfAsync); } private static void ConfigureForAzureStorage(ContainerBuilder builder, IGalleryConfigurationService configuration) @@ -567,7 +567,7 @@ private static IAuditingService GetAuditingServiceForAzureStorage(ContainerBuild var localIp = AuditActor.GetLocalIpAddressAsync().Result; - var service = new CloudAuditingService(instanceId, localIp, configuration.Current.AzureStorage_Auditing_ConnectionString, AuditingHelper.GetAspNetOnBehalfOfAsync); + var service = new CloudAuditingService(instanceId, localIp, configuration.Current.AzureStorage_Auditing_ConnectionString, AuditActor.GetAspNetOnBehalfOfAsync); builder.RegisterInstance(service) .As() diff --git a/src/NuGetGallery/Authentication/NuGetClaims.cs b/src/NuGetGallery/Authentication/NuGetClaims.cs index 6af22853d8..df1289a110 100644 --- a/src/NuGetGallery/Authentication/NuGetClaims.cs +++ b/src/NuGetGallery/Authentication/NuGetClaims.cs @@ -10,8 +10,5 @@ public static class NuGetClaims public const string ApiKey = "https://claims.nuget.org/apikey"; public const string Scope = "https://claims.nuget.org/scope"; - - // Allows identifying the credential that was used by his DB key. - public const string CredentialKey = "https://claims.nuget.org/credentialkey"; } } \ No newline at end of file diff --git a/src/NuGetGallery/Authentication/Providers/ApiKey/ApiKeyAuthenticationHandler.cs b/src/NuGetGallery/Authentication/Providers/ApiKey/ApiKeyAuthenticationHandler.cs index 9454a388f3..63a9329089 100644 --- a/src/NuGetGallery/Authentication/Providers/ApiKey/ApiKeyAuthenticationHandler.cs +++ b/src/NuGetGallery/Authentication/Providers/ApiKey/ApiKeyAuthenticationHandler.cs @@ -109,8 +109,7 @@ protected override async Task AuthenticateCoreAsync() authUser.User, AuthenticationTypes.ApiKey, new Claim(NuGetClaims.ApiKey, apiKey), - new Claim(NuGetClaims.Scope, scopes), - new Claim(NuGetClaims.CredentialKey, authUser.CredentialUsed.Key.ToString())), + new Claim(NuGetClaims.Scope, scopes)), new AuthenticationProperties()); } else diff --git a/src/NuGetGallery/Helpers/AuditingHelper.cs b/src/NuGetGallery/Helpers/AuditingHelper.cs deleted file mode 100644 index 85969afe62..0000000000 --- a/src/NuGetGallery/Helpers/AuditingHelper.cs +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Security.Claims; -using System.Threading.Tasks; -using System.Web; -using NuGetGallery.Auditing; -using NuGetGallery.Authentication; - -namespace NuGetGallery -{ - public static class AuditingHelper - { - public static Task GetAspNetOnBehalfOfAsync() - { - // Use HttpContext to build an actor representing the user performing the action - var context = HttpContext.Current; - if (context == null) - { - return Task.FromResult(null); - } - - return GetAspNetOnBehalfOfAsync(new HttpContextWrapper(context)); - } - - public static Task GetAspNetOnBehalfOfAsync(HttpContextBase context) - { - // Try to identify the client IP using various server variables - var clientIpAddress = context.Request.ServerVariables["HTTP_X_FORWARDED_FOR"]; - if (string.IsNullOrEmpty(clientIpAddress)) // Try REMOTE_ADDR server variable - { - clientIpAddress = context.Request.ServerVariables["REMOTE_ADDR"]; - } - - if (string.IsNullOrEmpty(clientIpAddress)) // Try UserHostAddress property - { - clientIpAddress = context.Request.UserHostAddress; - } - - if (!string.IsNullOrEmpty(clientIpAddress) && clientIpAddress.IndexOf(".", StringComparison.Ordinal) > 0) - { - clientIpAddress = clientIpAddress.Substring(0, clientIpAddress.LastIndexOf(".", StringComparison.Ordinal)) + ".0"; - } - - string user = null; - string authType = null; - string credentialKey = null; - - if (context.User != null) - { - user = context.User.Identity.Name; - authType = context.User.Identity.AuthenticationType; - - var claimsIdentity = context.User.Identity as ClaimsIdentity; - credentialKey = claimsIdentity?.GetClaimOrDefault(NuGetClaims.CredentialKey); - } - - return Task.FromResult(new AuditActor( - null, - clientIpAddress, - user, - authType, - credentialKey, - DateTime.UtcNow)); - } - } -} \ No newline at end of file diff --git a/src/NuGetGallery/NuGetGallery.csproj b/src/NuGetGallery/NuGetGallery.csproj index 9191624f32..3020847a4c 100644 --- a/src/NuGetGallery/NuGetGallery.csproj +++ b/src/NuGetGallery/NuGetGallery.csproj @@ -768,7 +768,6 @@ - diff --git a/tests/NuGetGallery.Core.Facts/Auditing/AuditActorTests.cs b/tests/NuGetGallery.Core.Facts/Auditing/AuditActorTests.cs index 651f3c019d..eec8bb2e50 100644 --- a/tests/NuGetGallery.Core.Facts/Auditing/AuditActorTests.cs +++ b/tests/NuGetGallery.Core.Facts/Auditing/AuditActorTests.cs @@ -3,11 +3,15 @@ using System; using System.Collections.Generic; +using System.Collections.Specialized; using System.Linq; using System.Net; using System.Net.NetworkInformation; using System.Net.Sockets; +using System.Security.Principal; using System.Threading.Tasks; +using System.Web; +using Moq; using Xunit; namespace NuGetGallery.Auditing @@ -22,7 +26,6 @@ public void Constructor_WithoutOnBehalfOf_AcceptsNullValues() machineIP: null, userName: null, authenticationType: null, - credentialKey: null, timeStampUtc: DateTime.MinValue); Assert.Null(actor.MachineName); @@ -38,7 +41,6 @@ public void Constructor_WithOnBehalfOf_AcceptsNullValues() machineIP: null, userName: null, authenticationType: null, - credentialKey: null, timeStampUtc: DateTime.MinValue, onBehalfOf: null); @@ -47,44 +49,39 @@ public void Constructor_WithOnBehalfOf_AcceptsNullValues() Assert.Null(actor.UserName); Assert.Null(actor.AuthenticationType); Assert.Null(actor.OnBehalfOf); - Assert.Null(actor.CredentialKey); } [Fact] public void Constructor_WithoutOnBehalfOf_AcceptsEmptyStringValues() { var actor = new AuditActor( - machineName: string.Empty, - machineIP: string.Empty, - userName: string.Empty, - authenticationType: string.Empty, - credentialKey: string.Empty, + machineName: "", + machineIP: "", + userName: "", + authenticationType: "", timeStampUtc: DateTime.MinValue); - Assert.Equal(string.Empty, actor.MachineName); - Assert.Equal(string.Empty, actor.MachineIP); - Assert.Equal(string.Empty, actor.UserName); - Assert.Equal(string.Empty, actor.AuthenticationType); - Assert.Equal(string.Empty, actor.CredentialKey); + Assert.Equal("", actor.MachineName); + Assert.Equal("", actor.MachineIP); + Assert.Equal("", actor.UserName); + Assert.Equal("", actor.AuthenticationType); } [Fact] public void Constructor_WithOnBehalfOf_AcceptsEmptyStringValues() { var actor = new AuditActor( - machineName: string.Empty, - machineIP: string.Empty, - userName: string.Empty, - authenticationType: string.Empty, - credentialKey: string.Empty, + machineName: "", + machineIP: "", + userName: "", + authenticationType: "", timeStampUtc: DateTime.MinValue, onBehalfOf: null); - Assert.Equal(string.Empty, actor.MachineName); - Assert.Equal(string.Empty, actor.MachineIP); - Assert.Equal(string.Empty, actor.UserName); - Assert.Equal(string.Empty, actor.AuthenticationType); - Assert.Equal(string.Empty, actor.CredentialKey); + Assert.Equal("", actor.MachineName); + Assert.Equal("", actor.MachineIP); + Assert.Equal("", actor.UserName); + Assert.Equal("", actor.AuthenticationType); } [Fact] @@ -95,14 +92,12 @@ public void Constructor_WithoutOnBehalfOf_SetsProperties() machineIP: "b", userName: "c", authenticationType: "d", - credentialKey: "e", timeStampUtc: DateTime.MinValue); Assert.Equal("a", actor.MachineName); Assert.Equal("b", actor.MachineIP); Assert.Equal("c", actor.UserName); Assert.Equal("d", actor.AuthenticationType); - Assert.Equal("e", actor.CredentialKey); Assert.Equal(DateTime.MinValue, actor.TimestampUtc); } @@ -114,14 +109,12 @@ public void Constructor_WithOnBehalfOf_SetsProperties() machineIP: null, userName: null, authenticationType: null, - credentialKey: null, timeStampUtc: DateTime.MinValue); var actor = new AuditActor( machineName: "a", machineIP: "b", userName: "c", authenticationType: "d", - credentialKey: "e", timeStampUtc: DateTime.MinValue, onBehalfOf: onBehalfOfActor); @@ -129,11 +122,172 @@ public void Constructor_WithOnBehalfOf_SetsProperties() Assert.Equal("b", actor.MachineIP); Assert.Equal("c", actor.UserName); Assert.Equal("d", actor.AuthenticationType); - Assert.Equal("e", actor.CredentialKey); Assert.Equal(DateTime.MinValue, actor.TimestampUtc); Assert.Same(onBehalfOfActor, actor.OnBehalfOf); } - + + [Fact] + public async Task GetAspNetOnBehalfOfAsync_WithoutContext_ReturnsNullForNullHttpContext() + { + var actor = await AuditActor.GetAspNetOnBehalfOfAsync(); + + Assert.Null(actor); + } + + [Fact] + public async Task GetAspNetOnBehalfOfAsync_WithContext_ReturnsActor_WithHttpXForwardedForHeader() + { + var request = new Mock(); + var identity = new Mock(); + var user = new Mock(); + var context = new Mock(); + + request.SetupGet(x => x.ServerVariables) + .Returns(new NameValueCollection() { { "HTTP_X_FORWARDED_FOR", "a" } }); + identity.Setup(x => x.Name) + .Returns("b"); + identity.Setup(x => x.AuthenticationType) + .Returns("c"); + user.Setup(x => x.Identity) + .Returns(identity.Object); + context.Setup(x => x.Request) + .Returns(request.Object); + context.Setup(x => x.User) + .Returns(user.Object); + + var actor = await AuditActor.GetAspNetOnBehalfOfAsync(context.Object); + + Assert.NotNull(actor); + Assert.Equal("c", actor.AuthenticationType); + Assert.Equal("a", actor.MachineIP); + Assert.Null(actor.MachineName); + Assert.Null(actor.OnBehalfOf); + Assert.InRange(actor.TimestampUtc, DateTime.UtcNow.AddMinutes(-1), DateTime.UtcNow.AddMinutes(1)); + Assert.Equal("b", actor.UserName); + } + + [Fact] + public async Task GetAspNetOnBehalfOfAsync_WithContext_ReturnsActor_WithRemoteAddrHeader() + { + var request = new Mock(); + var identity = new Mock(); + var user = new Mock(); + var context = new Mock(); + + request.SetupGet(x => x.ServerVariables) + .Returns(new NameValueCollection() { { "REMOTE_ADDR", "a" } }); + identity.Setup(x => x.Name) + .Returns("b"); + identity.Setup(x => x.AuthenticationType) + .Returns("c"); + user.Setup(x => x.Identity) + .Returns(identity.Object); + context.Setup(x => x.Request) + .Returns(request.Object); + context.Setup(x => x.User) + .Returns(user.Object); + + var actor = await AuditActor.GetAspNetOnBehalfOfAsync(context.Object); + + Assert.NotNull(actor); + Assert.Equal("c", actor.AuthenticationType); + Assert.Equal("a", actor.MachineIP); + Assert.Null(actor.MachineName); + Assert.Null(actor.OnBehalfOf); + Assert.InRange(actor.TimestampUtc, DateTime.UtcNow.AddMinutes(-1), DateTime.UtcNow.AddMinutes(1)); + Assert.Equal("b", actor.UserName); + } + + [Fact] + public async Task GetAspNetOnBehalfOfAsync_WithContext_ReturnsActor_WithUserHostAddress() + { + var request = new Mock(); + var identity = new Mock(); + var user = new Mock(); + var context = new Mock(); + + request.SetupGet(x => x.ServerVariables) + .Returns(new NameValueCollection()); + request.SetupGet(x => x.UserHostAddress) + .Returns("a"); + identity.Setup(x => x.Name) + .Returns("b"); + identity.Setup(x => x.AuthenticationType) + .Returns("c"); + user.Setup(x => x.Identity) + .Returns(identity.Object); + context.Setup(x => x.Request) + .Returns(request.Object); + context.Setup(x => x.User) + .Returns(user.Object); + + var actor = await AuditActor.GetAspNetOnBehalfOfAsync(context.Object); + + Assert.NotNull(actor); + Assert.Equal("c", actor.AuthenticationType); + Assert.Equal("a", actor.MachineIP); + Assert.Null(actor.MachineName); + Assert.Null(actor.OnBehalfOf); + Assert.InRange(actor.TimestampUtc, DateTime.UtcNow.AddMinutes(-1), DateTime.UtcNow.AddMinutes(1)); + Assert.Equal("b", actor.UserName); + } + + [Fact] + public async Task GetAspNetOnBehalfOfAsync_WithContext_ObfuscatesLastIpAddressOctet() + { + var request = new Mock(); + var identity = new Mock(); + var user = new Mock(); + var context = new Mock(); + + request.SetupGet(x => x.ServerVariables) + .Returns(new NameValueCollection() { { "HTTP_X_FORWARDED_FOR", "1.2.3.4" } }); + identity.Setup(x => x.Name) + .Returns("b"); + identity.Setup(x => x.AuthenticationType) + .Returns("c"); + user.Setup(x => x.Identity) + .Returns(identity.Object); + context.Setup(x => x.Request) + .Returns(request.Object); + context.Setup(x => x.User) + .Returns(user.Object); + + var actor = await AuditActor.GetAspNetOnBehalfOfAsync(context.Object); + + Assert.NotNull(actor); + Assert.Equal("c", actor.AuthenticationType); + Assert.Equal("1.2.3.0", actor.MachineIP); + Assert.Null(actor.MachineName); + Assert.Null(actor.OnBehalfOf); + Assert.InRange(actor.TimestampUtc, DateTime.UtcNow.AddMinutes(-1), DateTime.UtcNow.AddMinutes(1)); + Assert.Equal("b", actor.UserName); + } + + [Fact] + public async Task GetAspNetOnBehalfOfAsync_WithContext_SupportsNullUser() + { + var request = new Mock(); + var context = new Mock(); + + request.SetupGet(x => x.ServerVariables) + .Returns(new NameValueCollection() { { "HTTP_X_FORWARDED_FOR", "1.2.3.4" } }); + context.Setup(x => x.Request) + .Returns(request.Object); + context.Setup(x => x.User) + .Returns((IPrincipal)null); + + var actor = await AuditActor.GetAspNetOnBehalfOfAsync(context.Object); + + Assert.NotNull(actor); + Assert.Null(actor.AuthenticationType); + Assert.Equal("1.2.3.0", actor.MachineIP); + Assert.Null(actor.MachineName); + Assert.Null(actor.OnBehalfOf); + Assert.InRange(actor.TimestampUtc, DateTime.UtcNow.AddMinutes(-1), DateTime.UtcNow.AddMinutes(1)); + Assert.Null(actor.UserName); + } + [Fact] public async Task GetCurrentMachineActorAsync_WithoutOnBehalfOf() { diff --git a/tests/NuGetGallery.Core.Facts/Auditing/AuditEntryTests.cs b/tests/NuGetGallery.Core.Facts/Auditing/AuditEntryTests.cs index 320f0a84e3..b167d8a823 100644 --- a/tests/NuGetGallery.Core.Facts/Auditing/AuditEntryTests.cs +++ b/tests/NuGetGallery.Core.Facts/Auditing/AuditEntryTests.cs @@ -27,7 +27,6 @@ public void Constructor_SetsProperties() machineIP: null, userName: null, authenticationType: null, - credentialKey: null, timeStampUtc: DateTime.MinValue); var entry = new AuditEntry(record.Object, actor); diff --git a/tests/NuGetGallery.Core.Facts/Auditing/FileSystemAuditingServiceTests.cs b/tests/NuGetGallery.Core.Facts/Auditing/FileSystemAuditingServiceTests.cs index 54258192c8..de2453c526 100644 --- a/tests/NuGetGallery.Core.Facts/Auditing/FileSystemAuditingServiceTests.cs +++ b/tests/NuGetGallery.Core.Facts/Auditing/FileSystemAuditingServiceTests.cs @@ -36,7 +36,7 @@ public async Task SaveAuditRecord_ThrowsForNull() { var service = new FileSystemAuditingService( auditingPath: "a", - getOnBehalfOf: GetOnBehalfOf); + getOnBehalfOf: AuditActor.GetAspNetOnBehalfOfAsync); await Assert.ThrowsAsync(async () => await service.SaveAuditRecordAsync(record: null)); @@ -141,7 +141,6 @@ private static Task GetOnBehalfOf() machineIP: "b", userName: "c", authenticationType: "d", - credentialKey: "e", timeStampUtc: DateTime.MinValue); return Task.FromResult(actor); diff --git a/tests/NuGetGallery.Facts/Helpers/AuditingHelperFacts.cs b/tests/NuGetGallery.Facts/Helpers/AuditingHelperFacts.cs deleted file mode 100644 index 5af2e6bea4..0000000000 --- a/tests/NuGetGallery.Facts/Helpers/AuditingHelperFacts.cs +++ /dev/null @@ -1,216 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Collections.Specialized; -using System.Security.Claims; -using System.Security.Principal; -using System.Threading.Tasks; -using System.Web; -using Moq; -using NuGetGallery.Authentication; -using Xunit; - -namespace NuGetGallery.Helpers -{ - public class AuditingHelperFacts - { - [Fact] - public async Task GetAspNetOnBehalfOfAsync_WithoutContext_ReturnsNullForNullHttpContext() - { - var actor = await AuditingHelper.GetAspNetOnBehalfOfAsync(); - - Assert.Null(actor); - } - - [Fact] - public async Task GetAspNetOnBehalfOfAsync_WithContext_ReturnsActor_WithHttpXForwardedForHeader() - { - var request = new Mock(); - var identity = new Mock(); - var user = new Mock(); - var context = new Mock(); - - request.SetupGet(x => x.ServerVariables) - .Returns(new NameValueCollection() { { "HTTP_X_FORWARDED_FOR", "a" } }); - identity.Setup(x => x.Name) - .Returns("b"); - identity.Setup(x => x.AuthenticationType) - .Returns("c"); - user.Setup(x => x.Identity) - .Returns(identity.Object); - context.Setup(x => x.Request) - .Returns(request.Object); - context.Setup(x => x.User) - .Returns(user.Object); - - var actor = await AuditingHelper.GetAspNetOnBehalfOfAsync(context.Object); - - Assert.NotNull(actor); - Assert.Equal("c", actor.AuthenticationType); - Assert.Equal("a", actor.MachineIP); - Assert.Null(actor.MachineName); - Assert.Null(actor.OnBehalfOf); - Assert.InRange(actor.TimestampUtc, DateTime.UtcNow.AddMinutes(-1), DateTime.UtcNow.AddMinutes(1)); - Assert.Equal("b", actor.UserName); - } - - [Fact] - public async Task GetAspNetOnBehalfOfAsync_WithContext_ReturnsActor_WithRemoteAddrHeader() - { - var request = new Mock(); - var identity = new Mock(); - var user = new Mock(); - var context = new Mock(); - - request.SetupGet(x => x.ServerVariables) - .Returns(new NameValueCollection() { { "REMOTE_ADDR", "a" } }); - identity.Setup(x => x.Name) - .Returns("b"); - identity.Setup(x => x.AuthenticationType) - .Returns("c"); - user.Setup(x => x.Identity) - .Returns(identity.Object); - context.Setup(x => x.Request) - .Returns(request.Object); - context.Setup(x => x.User) - .Returns(user.Object); - - var actor = await AuditingHelper.GetAspNetOnBehalfOfAsync(context.Object); - - Assert.NotNull(actor); - Assert.Equal("c", actor.AuthenticationType); - Assert.Equal("a", actor.MachineIP); - Assert.Null(actor.MachineName); - Assert.Null(actor.OnBehalfOf); - Assert.InRange(actor.TimestampUtc, DateTime.UtcNow.AddMinutes(-1), DateTime.UtcNow.AddMinutes(1)); - Assert.Equal("b", actor.UserName); - } - - [Fact] - public async Task GetAspNetOnBehalfOfAsync_WithContext_ReturnsActor_WithUserHostAddress() - { - var request = new Mock(); - var identity = new Mock(); - var user = new Mock(); - var context = new Mock(); - - request.SetupGet(x => x.ServerVariables) - .Returns(new NameValueCollection()); - request.SetupGet(x => x.UserHostAddress) - .Returns("a"); - identity.Setup(x => x.Name) - .Returns("b"); - identity.Setup(x => x.AuthenticationType) - .Returns("c"); - user.Setup(x => x.Identity) - .Returns(identity.Object); - context.Setup(x => x.Request) - .Returns(request.Object); - context.Setup(x => x.User) - .Returns(user.Object); - - var actor = await AuditingHelper.GetAspNetOnBehalfOfAsync(context.Object); - - Assert.NotNull(actor); - Assert.Equal("c", actor.AuthenticationType); - Assert.Equal("a", actor.MachineIP); - Assert.Null(actor.MachineName); - Assert.Null(actor.OnBehalfOf); - Assert.InRange(actor.TimestampUtc, DateTime.UtcNow.AddMinutes(-1), DateTime.UtcNow.AddMinutes(1)); - Assert.Equal("b", actor.UserName); - } - - [Fact] - public async Task GetAspNetOnBehalfOfAsync_WithContext_ObfuscatesLastIpAddressOctet() - { - var request = new Mock(); - var identity = new Mock(); - var user = new Mock(); - var context = new Mock(); - - request.SetupGet(x => x.ServerVariables) - .Returns(new NameValueCollection() { { "HTTP_X_FORWARDED_FOR", "1.2.3.4" } }); - identity.Setup(x => x.Name) - .Returns("b"); - identity.Setup(x => x.AuthenticationType) - .Returns("c"); - user.Setup(x => x.Identity) - .Returns(identity.Object); - context.Setup(x => x.Request) - .Returns(request.Object); - context.Setup(x => x.User) - .Returns(user.Object); - - var actor = await AuditingHelper.GetAspNetOnBehalfOfAsync(context.Object); - - Assert.NotNull(actor); - Assert.Equal("c", actor.AuthenticationType); - Assert.Equal("1.2.3.0", actor.MachineIP); - Assert.Null(actor.MachineName); - Assert.Null(actor.OnBehalfOf); - Assert.InRange(actor.TimestampUtc, DateTime.UtcNow.AddMinutes(-1), DateTime.UtcNow.AddMinutes(1)); - Assert.Equal("b", actor.UserName); - } - - [Fact] - public async Task GetAspNetOnBehalfOfAsync_WithContext_ResturnActorWithCredentialKey() - { - var request = new Mock(); - var identity = new Mock(); - var user = new Mock(); - var context = new Mock(); - - request.SetupGet(x => x.ServerVariables) - .Returns(new NameValueCollection() { { "HTTP_X_FORWARDED_FOR", "1.2.3.4" } }); - identity.Setup(x => x.Name) - .Returns("b"); - identity.Setup(x => x.AuthenticationType) - .Returns("c"); - - var cliamsIdentity = new ClaimsIdentity(identity.Object, new List { new Claim(NuGetClaims.CredentialKey, "99") }); - user.Setup(x => x.Identity) - .Returns(cliamsIdentity); - context.Setup(x => x.Request) - .Returns(request.Object); - context.Setup(x => x.User) - .Returns(user.Object); - - var actor = await AuditingHelper.GetAspNetOnBehalfOfAsync(context.Object); - - Assert.NotNull(actor); - Assert.Equal("c", actor.AuthenticationType); - Assert.Equal("99", actor.CredentialKey); - Assert.Equal("1.2.3.0", actor.MachineIP); - Assert.Null(actor.MachineName); - Assert.Null(actor.OnBehalfOf); - Assert.InRange(actor.TimestampUtc, DateTime.UtcNow.AddMinutes(-1), DateTime.UtcNow.AddMinutes(1)); - Assert.Equal("b", actor.UserName); - } - - [Fact] - public async Task GetAspNetOnBehalfOfAsync_WithContext_SupportsNullUser() - { - var request = new Mock(); - var context = new Mock(); - - request.SetupGet(x => x.ServerVariables) - .Returns(new NameValueCollection() { { "HTTP_X_FORWARDED_FOR", "1.2.3.4" } }); - context.Setup(x => x.Request) - .Returns(request.Object); - context.Setup(x => x.User) - .Returns((IPrincipal)null); - - var actor = await AuditingHelper.GetAspNetOnBehalfOfAsync(context.Object); - - Assert.NotNull(actor); - Assert.Null(actor.AuthenticationType); - Assert.Equal("1.2.3.0", actor.MachineIP); - Assert.Null(actor.MachineName); - Assert.Null(actor.OnBehalfOf); - Assert.InRange(actor.TimestampUtc, DateTime.UtcNow.AddMinutes(-1), DateTime.UtcNow.AddMinutes(1)); - Assert.Null(actor.UserName); - } - } -} diff --git a/tests/NuGetGallery.Facts/NuGetGallery.Facts.csproj b/tests/NuGetGallery.Facts/NuGetGallery.Facts.csproj index c1c9ea007d..492208e204 100644 --- a/tests/NuGetGallery.Facts/NuGetGallery.Facts.csproj +++ b/tests/NuGetGallery.Facts/NuGetGallery.Facts.csproj @@ -423,7 +423,6 @@ -