Skip to content

Commit 608d129

Browse files
committed
[confcom] Add --platform commandline option
1 parent ef8c8cd commit 608d129

File tree

4 files changed

+47
-28
lines changed

4 files changed

+47
-28
lines changed

src/confcom/azext_confcom/_params.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,14 @@ def load_arguments(self, _):
114114
help="Image Name",
115115
validator=validate_aci_source
116116
)
117+
c.argument(
118+
"platform",
119+
options_list=("--platform",),
120+
required=False,
121+
default="linux/amd64",
122+
help="Target platform for policy generation. Defaults to linux/amd64.",
123+
choices=["linux/amd64", "windows/amd64"],
124+
)
117125
c.argument(
118126
"tar_mapping_location",
119127
options_list=("--tar",),

src/confcom/azext_confcom/custom.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ def acipolicygen_confcom(
4242
virtual_node_yaml_path: str,
4343
infrastructure_svn: str,
4444
tar_mapping_location: str,
45+
platform: str = "linux/amd64",
4546
container_definitions: Optional[list] = None,
4647
approve_wildcards: str = False,
4748
outraw: bool = False,
@@ -120,6 +121,7 @@ def acipolicygen_confcom(
120121
if output_type == security_policy.OutputType.DEFAULT
121122
else "clear text",
122123
)
124+
logger.warning("Using platform: %s", platform)
123125
# error checking for making sure an input is provided is above
124126
if input_path:
125127
container_group_policies = security_policy.load_policy_from_json_file(
@@ -128,6 +130,7 @@ def acipolicygen_confcom(
128130
infrastructure_svn=infrastructure_svn,
129131
disable_stdio=(not stdio_enabled),
130132
exclude_default_fragments=exclude_default_fragments,
133+
platform=platform,
131134
)
132135
elif arm_template:
133136
container_group_policies = security_policy.load_policy_from_arm_template_file(
@@ -140,10 +143,12 @@ def acipolicygen_confcom(
140143
diff_mode=diff,
141144
rego_imports=fragments_list,
142145
exclude_default_fragments=exclude_default_fragments,
146+
platform=platform,
143147
)
144148
elif image_name:
145149
container_group_policies = security_policy.load_policy_from_image_name(
146-
image_name, debug_mode=debug_mode, disable_stdio=(not stdio_enabled)
150+
image_name, debug_mode=debug_mode, disable_stdio=(not stdio_enabled),
151+
platform=platform,
147152
)
148153
elif virtual_node_yaml_path:
149154
container_group_policies = security_policy.load_policy_from_virtual_node_yaml_file(
@@ -155,6 +160,7 @@ def acipolicygen_confcom(
155160
rego_imports=fragments_list,
156161
exclude_default_fragments=exclude_default_fragments,
157162
infrastructure_svn=infrastructure_svn,
163+
platform=platform,
158164
)
159165
elif container_definitions:
160166
container_group_policies = AciPolicy(

src/confcom/azext_confcom/lib/containers.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66

77
from dataclasses import asdict
8-
from azext_confcom.lib.images import get_image_layers, get_image_config, get_image_platform
8+
from azext_confcom.lib.images import get_image_layers, get_image_config, get_image_platform # pylint: disable=unused-import
99
from azext_confcom.lib.platform import ACI_MOUNTS, VN2_MOUNTS
1010

1111

@@ -36,20 +36,18 @@ def merge_containers(*args) -> dict:
3636
return merged_container
3737

3838

39-
def from_image(image: str, aci_or_vn2: str) -> dict:
39+
def from_image(image: str, aci_or_vn2: str, platform: str = "linux/amd64") -> dict:
4040

4141
mounts = {
4242
"aci": [asdict(mount) for mount in ACI_MOUNTS],
4343
"vn2": VN2_MOUNTS,
4444
}.get(aci_or_vn2, None)
4545

46-
image_platform = get_image_platform(image)
47-
4846
return {
4947
"id": image,
5048
"name": image,
51-
"layers": get_image_layers(image, platform=image_platform),
52-
"platform": image_platform,
49+
"layers": get_image_layers(image, platform=platform),
50+
"platform": platform,
5351
**({"mounts": mounts} if mounts else {}),
5452
**get_image_config(image),
5553
}

src/confcom/azext_confcom/security_policy.py

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,8 @@
4141
process_fragment_imports,
4242
process_mounts,
4343
process_mounts_from_config,
44-
readable_diff,
45-
find_value_in_params_and_vars)
46-
from azext_confcom.lib.images import get_image_platform
44+
readable_diff)
45+
from azext_confcom.lib.images import get_image_platform # pylint: disable=unused-import
4746
from azext_confcom.lib.defaults import get_debug_mode_exec_procs
4847
from knack.log import get_logger
4948
from tqdm import tqdm
@@ -281,7 +280,7 @@ def validate_sidecars(self) -> Tuple[bool, Dict]:
281280
if len(policy_ids) == 0:
282281
eprint("No sidecar images found in the policy.")
283282

284-
policy = load_policy_from_image_name(policy_ids)
283+
policy = load_policy_from_image_name(policy_ids, platform=self._platform or "linux/amd64")
285284

286285
policy.populate_policy_content_for_all_images(individual_image=True)
287286
policy_str = self.get_serialized_output(
@@ -678,6 +677,7 @@ def load_policy_from_arm_template_str(
678677
rego_imports: Any = None,
679678
fragment_contents: Any = None,
680679
exclude_default_fragments: bool = False,
680+
platform: str = "linux/amd64",
681681
) -> List[AciPolicy]:
682682
"""Function that converts ARM template string to an ACI Policy"""
683683
input_arm_json = os_util.load_json_from_str(template_data)
@@ -737,6 +737,18 @@ def load_policy_from_arm_template_str(
737737
container_group_properties = case_insensitive_dict_get(
738738
resource, config.ACI_FIELD_TEMPLATE_PROPERTIES
739739
)
740+
741+
# Validate that osType in the ARM template matches the specified platform
742+
os_type = case_insensitive_dict_get(container_group_properties, "osType")
743+
if os_type:
744+
expected_os = "linux" if platform.startswith("linux") else "windows"
745+
if os_type.lower() != expected_os:
746+
eprint(
747+
f'ARM template osType "{os_type}" does not match '
748+
f'the supplied platform "{platform}". '
749+
f'Please use --platform to specify a consistent platform.'
750+
)
751+
740752
container_list = case_insensitive_dict_get(
741753
container_group_properties, config.ACI_FIELD_TEMPLATE_CONTAINERS
742754
)
@@ -818,16 +830,6 @@ def load_policy_from_arm_template_str(
818830
extract_probe(exec_processes, image_properties, config.ACI_FIELD_CONTAINERS_READINESS_PROBE)
819831
extract_probe(exec_processes, image_properties, config.ACI_FIELD_CONTAINERS_LIVENESS_PROBE)
820832

821-
# Use platform from template if specified, otherwise try to auto-detect from image
822-
platform = case_insensitive_dict_get(image_properties, "platform")
823-
if not platform:
824-
# By this point, we have not substituted any parameters or
825-
# variables yet, but in order to get the image we have to know
826-
# the final image name. So resolve it here temporarily (later
827-
# on, the constructor of AciPolicy will resolve it again)
828-
image_name_with_param_substituted = find_value_in_params_and_vars(all_params, all_vars, image_name)
829-
platform = get_image_platform(image_name_with_param_substituted)
830-
831833
containers.append(
832834
{
833835
config.ACI_FIELD_CONTAINERS_ID: image_name,
@@ -882,6 +884,7 @@ def load_policy_from_arm_template_file(
882884
rego_imports: list = None,
883885
fragment_contents: list = None,
884886
exclude_default_fragments: bool = False,
887+
platform: str = "linux/amd64",
885888
) -> List[AciPolicy]:
886889
"""Utility function: generate policy object from given arm template and parameter file paths"""
887890
input_arm_json = os_util.load_str_from_file(template_path)
@@ -899,11 +902,13 @@ def load_policy_from_arm_template_file(
899902
diff_mode=diff_mode,
900903
fragment_contents=fragment_contents,
901904
exclude_default_fragments=exclude_default_fragments,
905+
platform=platform,
902906
)
903907

904908

905909
def load_policy_from_image_name(
906-
image_names: Union[List[str], str], debug_mode: bool = False, disable_stdio: bool = False
910+
image_names: Union[List[str], str], debug_mode: bool = False, disable_stdio: bool = False,
911+
platform: str = "linux/amd64",
907912
) -> AciPolicy:
908913
# can either take a list of image names or a single image name
909914
if isinstance(image_names, str):
@@ -925,7 +930,7 @@ def load_policy_from_image_name(
925930
container[config.ACI_FIELD_CONTAINERS_CONTAINERIMAGE] = image_name
926931
container[config.ACI_FIELD_CONTAINERS_ALLOW_STDIO_ACCESS] = not disable_stdio
927932

928-
container["platform"] = get_image_platform(image_name)
933+
container["platform"] = platform
929934

930935
containers.append(container)
931936

@@ -945,14 +950,16 @@ def load_policy_from_json_file(
945950
disable_stdio: bool = False,
946951
infrastructure_svn: str = None,
947952
exclude_default_fragments: bool = False,
953+
platform: str = "linux/amd64",
948954
) -> AciPolicy:
949955
json_content = os_util.load_str_from_file(data)
950956
return load_policy_from_json(
951957
json_content,
952958
debug_mode=debug_mode,
953959
disable_stdio=disable_stdio,
954960
infrastructure_svn=infrastructure_svn,
955-
exclude_default_fragments=exclude_default_fragments
961+
exclude_default_fragments=exclude_default_fragments,
962+
platform=platform,
956963
)
957964

958965

@@ -962,6 +969,7 @@ def load_policy_from_json(
962969
disable_stdio: bool = False,
963970
infrastructure_svn: str = None,
964971
exclude_default_fragments: bool = False,
972+
platform: str = "linux/amd64",
965973
) -> AciPolicy:
966974
output_containers = []
967975
# 1) Parse incoming string as JSON
@@ -1070,8 +1078,6 @@ def load_policy_from_json(
10701078

10711079
envs += process_env_vars_from_config(container_properties)
10721080

1073-
platform = get_image_platform(image_name)
1074-
10751081
output_containers.append(
10761082
{
10771083
config.ACI_FIELD_CONTAINERS_ID: image_name,
@@ -1129,6 +1135,7 @@ def load_policy_from_virtual_node_yaml_file(
11291135
exclude_default_fragments: bool = False,
11301136
fragment_contents: list = None,
11311137
infrastructure_svn: str = None,
1138+
platform: str = "linux/amd64",
11321139
) -> List[AciPolicy]:
11331140
yaml_contents_str = os_util.load_str_from_file(virtual_node_yaml_path)
11341141
return load_policy_from_virtual_node_yaml_str(
@@ -1141,6 +1148,7 @@ def load_policy_from_virtual_node_yaml_file(
11411148
exclude_default_fragments=exclude_default_fragments,
11421149
fragment_contents=fragment_contents,
11431150
infrastructure_svn=infrastructure_svn,
1151+
platform=platform,
11441152
)
11451153

11461154

@@ -1155,6 +1163,7 @@ def load_policy_from_virtual_node_yaml_str(
11551163
exclude_default_fragments: bool = False,
11561164
fragment_contents: Any = None,
11571165
infrastructure_svn: str = None,
1166+
platform: str = "linux/amd64",
11581167
) -> List[AciPolicy]:
11591168
"""
11601169
Load a virtual node yaml file and generate a policy object
@@ -1343,8 +1352,6 @@ def load_policy_from_virtual_node_yaml_str(
13431352
extract_lifecycle_hook(exec_processes, container, config.VIRTUAL_NODE_YAML_LIFECYCLE_POST_START)
13441353
extract_lifecycle_hook(exec_processes, container, config.VIRTUAL_NODE_YAML_LIFECYCLE_PRE_STOP)
13451354

1346-
platform = get_image_platform(image)
1347-
13481355
policy_containers.append(
13491356
{
13501357
config.ACI_FIELD_CONTAINERS_ID: image,

0 commit comments

Comments
 (0)