diff --git a/src/Contrast.K8s.AgentOperator/Core/Reactions/Matching/AgentInjectorMatcher.cs b/src/Contrast.K8s.AgentOperator/Core/Reactions/Matching/AgentInjectorMatcher.cs index 9378edea..f45f96e4 100644 --- a/src/Contrast.K8s.AgentOperator/Core/Reactions/Matching/AgentInjectorMatcher.cs +++ b/src/Contrast.K8s.AgentOperator/Core/Reactions/Matching/AgentInjectorMatcher.cs @@ -26,13 +26,13 @@ public IEnumerable> GetMatchingInjec return readyInjectors.Where(injector => InjectorMatchesTarget(injector, target)); } - public bool InjectorMatchesTarget(ResourceIdentityPair injector, - ResourceIdentityPair target) + private bool InjectorMatchesTarget(ResourceIdentityPair injector, + ResourceIdentityPair target) { var (_, labelPatterns, namespaces) = injector.Resource.Selector; var matchesNamespace = namespaces.Contains(target.Identity.Namespace, StringComparer.OrdinalIgnoreCase); - var matchesLabel = !labelPatterns.Any() || labelPatterns.Any(x => MatchesLabel(target.Resource, x.Key, x.Value)); + var matchesLabel = !labelPatterns.Any() || labelPatterns.All(x => MatchesLabel(target.Resource, x.Key, x.Value)); return matchesNamespace && matchesLabel; } diff --git a/tests/Contrast.K8s.AgentOperator.Tests/Core/Reactions/Matching/AgentInjectorMatcherTests.cs b/tests/Contrast.K8s.AgentOperator.Tests/Core/Reactions/Matching/AgentInjectorMatcherTests.cs new file mode 100644 index 00000000..59fff32b --- /dev/null +++ b/tests/Contrast.K8s.AgentOperator.Tests/Core/Reactions/Matching/AgentInjectorMatcherTests.cs @@ -0,0 +1,118 @@ +// Contrast Security, Inc licenses this file to you under the Apache 2.0 License. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.Linq; +using AutoFixture; +using Contrast.K8s.AgentOperator.Core.Reactions; +using Contrast.K8s.AgentOperator.Core.Reactions.Matching; +using Contrast.K8s.AgentOperator.Core.State; +using Contrast.K8s.AgentOperator.Core.State.Resources; +using Contrast.K8s.AgentOperator.Core.State.Resources.Interfaces; +using Contrast.K8s.AgentOperator.Core.State.Resources.Primitives; +using FluentAssertions; +using Xunit; + +namespace Contrast.K8s.AgentOperator.Tests.Core.Reactions.Matching +{ + public class AgentInjectorMatcherTests + { + private static readonly Fixture AutoFixture = new(); + + [Fact] + public void When_injector_matches_resource_then_GetMatchingInjectors_should_return_injector() + { + var labelsFake = AutoFixture.CreateMany(3).ToList(); + + var targetFake = new ResourceIdentityPair( + FakeNamespacedResourceIdentity(), + AutoFixture.Create() with + { + Labels = labelsFake + } + ); + + var injectorsFake = new List> + { + new( + FakeNamespacedResourceIdentity(), + AutoFixture.Create() with + { + Selector = AutoFixture.Create() with + { + Namespaces = new List + { + targetFake.Identity.Namespace + }, + LabelPatterns = labelsFake.Select(x => new KeyValuePair(x.Name, x.Value)).ToList() + } + } + ) + }; + + var matcher = CreateMatcher(); + + // Act + var result = matcher.GetMatchingInjectors(injectorsFake, targetFake); + + // Assert + result.Should().BeEquivalentTo(injectorsFake); + } + + [Fact] + public void When_matching_then_GetMatchingInjectors_should_match_on_all_labels() + { + // Create three labels. + var labelsFake = AutoFixture.CreateMany(3).ToList(); + + var targetFake = new ResourceIdentityPair( + FakeNamespacedResourceIdentity(), + AutoFixture.Create() with + { + // Only apply one label to the resource. + Labels = labelsFake.Take(1).ToList() + } + ); + + var injectorsFake = new List> + { + new( + FakeNamespacedResourceIdentity(), + AutoFixture.Create() with + { + Selector = AutoFixture.Create() with + { + Namespaces = new List + { + targetFake.Identity.Namespace + }, + // But match on all 3 labels. + LabelPatterns = labelsFake.Select(x => new KeyValuePair(x.Name, x.Value)).ToList() + } + } + ) + }; + + var matcher = CreateMatcher(); + + // Act + var result = matcher.GetMatchingInjectors(injectorsFake, targetFake); + + // Assert + result.Should().BeEmpty(); + } + + public AgentInjectorMatcher CreateMatcher() + { + return new AgentInjectorMatcher(new GlobMatcher()); + } + + public NamespacedResourceIdentity FakeNamespacedResourceIdentity(string? name = null, string? @namespace = null) + { + return NamespacedResourceIdentity.Create( + name ?? AutoFixture.Create(), + @namespace ?? AutoFixture.Create() + ); + } + } +}