Skip to content

Commit d02ac69

Browse files
committed
Bundle cimwriter dll and update tooling to consume json
1 parent e8ba888 commit d02ac69

6 files changed

Lines changed: 52 additions & 11 deletions

File tree

src/confcom/.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@ azext_confcom/bin/*
3232
**/dmverity-vhd
3333
**/bin/genpolicy*
3434

35+
# Exception: CimWriter.dll is required for Windows container support
36+
# Downloaded from Microsoft.Windows.CimWriter.amd64fre NuGet package
37+
# Version: 10.0.28552.1000-260402-1747.br-current-directbase-backport-cwcow
38+
# Source: https://msazure.visualstudio.com/One/_artifacts/feed/Microsoft.Windows.CimWriter.amd64fre@Local
39+
!azext_confcom/bin/CimWriter.dll
40+
3541
# metadata file for coverage reports
3642
**/.coverage
3743

388 KB
Binary file not shown.

src/confcom/azext_confcom/config.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@
127127
POLICY_FIELD_CONTAINERS_ELEMENTS_ENVS_RULE = "pattern"
128128
POLICY_FIELD_CONTAINERS_ELEMENTS_REQUIRED = "required"
129129
POLICY_FIELD_CONTAINERS_ELEMENTS_LAYERS = "layers"
130+
POLICY_FIELD_CONTAINERS_ELEMENTS_MOUNTED_CIM = "mounted_cim"
130131
POLICY_FIELD_CONTAINERS_ELEMENTS_WORKINGDIR = "working_dir"
131132
POLICY_FIELD_CONTAINERS_ELEMENTS_MOUNTS = "mounts"
132133
POLICY_FIELD_CONTAINERS_ELEMENTS_MOUNTS_SOURCE = "source"

src/confcom/azext_confcom/container.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -606,6 +606,7 @@ def __init__(
606606
self._command = command
607607
self._workingDir = workingDir
608608
self._layers = []
609+
self._mounted_cim = []
609610
self._mounts = mounts
610611
self._allow_elevated = allow_elevated
611612
self._allow_stdio_access = allowStdioAccess
@@ -661,6 +662,12 @@ def get_layers(self) -> List[str]:
661662
def set_layers(self, layers: List[str]) -> None:
662663
self._layers = layers
663664

665+
def get_mounted_cim(self) -> List[str]:
666+
return self._mounted_cim
667+
668+
def set_mounted_cim(self, mounted_cim: List[str]) -> None:
669+
self._mounted_cim = mounted_cim
670+
664671
def get_user(self) -> Dict:
665672
return self._user
666673

@@ -784,6 +791,9 @@ def _populate_policy_json_elements(self, omit_id: bool = False) -> Dict[str, Any
784791
elements.update({
785792
config.POLICY_FIELD_CONTAINERS_ELEMENTS_USER: self.get_user()["user_idname"]["pattern"],
786793
})
794+
# Add mounted_cim for Windows if present
795+
if self._mounted_cim:
796+
elements[config.POLICY_FIELD_CONTAINERS_ELEMENTS_MOUNTED_CIM] = self._mounted_cim
787797

788798

789799
if not omit_id:

src/confcom/azext_confcom/rootfs_proxy.py

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,13 @@
55

66

77
import hashlib
8+
import json
89
import os
910
import platform
1011
import stat
1112
import subprocess
1213
import sys
13-
from typing import List
14+
from typing import List, Dict
1415

1516
import requests
1617
from azext_confcom.errors import eprint
@@ -91,7 +92,7 @@ def get_policy_image_layers(
9192
platform: str = "linux/amd64",
9293
tar_location: str = "",
9394
faster_hashing=False
94-
) -> List[str]:
95+
) -> Dict[str, List[str]]:
9596
image_name = f"{image}:{tag}"
9697
# populate layer info
9798
if self.layer_cache.get(image_name):
@@ -125,7 +126,7 @@ def get_policy_image_layers(
125126
check=False,
126127
)
127128

128-
output = []
129+
result = {}
129130
if item.returncode != 0:
130131
if item.stderr.decode("utf-8") != "" and item.stderr.decode("utf-8") is not None:
131132
logger.warning(item.stderr.decode("utf-8"))
@@ -137,13 +138,29 @@ def get_policy_image_layers(
137138
)
138139
sys.exit(item.returncode)
139140
elif len(item.stdout) > 0:
140-
output = item.stdout.decode("utf8").strip("\n").split("\n")
141-
output = [i.split(": ", 1)[1] for i in output if len(i.split(": ", 1)) > 1]
141+
stdout_str = item.stdout.decode("utf8").strip()
142+
143+
# Try parsing as JSON (both Linux and Windows now output JSON)
144+
if stdout_str.startswith("{"):
145+
try:
146+
json_output = json.loads(stdout_str)
147+
result["layers"] = json_output.get("layers", [])
148+
# mounted_cim is only present for Windows
149+
if "mounted_cim" in json_output:
150+
result["mounted_cim"] = json_output["mounted_cim"]
151+
except json.JSONDecodeError as e:
152+
logger.error(f"Failed to parse JSON output: {e}")
153+
sys.exit(1)
154+
else:
155+
# Fallback: line-by-line parsing for older dmverity-vhd versions
156+
lines = stdout_str.split("\n")
157+
layers = [i.split(": ", 1)[1] for i in lines if len(i.split(": ", 1)) > 1]
158+
result["layers"] = layers
142159
else:
143160
eprint(
144161
"Could not get layer hashes"
145162
)
146163

147-
# cache output layers
148-
self.layer_cache[image_name] = output
149-
return output
164+
# cache output
165+
self.layer_cache[image_name] = result
166+
return result

src/confcom/azext_confcom/security_policy.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -597,13 +597,17 @@ def populate_policy_content_for_all_images(
597597
if isinstance(tar_mapping, dict):
598598
tar_location = get_tar_location_from_mapping(tar_mapping, image_name)
599599
# populate layer info
600-
image.set_layers(proxy.get_policy_image_layers(
600+
layer_info = proxy.get_policy_image_layers(
601601
image.base,
602602
image.tag,
603603
platform=self._platform,
604604
tar_location=tar_location if tar else "",
605605
faster_hashing=faster_hashing,
606-
))
606+
)
607+
image.set_layers(layer_info.get("layers", []))
608+
# Set mounted_cim for Windows containers
609+
if "mounted_cim" in layer_info:
610+
image.set_mounted_cim(layer_info["mounted_cim"])
607611

608612
progress.update()
609613
progress.close()
@@ -812,7 +816,10 @@ def load_policy_from_arm_template_str(
812816
extract_probe(exec_processes, image_properties, config.ACI_FIELD_CONTAINERS_READINESS_PROBE)
813817
extract_probe(exec_processes, image_properties, config.ACI_FIELD_CONTAINERS_LIVENESS_PROBE)
814818

815-
platform = get_image_platform(image_name)
819+
# Use platform from template if specified, otherwise try to auto-detect from image
820+
platform = case_insensitive_dict_get(image_properties, "platform")
821+
if not platform:
822+
platform = get_image_platform(image_name)
816823

817824
containers.append(
818825
{

0 commit comments

Comments
 (0)