From d2c55ef5f3e26a46c02ed00e1147b3414c6864db Mon Sep 17 00:00:00 2001 From: chanel-y Date: Tue, 15 Sep 2026 11:47:10 -0700 Subject: [PATCH 1/2] Add Kubernetes and Compose YAML models Add structural Kubernetes workload and RBAC classes and expand Compose services with environment, secret, image, volume, capability, and runtime settings. Include focused library fixtures for workload, RBAC, and both Compose environment forms. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 8eab11c3-3153-4036-9847-28a2f615835f --- iac/ql/lib/codeql/iac/compose/Compose.qll | 81 ++++++- .../lib/codeql/iac/kubernetes/Kubernetes.qll | 218 ++++++++++++++++++ iac/ql/lib/iac.qll | 3 + iac/ql/test/library-tests/compose/ast/AST.ql | 5 + .../compose/ast/compose-list.yaml | 11 + .../library-tests/compose/ast/compose.yaml | 18 ++ .../test/library-tests/kubernetes/ast/AST.ql | 13 ++ .../kubernetes/ast/workloads.yaml | 54 +++++ 8 files changed, 401 insertions(+), 2 deletions(-) create mode 100644 iac/ql/lib/codeql/iac/kubernetes/Kubernetes.qll create mode 100644 iac/ql/test/library-tests/compose/ast/AST.ql create mode 100644 iac/ql/test/library-tests/compose/ast/compose-list.yaml create mode 100644 iac/ql/test/library-tests/compose/ast/compose.yaml create mode 100644 iac/ql/test/library-tests/kubernetes/ast/AST.ql create mode 100644 iac/ql/test/library-tests/kubernetes/ast/workloads.yaml diff --git a/iac/ql/lib/codeql/iac/compose/Compose.qll b/iac/ql/lib/codeql/iac/compose/Compose.qll index 496d123c4483..f0905bb353dc 100644 --- a/iac/ql/lib/codeql/iac/compose/Compose.qll +++ b/iac/ql/lib/codeql/iac/compose/Compose.qll @@ -34,6 +34,12 @@ module Compose { * Returns the services defined in the Compose file. */ Service getServices() { result = this.lookup("services").getAChildNode() } + + YamlValue getNetworks() { result = this.lookup("networks") } + + YamlValue getVolumes() { result = this.lookup("volumes") } + + YamlValue getSecrets() { result = this.lookup("secrets") } } /** @@ -51,8 +57,79 @@ module Compose { * Returns the name of the service. */ string getName() { - result = this.lookup("container_name").toString() - // TODO get parent key name + result = yamlToString(this.lookup("container_name")) + or + exists(YamlMapping services, YamlValue key, YamlValue value | + services = compose.lookup("services") and + services.maps(key, value) and + value = this and + result = key.toString() + ) + } + + string getImage() { result = yamlToString(this.lookup("image")) } + + YamlValue getBuild() { result = this.lookup("build") } + + YamlValue getEnvironment() { result = this.lookup("environment") } + + EnvironmentEntry getEnvironmentEntries() { + result = this.lookup("environment").(YamlSequence).getAChild() + or + result = this.lookup("environment").(YamlMapping).getAChild() + } + + YamlValue getSecrets() { result = this.lookup("secrets") } + + YamlValue getVolumes() { result = this.lookup("volumes") } + + YamlValue getCapAdd() { result = this.lookup("cap_add") } + + YamlValue getCapDrop() { result = this.lookup("cap_drop") } + + YamlValue getPrivileged() { result = this.lookup("privileged") } + + YamlValue getReadOnly() { result = this.lookup("read_only") } + + YamlValue getUser() { result = this.lookup("user") } + + YamlValue getPid() { result = this.lookup("pid") } + + YamlValue getNetworkMode() { result = this.lookup("network_mode") } + + YamlValue getDevices() { result = this.lookup("devices") } + } + + class EnvironmentEntry extends YamlNode { + EnvironmentEntry() { + exists(Service service | + service.lookup("environment").(YamlSequence).getAChildNode() = this + ) + or + exists(Service service | + service.lookup("environment").(YamlMapping).getAChildNode() = this + ) + } + + string getName() { + result = this.(YamlString).getValue() + or + exists(YamlMapping environment, YamlValue key, YamlValue value | + environment.getAChildNode() = this and + environment.maps(key, value) and + value = this and + result = key.toString() + ) + } + + YamlValue getValue() { + result = this.(YamlMapping).lookup("value") + or + result = this.(YamlMapping).lookup("value_from") + or + result = this.(YamlMapping).lookup("value") + or + result = this } } } diff --git a/iac/ql/lib/codeql/iac/kubernetes/Kubernetes.qll b/iac/ql/lib/codeql/iac/kubernetes/Kubernetes.qll new file mode 100644 index 000000000000..97516328f9c2 --- /dev/null +++ b/iac/ql/lib/codeql/iac/kubernetes/Kubernetes.qll @@ -0,0 +1,218 @@ +private import codeql.iac.YAML +private import codeql.files.FileSystem + +/** + * Structural model for Kubernetes YAML manifests. + * + * The model intentionally covers locally observable workload and RBAC + * structure. It does not attempt to resolve admission policies, rendered Helm + * values, or cluster-level defaults. + */ +module YamlKubernetes { + class Document extends YamlNode, YamlDocument, YamlMapping { + Document() { + this.getFile().getExtension() = ["yml", "yaml"] and + exists(this.lookup("apiVersion")) and + exists(this.lookup("kind")) + } + + override string toString() { result = "Kubernetes " + this.getKind() + " document" } + + string getApiVersion() { result = yamlToString(this.lookup("apiVersion")) } + + string getKind() { result = yamlToString(this.lookup("kind")) } + + Metadata getMetadata() { result = this.lookup("metadata") } + + YamlMapping getSpec() { result = this.lookup("spec") } + + PodSpec getPodSpec() { + result = this.getSpec().(PodSpec) + or + result = this.getSpec().lookup("template").(YamlMapping).lookup("spec").(PodSpec) + or + result = this.getSpec().lookup("jobTemplate").(YamlMapping).lookup("spec").(YamlMapping) + .lookup("template").(YamlMapping).lookup("spec").(PodSpec) + } + + Container getContainers() { result = this.getPodSpec().getContainers() } + + Container getInitContainers() { result = this.getPodSpec().getInitContainers() } + + Container getEphemeralContainers() { result = this.getPodSpec().getEphemeralContainers() } + } + + class Metadata extends YamlNode, YamlMapping { + Metadata() { exists(Document document | document.lookup("metadata") = this) } + + string getName() { result = yamlToString(this.lookup("name")) } + + string getNamespace() { result = yamlToString(this.lookup("namespace")) } + + YamlValue getLabels() { result = this.lookup("labels") } + + YamlValue getAnnotations() { result = this.lookup("annotations") } + } + + class PodSpec extends YamlNode, YamlMapping { + PodSpec() { + exists(Document document | document.getSpec() = this) + or + exists(YamlMapping template | template.lookup("spec") = this) + } + + Container getContainers() { result = this.lookup("containers").(YamlSequence).getAChild() } + + Container getInitContainers() { + result = this.lookup("initContainers").(YamlSequence).getAChild() + } + + Container getEphemeralContainers() { + result = this.lookup("ephemeralContainers").(YamlSequence).getAChild() + } + + SecurityContext getSecurityContext() { result = this.lookup("securityContext") } + + YamlValue getServiceAccountName() { result = this.lookup("serviceAccountName") } + + YamlValue getAutomountServiceAccountToken() { + result = this.lookup("automountServiceAccountToken") + } + + Volume getVolumes() { result = this.lookup("volumes").(YamlSequence).getAChild() } + + YamlValue getHostNetwork() { result = this.lookup("hostNetwork") } + + YamlValue getHostPid() { result = this.lookup("hostPID") } + + YamlValue getHostIpc() { result = this.lookup("hostIPC") } + } + + class Container extends YamlNode, YamlMapping { + Container() { + exists(PodSpec pod | pod.lookup("containers").(YamlSequence).getAChildNode() = this) + or + exists(PodSpec pod | pod.lookup("initContainers").(YamlSequence).getAChildNode() = this) + or + exists(PodSpec pod | pod.lookup("ephemeralContainers").(YamlSequence).getAChildNode() = this) + } + + string getName() { result = yamlToString(this.lookup("name")) } + + string getImage() { result = yamlToString(this.lookup("image")) } + + SecurityContext getSecurityContext() { result = this.lookup("securityContext") } + + YamlValue getCommand() { result = this.lookup("command") } + + YamlValue getArgs() { result = this.lookup("args") } + + YamlValue getEnv() { result = this.lookup("env") } + + EnvEntry getEnvironmentEntries() { result = this.lookup("env").(YamlSequence).getAChild() } + + YamlValue getEnvFrom() { result = this.lookup("envFrom") } + + YamlValue getVolumeMounts() { result = this.lookup("volumeMounts") } + + YamlValue getPorts() { result = this.lookup("ports") } + } + + class EnvEntry extends YamlNode, YamlMapping { + EnvEntry() { + exists(Container container | container.lookup("env").(YamlSequence).getAChildNode() = this) + } + + string getName() { result = yamlToString(this.lookup("name")) } + + YamlValue getValue() { result = this.lookup("value") } + + YamlMapping getValueFrom() { result = this.lookup("valueFrom") } + + YamlMapping getSecretKeyRef() { result = this.getValueFrom().lookup("secretKeyRef") } + + YamlMapping getConfigMapKeyRef() { result = this.getValueFrom().lookup("configMapKeyRef") } + } + + class SecurityContext extends YamlNode, YamlMapping { + SecurityContext() { + exists(PodSpec pod | pod.lookup("securityContext") = this) + or + exists(Container container | container.lookup("securityContext") = this) + } + + YamlValue getPrivileged() { result = this.lookup("privileged") } + + YamlValue getAllowPrivilegeEscalation() { + result = this.lookup("allowPrivilegeEscalation") + } + + YamlValue getRunAsUser() { result = this.lookup("runAsUser") } + + YamlValue getRunAsGroup() { result = this.lookup("runAsGroup") } + + YamlValue getRunAsNonRoot() { result = this.lookup("runAsNonRoot") } + + YamlValue getReadOnlyRootFilesystem() { + result = this.lookup("readOnlyRootFilesystem") + } + + YamlValue getCapabilities() { result = this.lookup("capabilities") } + + YamlValue getSeccompProfile() { result = this.lookup("seccompProfile") } + } + + class Volume extends YamlNode, YamlMapping { + Volume() { exists(PodSpec pod | pod.lookup("volumes").(YamlSequence).getAChildNode() = this) } + + string getName() { result = yamlToString(this.lookup("name")) } + + YamlValue getHostPath() { result = this.lookup("hostPath") } + + YamlValue getProjected() { result = this.lookup("projected") } + + YamlValue getSecret() { result = this.lookup("secret") } + + YamlValue getConfigMap() { result = this.lookup("configMap") } + } + + class Role extends Document { + Role() { this.getKind() = ["Role", "ClusterRole"] } + + Rule getRules() { result = this.getSpec().lookup("rules").(YamlSequence).getAChild() } + } + + class Rule extends YamlNode, YamlMapping { + Rule() { exists(Role role | role.getSpec().lookup("rules").(YamlSequence).getAChildNode() = this) } + + YamlValue getApiGroups() { result = this.lookup("apiGroups") } + + YamlValue getResources() { result = this.lookup("resources") } + + YamlValue getVerbs() { result = this.lookup("verbs") } + + YamlValue getResourceNames() { result = this.lookup("resourceNames") } + } + + class RoleBinding extends Document { + RoleBinding() { this.getKind() = ["RoleBinding", "ClusterRoleBinding"] } + + YamlMapping getRoleRef() { result = this.getSpec().lookup("roleRef") } + + Subject getSubjects() { result = this.getSpec().lookup("subjects").(YamlSequence).getAChild() } + } + + class Subject extends YamlNode, YamlMapping { + Subject() { + exists(RoleBinding binding | + binding.getSpec().lookup("subjects").(YamlSequence).getAChildNode() = this + ) + } + + string getKind() { result = yamlToString(this.lookup("kind")) } + + string getName() { result = yamlToString(this.lookup("name")) } + + string getNamespace() { result = yamlToString(this.lookup("namespace")) } + } +} diff --git a/iac/ql/lib/iac.qll b/iac/ql/lib/iac.qll index f5258b4b39dd..62838ba9a842 100644 --- a/iac/ql/lib/iac.qll +++ b/iac/ql/lib/iac.qll @@ -12,6 +12,8 @@ import codeql.iac.containers.Containers import codeql.iac.containers.Images // Compose import codeql.iac.compose.Compose +// Kubernetes +import codeql.iac.kubernetes.Kubernetes // HelmCharts import codeql.iac.helmcharts.HelmChart // Terraform / HCL @@ -20,3 +22,4 @@ import hcl import codeql.iac.openapi.OpenApi // YAML import codeql.iac.YAML +import codeql.iac.YamlDocumentClassification diff --git a/iac/ql/test/library-tests/compose/ast/AST.ql b/iac/ql/test/library-tests/compose/ast/AST.ql new file mode 100644 index 000000000000..7f16160e10e6 --- /dev/null +++ b/iac/ql/test/library-tests/compose/ast/AST.ql @@ -0,0 +1,5 @@ +private import iac + +query predicate documents(Compose::Document n) { any() } +query predicate services(Compose::Service n) { any() } +query predicate environment(Compose::EnvironmentEntry n) { any() } diff --git a/iac/ql/test/library-tests/compose/ast/compose-list.yaml b/iac/ql/test/library-tests/compose/ast/compose-list.yaml new file mode 100644 index 000000000000..0d853ba26cdd --- /dev/null +++ b/iac/ql/test/library-tests/compose/ast/compose-list.yaml @@ -0,0 +1,11 @@ +services: + worker: + image: example/worker:1.0 + environment: + - DEBUG=true + - API_TOKEN + secrets: + - worker-token +secrets: + worker-token: + file: ./worker-token.txt diff --git a/iac/ql/test/library-tests/compose/ast/compose.yaml b/iac/ql/test/library-tests/compose/ast/compose.yaml new file mode 100644 index 000000000000..74fe325175ec --- /dev/null +++ b/iac/ql/test/library-tests/compose/ast/compose.yaml @@ -0,0 +1,18 @@ +services: + web: + image: nginx:1.25 + environment: + PASSWORD: ${PASSWORD} + DEBUG: "true" + secrets: + - app-password + cap_drop: + - ALL + read_only: true + user: "1000:1000" + network_mode: bridge + volumes: + - ./web:/srv/web +secrets: + app-password: + file: ./password.txt diff --git a/iac/ql/test/library-tests/kubernetes/ast/AST.ql b/iac/ql/test/library-tests/kubernetes/ast/AST.ql new file mode 100644 index 000000000000..d265519566fc --- /dev/null +++ b/iac/ql/test/library-tests/kubernetes/ast/AST.ql @@ -0,0 +1,13 @@ +private import iac + +query predicate documents(YamlKubernetes::Document n) { any() } +query predicate metadata(YamlKubernetes::Metadata n) { any() } +query predicate podSpecs(YamlKubernetes::PodSpec n) { any() } +query predicate containers(YamlKubernetes::Container n) { any() } +query predicate env(YamlKubernetes::EnvEntry n) { any() } +query predicate security(YamlKubernetes::SecurityContext n) { any() } +query predicate volumes(YamlKubernetes::Volume n) { any() } +query predicate roles(YamlKubernetes::Role n) { any() } +query predicate rules(YamlKubernetes::Rule n) { any() } +query predicate bindings(YamlKubernetes::RoleBinding n) { any() } +query predicate subjects(YamlKubernetes::Subject n) { any() } diff --git a/iac/ql/test/library-tests/kubernetes/ast/workloads.yaml b/iac/ql/test/library-tests/kubernetes/ast/workloads.yaml new file mode 100644 index 000000000000..390918371b0b --- /dev/null +++ b/iac/ql/test/library-tests/kubernetes/ast/workloads.yaml @@ -0,0 +1,54 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: web + namespace: prod +spec: + replicas: 2 + template: + metadata: + labels: + app: web + spec: + serviceAccountName: web + automountServiceAccountToken: false + hostNetwork: false + containers: + - name: web + image: nginx:1.25 + env: + - name: PASSWORD + valueFrom: + secretKeyRef: + name: app-secrets + key: password + securityContext: + privileged: false + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + volumes: + - name: config + configMap: + name: app-config +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: reader +rules: + - apiGroups: [""] + resources: ["pods"] + verbs: ["get", "list"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: reader-binding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: reader +subjects: + - kind: ServiceAccount + name: web + namespace: prod From 4e86ca029a68f5e4ed5968777affa7d1b6213210 Mon Sep 17 00:00:00 2001 From: chanel-y Date: Thu, 17 Sep 2026 12:26:56 -0700 Subject: [PATCH 2/2] Fix Kubernetes and Compose model relationships Restrict pod specs to actual workload locations, model top-level Kubernetes RBAC rules and subjects, and normalize Compose mapping and list environment entries. Add generated expected outputs and classify Kubernetes YAML through the shared document foundation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 8eab11c3-3153-4036-9847-28a2f615835f --- .../codeql/iac/YamlDocumentClassification.qll | 4 +- iac/ql/lib/codeql/iac/compose/Compose.qll | 24 ++++------- .../lib/codeql/iac/kubernetes/Kubernetes.qll | 41 +++++++++++-------- .../library-tests/compose/ast/AST.expected | 13 ++++++ ...{compose-list.yaml => docker-compose.yaml} | 0 .../library-tests/kubernetes/ast/AST.expected | 31 ++++++++++++++ .../yaml-classification/AST.expected | 2 + 7 files changed, 83 insertions(+), 32 deletions(-) create mode 100644 iac/ql/test/library-tests/compose/ast/AST.expected rename iac/ql/test/library-tests/compose/ast/{compose-list.yaml => docker-compose.yaml} (100%) create mode 100644 iac/ql/test/library-tests/kubernetes/ast/AST.expected diff --git a/iac/ql/lib/codeql/iac/YamlDocumentClassification.qll b/iac/ql/lib/codeql/iac/YamlDocumentClassification.qll index 9829bfe845d7..bff776bff270 100644 --- a/iac/ql/lib/codeql/iac/YamlDocumentClassification.qll +++ b/iac/ql/lib/codeql/iac/YamlDocumentClassification.qll @@ -22,6 +22,7 @@ import iac private import codeql.iac.YAML private import codeql.iac.azure.Pipelines private import codeql.iac.helmcharts.HelmChart +private import codeql.iac.kubernetes.Kubernetes private import codeql.iac.compose.Compose private import codeql.iac.openapi.OpenApi private import codeql.iac.aws.CloudFormation @@ -69,7 +70,8 @@ module YamlDocumentClassification { ( doc instanceof AzurePipelines::Document and kind = "ado-pipeline" or - doc instanceof HelmChart::Document and kind = "kubernetes-helm" + (doc instanceof HelmChart::Document or doc instanceof YamlKubernetes::Document) and + kind = "kubernetes-helm" or doc instanceof Compose::Document and kind = "compose" or diff --git a/iac/ql/lib/codeql/iac/compose/Compose.qll b/iac/ql/lib/codeql/iac/compose/Compose.qll index f0905bb353dc..78b0cca8a045 100644 --- a/iac/ql/lib/codeql/iac/compose/Compose.qll +++ b/iac/ql/lib/codeql/iac/compose/Compose.qll @@ -100,36 +100,30 @@ module Compose { YamlValue getDevices() { result = this.lookup("devices") } } - class EnvironmentEntry extends YamlNode { + class EnvironmentEntry extends YamlValue { EnvironmentEntry() { exists(Service service | - service.lookup("environment").(YamlSequence).getAChildNode() = this + service.lookup("environment").(YamlSequence).getAChild() = this ) or exists(Service service | - service.lookup("environment").(YamlMapping).getAChildNode() = this + service.lookup("environment").(YamlMapping).getAChild() = this ) } string getName() { - result = this.(YamlString).getValue() - or exists(YamlMapping environment, YamlValue key, YamlValue value | - environment.getAChildNode() = this and environment.maps(key, value) and value = this and - result = key.toString() + result = yamlToString(key.(YamlString)) ) - } - - YamlValue getValue() { - result = this.(YamlMapping).lookup("value") - or - result = this.(YamlMapping).lookup("value_from") or - result = this.(YamlMapping).lookup("value") + result = this.(YamlString).getValue().regexpCapture("([^=]+)=.*", 1) or - result = this + result = this.(YamlString).getValue() and + not result.matches("%=%") } + + YamlValue getValue() { result = this } } } diff --git a/iac/ql/lib/codeql/iac/kubernetes/Kubernetes.qll b/iac/ql/lib/codeql/iac/kubernetes/Kubernetes.qll index 97516328f9c2..30f1cc123213 100644 --- a/iac/ql/lib/codeql/iac/kubernetes/Kubernetes.qll +++ b/iac/ql/lib/codeql/iac/kubernetes/Kubernetes.qll @@ -13,7 +13,8 @@ module YamlKubernetes { Document() { this.getFile().getExtension() = ["yml", "yaml"] and exists(this.lookup("apiVersion")) and - exists(this.lookup("kind")) + exists(this.lookup("kind")) and + this.lookup("kind").(YamlString).getValue() != "Chart" } override string toString() { result = "Kubernetes " + this.getKind() + " document" } @@ -26,14 +27,7 @@ module YamlKubernetes { YamlMapping getSpec() { result = this.lookup("spec") } - PodSpec getPodSpec() { - result = this.getSpec().(PodSpec) - or - result = this.getSpec().lookup("template").(YamlMapping).lookup("spec").(PodSpec) - or - result = this.getSpec().lookup("jobTemplate").(YamlMapping).lookup("spec").(YamlMapping) - .lookup("template").(YamlMapping).lookup("spec").(PodSpec) - } + PodSpec getPodSpec() { result.getDocument() = this } Container getContainers() { result = this.getPodSpec().getContainers() } @@ -56,9 +50,24 @@ module YamlKubernetes { class PodSpec extends YamlNode, YamlMapping { PodSpec() { - exists(Document document | document.getSpec() = this) + exists(Document document | + document.getKind() = "Pod" and + document.lookup("spec") = this + ) or - exists(YamlMapping template | template.lookup("spec") = this) + exists(Document document | + document.getKind() = + [ + "DaemonSet", "Deployment", "Job", "ReplicaSet", "ReplicationController", "StatefulSet", + ] and + document.lookup("spec").(YamlMapping).lookup("template").(YamlMapping).lookup("spec") = this + ) + or + exists(Document document | + document.getKind() = "CronJob" and + document.lookup("spec").(YamlMapping).lookup("jobTemplate").(YamlMapping).lookup("spec") + .(YamlMapping).lookup("template").(YamlMapping).lookup("spec") = this + ) } Container getContainers() { result = this.lookup("containers").(YamlSequence).getAChild() } @@ -179,11 +188,11 @@ module YamlKubernetes { class Role extends Document { Role() { this.getKind() = ["Role", "ClusterRole"] } - Rule getRules() { result = this.getSpec().lookup("rules").(YamlSequence).getAChild() } + Rule getRules() { result = this.lookup("rules").(YamlSequence).getAChild() } } class Rule extends YamlNode, YamlMapping { - Rule() { exists(Role role | role.getSpec().lookup("rules").(YamlSequence).getAChildNode() = this) } + Rule() { exists(Role role | role.lookup("rules").(YamlSequence).getAChildNode() = this) } YamlValue getApiGroups() { result = this.lookup("apiGroups") } @@ -197,15 +206,15 @@ module YamlKubernetes { class RoleBinding extends Document { RoleBinding() { this.getKind() = ["RoleBinding", "ClusterRoleBinding"] } - YamlMapping getRoleRef() { result = this.getSpec().lookup("roleRef") } + YamlMapping getRoleRef() { result = this.lookup("roleRef") } - Subject getSubjects() { result = this.getSpec().lookup("subjects").(YamlSequence).getAChild() } + Subject getSubjects() { result = this.lookup("subjects").(YamlSequence).getAChild() } } class Subject extends YamlNode, YamlMapping { Subject() { exists(RoleBinding binding | - binding.getSpec().lookup("subjects").(YamlSequence).getAChildNode() = this + binding.lookup("subjects").(YamlSequence).getAChildNode() = this ) } diff --git a/iac/ql/test/library-tests/compose/ast/AST.expected b/iac/ql/test/library-tests/compose/ast/AST.expected new file mode 100644 index 000000000000..9ebc41d7f4ee --- /dev/null +++ b/iac/ql/test/library-tests/compose/ast/AST.expected @@ -0,0 +1,13 @@ +documents +| compose.yaml:1:1:18:25 | services: | +| docker-compose.yaml:1:1:11:29 | services: | +services +| compose.yaml:3:5:15:23 | image: nginx:1.25 | +| docker-compose.yaml:3:5:8:21 | image: ... ker:1.0 | +environment +| compose.yaml:5:7:5:14 | PASSWORD | +| compose.yaml:5:17:5:27 | ${PASSWORD} | +| compose.yaml:6:7:6:11 | DEBUG | +| compose.yaml:6:14:6:19 | "true" | +| docker-compose.yaml:5:9:5:18 | DEBUG=true | +| docker-compose.yaml:6:9:6:17 | API_TOKEN | diff --git a/iac/ql/test/library-tests/compose/ast/compose-list.yaml b/iac/ql/test/library-tests/compose/ast/docker-compose.yaml similarity index 100% rename from iac/ql/test/library-tests/compose/ast/compose-list.yaml rename to iac/ql/test/library-tests/compose/ast/docker-compose.yaml diff --git a/iac/ql/test/library-tests/kubernetes/ast/AST.expected b/iac/ql/test/library-tests/kubernetes/ast/AST.expected new file mode 100644 index 000000000000..7b800c10241c --- /dev/null +++ b/iac/ql/test/library-tests/kubernetes/ast/AST.expected @@ -0,0 +1,31 @@ +documents +| workloads.yaml:1:1:32:29 | HelmChart Document | +| workloads.yaml:1:1:32:29 | Kubernetes Deployment document | +| workloads.yaml:34:1:41:27 | HelmChart Document | +| workloads.yaml:34:1:41:27 | Kubernetes ClusterRole document | +| workloads.yaml:43:1:54:20 | HelmChart Document | +| workloads.yaml:43:1:54:20 | Kubernetes ClusterRoleBinding document | +metadata +| workloads.yaml:4:3:5:18 | name: web | +| workloads.yaml:37:3:37:15 | name: reader | +| workloads.yaml:46:3:46:23 | name: reader-binding | +podSpecs +| workloads.yaml:13:7:32:29 | service ... me: web | +containers +| workloads.yaml:17:11:29:6 | name: web | +env +| workloads.yaml:20:15:25:10 | name: PASSWORD | +security +| workloads.yaml:26:13:29:6 | privileged: false | +volumes +| workloads.yaml:30:11:32:29 | name: config | +roles +| workloads.yaml:34:1:41:27 | HelmChart Document | +| workloads.yaml:34:1:41:27 | Kubernetes ClusterRole document | +rules +| workloads.yaml:39:5:41:27 | apiGroups: [""] | +bindings +| workloads.yaml:43:1:54:20 | HelmChart Document | +| workloads.yaml:43:1:54:20 | Kubernetes ClusterRoleBinding document | +subjects +| workloads.yaml:52:5:54:20 | kind: ServiceAccount | diff --git a/iac/ql/test/library-tests/yaml-classification/AST.expected b/iac/ql/test/library-tests/yaml-classification/AST.expected index c8d07e824bca..75de151586df 100644 --- a/iac/ql/test/library-tests/yaml-classification/AST.expected +++ b/iac/ql/test/library-tests/yaml-classification/AST.expected @@ -3,6 +3,7 @@ supportedYamlDocument | cloudformation.yaml:1:1:6:29 | CloudFormation Document | cloudformation | | compose.yaml:1:1:4:24 | version: "3.9" | compose | | deployment.yaml:1:1:8:29 | HelmChart Document | kubernetes-helm | +| deployment.yaml:1:1:8:29 | Kubernetes Deployment document | kubernetes-helm | | openapi.yaml:1:1:12:26 | OpenApi Document | openapi | allYamlDocuments | arm-template.yaml:1:1:5:24 | $schema ... .json#" | @@ -10,6 +11,7 @@ allYamlDocuments | cloudformation.yaml:1:1:6:29 | CloudFormation Document | | compose.yaml:1:1:4:24 | version: "3.9" | | deployment.yaml:1:1:8:29 | HelmChart Document | +| deployment.yaml:1:1:8:29 | Kubernetes Deployment document | | openapi.json:1:1:8:1 | OpenApi Document | | openapi.yaml:1:1:12:26 | OpenApi Document | | unrelated.yaml:1:1:4:8 | descrip ... ocument |