-
Notifications
You must be signed in to change notification settings - Fork 122
Add component detectors for Docker Compose, Helm, and Kubernetes #1759
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
1a3f651
077d1d0
fd74cb5
d5c91ed
a111856
70776f8
a099d56
0bbc3db
5c4e487
b5d3fbf
5158b75
a26f434
0873316
ea3b0a4
5984b1c
9d56f38
8bce22b
ad592b2
9ae1dd4
70762f1
d220257
dff7d5f
569babe
f651b13
7f08f43
b77c789
70ada53
e5ffbb5
c0f586c
5d270f5
df6c196
ce8e98b
5b148b7
84b4383
6478e2e
a3fa9b8
146759c
7fc72c1
9b8e1b7
bac8dc8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -54,3 +54,4 @@ launchSettings.json | |
|
|
||
| # Dev nupkgs | ||
| dev-source | ||
| .nuget/ | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| # Docker Compose Detection | ||
|
|
||
| ## Requirements | ||
|
|
||
| Docker Compose detection depends on the following to successfully run: | ||
|
|
||
| - One or more Docker Compose files matching the patterns: `docker-compose.yml`, `docker-compose.yaml`, `docker-compose.*.yml`, `docker-compose.*.yaml`, `compose.yml`, `compose.yaml`, `compose.*.yml`, `compose.*.yaml` | ||
|
|
||
|
Comment on lines
+5
to
+8
|
||
| The `DockerComposeComponentDetector` is a **DefaultOff** detector and must be explicitly enabled via the `--DetectorArgs` parameter. | ||
|
|
||
| ## Detection strategy | ||
|
|
||
| The Docker Compose detector parses YAML compose files to extract Docker image references from service definitions. | ||
|
|
||
| ### Service Image Detection | ||
|
|
||
| The detector looks for the `services` section and extracts the `image` field from each service: | ||
|
|
||
| ```yaml | ||
| services: | ||
| web: | ||
| image: nginx:1.21 | ||
| db: | ||
| image: postgres:14 | ||
| ``` | ||
|
|
||
| Services that only define a `build` directive without an `image` field are skipped, as they do not reference external Docker images. | ||
|
|
||
| ### Full Registry References | ||
|
|
||
| The detector supports full registry image references: | ||
|
|
||
| ```yaml | ||
| services: | ||
| app: | ||
| image: ghcr.io/myorg/myapp:v2.0 | ||
| ``` | ||
|
|
||
| ### Variable Resolution | ||
|
|
||
| Images containing unresolved variables (e.g., `${TAG}` or `{{ .Values.tag }}`) are skipped to avoid reporting incomplete or incorrect references. The detector checks for `$`, `{`, or `}` characters in image references. | ||
|
|
||
| ## Known limitations | ||
|
|
||
| - **DefaultOff Status**: This detector must be explicitly enabled using `--DetectorArgs DockerCompose=EnableIfDefaultOff` | ||
| - **Variable Resolution**: Image references containing unresolved environment variables or template expressions are not reported, which may lead to under-reporting in compose files that heavily use variable substitution | ||
| - **Build-Only Services**: Services that only specify a `build` directive without an `image` field are not reported | ||
| - **No Dependency Graph**: All detected images are registered as independent components without parent-child relationships | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| # Helm Detection | ||
|
|
||
| ## Requirements | ||
|
|
||
| Helm detection depends on the following to successfully run: | ||
|
|
||
| - One or more Helm values files matching the patterns: `*values*.yaml`, `*values*.yml` | ||
| - Chart metadata files (`Chart.yaml`, `Chart.yml`, `chart.yaml`, `chart.yml`) are matched for file discovery but only values files are parsed for image references | ||
jpinz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
|
Comment on lines
+5
to
+9
|
||
| The `HelmComponentDetector` is a **DefaultOff** detector and must be explicitly enabled via the `--DetectorArgs` parameter. | ||
|
|
||
| ## Detection strategy | ||
|
|
||
| The Helm detector parses Helm values YAML files to extract Docker image references. It recursively walks the YAML tree looking for `image` keys. | ||
|
|
||
| ### Direct Image Strings | ||
|
|
||
| The detector recognizes image references specified as simple strings: | ||
|
|
||
| ```yaml | ||
| image: nginx:1.21 | ||
| ``` | ||
|
|
||
| ### Structured Image Objects | ||
|
|
||
| The detector also supports the common Helm chart pattern of structured image definitions: | ||
|
|
||
| ```yaml | ||
| image: | ||
| registry: ghcr.io | ||
| repository: org/myimage | ||
| tag: v1.0 | ||
| ``` | ||
|
|
||
| The `registry` and `tag` fields are optional. When present, the detector reconstructs the full image reference. The `digest` field is also supported. | ||
|
|
||
| ### Recursive Search | ||
|
|
||
| The detector recursively traverses all nested mappings and sequences in the values file, detecting image references at any depth in the YAML structure. | ||
|
|
||
| ### Variable Resolution | ||
|
|
||
| Images containing unresolved variables (e.g., `{{ .Values.tag }}`) are skipped to avoid reporting incomplete or incorrect references. The detector checks for `$`, `{`, or `}` characters in image references. | ||
|
|
||
| ## Known limitations | ||
|
|
||
| - **DefaultOff Status**: This detector must be explicitly enabled using `--DetectorArgs Helm=EnableIfDefaultOff` | ||
| - **Values Files Only**: Only files with `values` in the name are parsed for image references. Chart.yaml files are matched but not processed | ||
| - **Same-Directory Co-location**: Values files are only processed when a `Chart.yaml` (or `Chart.yml`) exists in the **same directory**. Values files in subdirectories of a chart root (e.g., `mychart/subdir/values.yaml`) will not be detected, even if a `Chart.yaml` exists in the parent directory | ||
| - **Variable Resolution**: Image references containing unresolved Helm template expressions are not reported | ||
| - **No Dependency Graph**: All detected images are registered as independent components without parent-child relationships | ||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,59 @@ | ||||||
| # Kubernetes Detection | ||||||
|
|
||||||
| ## Requirements | ||||||
|
|
||||||
| Kubernetes detection depends on the following to successfully run: | ||||||
|
|
||||||
| - One or more Kubernetes manifest files matching the patterns: `*.yaml`, `*.yml` | ||||||
| - Manifests must contain both `apiVersion` and `kind` fields to be recognized as Kubernetes resources | ||||||
|
|
||||||
| The `KubernetesComponentDetector` is a **DefaultOff** detector and must be explicitly enabled via the `--DetectorArgs` parameter. | ||||||
|
|
||||||
| ## Detection strategy | ||||||
|
|
||||||
| The Kubernetes detector parses Kubernetes manifest YAML files to extract Docker image references from container specifications. | ||||||
|
|
||||||
| ### Supported Resource Kinds | ||||||
|
|
||||||
| The detector recognizes the following Kubernetes resource kinds: | ||||||
|
|
||||||
| - `Pod` | ||||||
| - `PodTemplate` | ||||||
| - `Deployment` | ||||||
| - `StatefulSet` | ||||||
| - `DaemonSet` | ||||||
| - `ReplicaSet` | ||||||
| - `Job` | ||||||
| - `CronJob` | ||||||
| - `ReplicationController` | ||||||
|
|
||||||
|
Comment on lines
+16
to
+29
|
||||||
| Files with an unrecognized `kind` or missing `apiVersion`/`kind` fields are skipped. | ||||||
|
|
||||||
| ### Container Image Detection | ||||||
|
|
||||||
| The detector extracts image references from all container types within pod specifications: | ||||||
|
|
||||||
| - **containers**: Main application containers | ||||||
| - **initContainers**: Initialization containers that run before app containers | ||||||
| - **ephemeralContainers**: Ephemeral debugging containers | ||||||
|
|
||||||
| ### Pod Spec Locations | ||||||
|
|
||||||
| The detector handles different pod spec locations depending on the resource kind: | ||||||
|
|
||||||
| - **Pod**: `spec.containers` | ||||||
| - **Deployment, StatefulSet, DaemonSet, ReplicaSet, ReplicationController**: `spec.template.spec.containers` | ||||||
| - **Job**: `spec.template.spec.containers` | ||||||
| - **CronJob**: `spec.jobTemplate.spec.template.spec.containers` | ||||||
|
|
||||||
| ### Variable Resolution | ||||||
|
|
||||||
| Images containing unresolved variables (e.g., `${TAG}`) are skipped to avoid reporting incomplete or incorrect references. The detector checks for `$`, `{`, or `}` characters in image references. | ||||||
|
|
||||||
| ## Known limitations | ||||||
|
|
||||||
| - **DefaultOff Status**: This detector must be explicitly enabled using `--DetectorArgs Kubernetes=EnableIfDefaultOff` | ||||||
| - **Broad File Matching**: The `*.yaml` and `*.yml` search patterns match all YAML files, so the detector relies on content-based filtering (`apiVersion` and `kind` fields) to identify Kubernetes manifests | ||||||
| - **Variable Resolution**: Image references containing unresolved template variables are not reported | ||||||
| - **Limited Resource Kinds**: Only the eight resource kinds listed above are supported. Custom resources (CRDs) or other workload types are not detected | ||||||
|
||||||
| - **Limited Resource Kinds**: Only the eight resource kinds listed above are supported. Custom resources (CRDs) or other workload types are not detected | |
| - **Limited Resource Kinds**: Only the nine resource kinds listed above are supported. Custom resources (CRDs) or other workload types are not detected |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -38,6 +38,53 @@ public static class DockerReferenceUtility | |
| private const string LEGACYDEFAULTDOMAIN = "index.docker.io"; | ||
| private const string OFFICIALREPOSITORYNAME = "library"; | ||
|
|
||
| /// <summary> | ||
| /// Returns true if the reference contains unresolved variable placeholders (e.g., ${VAR}, {{ .Values.tag }}). | ||
| /// Such references should be skipped before calling <see cref="ParseFamiliarName"/> or <see cref="ParseQualifiedName"/>. | ||
| /// </summary> | ||
| /// <param name="reference">The image reference string to check.</param> | ||
|
Comment on lines
+41
to
+45
|
||
| /// <returns><c>true</c> if the reference contains variable placeholder characters; otherwise <c>false</c>.</returns> | ||
| public static bool HasUnresolvedVariables(string reference) => | ||
| reference.IndexOfAny(['$', '{', '}']) >= 0; | ||
|
Comment on lines
+41
to
+48
|
||
|
|
||
| /// <summary> | ||
| /// Attempts to parse an image reference string into a <see cref="DockerReference"/>. | ||
| /// Returns <c>null</c> if the reference contains unresolved variables or cannot be parsed. | ||
| /// </summary> | ||
| /// <param name="imageReference">The image reference string to parse.</param> | ||
| /// <returns>A <see cref="DockerReference"/> if parsing succeeds; otherwise <c>null</c>.</returns> | ||
| public static DockerReference? TryParseImageReference(string imageReference) | ||
| { | ||
| if (HasUnresolvedVariables(imageReference)) | ||
| { | ||
| return null; | ||
| } | ||
|
|
||
| try | ||
| { | ||
| return ParseFamiliarName(imageReference); | ||
| } | ||
| catch | ||
| { | ||
| return null; | ||
| } | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Parses an image reference and registers it with the recorder if valid. | ||
| /// Silently skips references with unresolved variables or that cannot be parsed. | ||
| /// </summary> | ||
| /// <param name="imageReference">The image reference string to parse.</param> | ||
| /// <param name="recorder">The component recorder to register the image with.</param> | ||
| public static void TryRegisterImageReference(string imageReference, ISingleFileComponentRecorder recorder) | ||
| { | ||
| var dockerRef = TryParseImageReference(imageReference); | ||
| if (dockerRef != null) | ||
| { | ||
| recorder.RegisterUsage(new DetectedComponent(dockerRef.ToTypedDockerReferenceComponent())); | ||
| } | ||
| } | ||
|
|
||
| public static DockerReference ParseQualifiedName(string qualifiedName) | ||
| { | ||
| var regexp = DockerRegex.ReferenceRegexp; | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.