Negating glob patterns not usable in AgentInjector resource
lkallas opened this issue ยท 6 comments
Background
Consider a case where there are many pods running with main container and some sidecar container (e.g. db-proxy) inside a Kubernetes cluster.
Contrast Kuberentes operator AgentInjector
custom resource allows one to specify to which containers the agent is injected to inside a pod.
spec.selector.images
allows specifying a glob pattern which is used to find a matching container where agent is injected.
I can see that there is C# Glob package in use.
Problem
In my case, I would like to inject nodejs
agent into every container in many pods. But I do not want to inject it to db-proxy
container which is not a nodejs
workload and also does not need any instrumentation.
I struggle to find a good glob pattern for this purpose.
Seems that there actually isn't one for my case - well, Glob package does not implement it (not correctly at least IMO).
So to illustrate this problem, take this small program snippet I used to determine the glob pattern for my case.
I would like to match any Docker image that does not have "some-proxy" in it's name using negating pattern.
using System;
using GlobExpressions;
public interface IGlobMatcher
{
bool Matches(string pattern, string value);
}
public class GlobMatcher : IGlobMatcher
{
public bool Matches(string pattern, string value)
{
var glob = new Glob(pattern, GlobOptions.CaseInsensitive | GlobOptions.Compiled);
return glob.IsMatch(value);
}
}
public class Program
{
public static void Main()
{
var matcher = new GlobMatcher();
var pattern = "!(*some-proxy*)"; // Trying to use negating pattern
var result1 = matcher.Matches(pattern, "europe-docker.pkg.dev/project/docker-images/whatever:latest"); // This should return True
Console.WriteLine(result1); // False
var result2 = matcher.Matches(pattern, "europe-docker.pkg.dev/project/docker-images/some-proxy:latest"); // This should return False
Console.WriteLine(result2); // False
}
}
I see that you do not have a such test-case either in your tests.
I could use something like:
var pattern = "**/[!some-proxy]*";
But it will match characters "s", "o", "m", "e", "-", "p", "r", "o", "x", "y" and not in that particular order + char "o" does not have to repeat.
So it matches any permutation of those characters e.g. "oepx-msyro" and "sexy-prom". Not accurate enough.
Workaround
The only workaround right now is to specify each image name in the manifest I wish to have agent injected to. The list grows really long if there are hundreds of unique microservices/images.
apiVersion: agents.contrastsecurity.com/v1beta1
kind: AgentInjector
metadata:
name: contrast-agent-injector
namespace: somenamespace
spec:
enabled: true
version: latest
type: nodejs
selector:
images:
- "*important-web*"
- "*some-other-web*"
- "*restful-api*"
labels:
- name: contrast
value: enabled
Could you assist/profide a fix?
@Silvenga @gamingrobot
Thank you!
Just a heads up, I no longer work for @Contrast-Security-OSS.
Just a heads up, I no longer work for @Contrast-Security-OSS.
I'm so sorry for mentioning you!
Just looked at the contributions insights and you were the top contributor - therefore mentioned you
Perhaps adding a regex support instead of glob patterns or adding glob + regex pattern support for image matching would make it a better/more flexible solution.
For example create new matcher e.g. RegexMatcher
that will be used in the matching function if the spec.selector.images
has image with a prefix re#
indicating that regular expression should be used for matching (not glob).
That way it wouldn't be a breaking change either.
In my case negative lookahead regex would do the trick.
^(?!.*some-proxy).*$
So given my suggestion the manifest could look like this:
apiVersion: agents.contrastsecurity.com/v1beta1
kind: AgentInjector
metadata:
name: contrast-agent-injector
namespace: somenamespace
spec:
enabled: true
version: latest
type: nodejs
selector:
images:
- "re#^(?!.*some-proxy).*$"
labels:
- name: contrast
value: enabled
Hi @lkallas Thanks for the suggestion. I've chatted with our developers and have submitted an enhancement request for the behavior updates on the operator. (Ref: CUST-4301 our ticket tracking system is internal.)
While in this case, since the other container is not a nodeJS application, we would essentially do nothing. Though it is still going through the motions, it should have no effects on the application. There is still a case for this and tighter control over the containers we inject into would be great.
The operator now supports additional labels that you can add like contrast-agent: nodejs
. Does that work for your use case here @lkallas ?
The operator now supports additional labels that you can add like
contrast-agent: nodejs
. Does that work for your use case here @lkallas ?
@johnament Can you elaborate how does it work, provide the documentation link?