Skip to content
Open
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
903d348
Initial dataclasses commit
DomAyre Sep 18, 2025
f01ec00
Get all tests passing
DomAyre Sep 19, 2025
b4264cb
Parse parameter values from arm template
DomAyre Sep 20, 2025
2194653
Avoid adding default fragments twice when loading arm template
DomAyre Sep 20, 2025
87e59ff
Avoid adding mounts multiple times
DomAyre Sep 20, 2025
f2921d2
Avoid adding debug exec processes multiple times
DomAyre Sep 20, 2025
83b4081
Remove diff_mode arg for loading arm template
DomAyre Sep 23, 2025
e0724ef
Add path as a field of AciFragmentSpec
DomAyre Sep 23, 2025
83844a2
Respect fragments args
DomAyre Sep 23, 2025
c2fc0dc
Fix case with no fragments
DomAyre Sep 24, 2025
bd271bd
Satisfy azdev style
DomAyre Sep 24, 2025
41babb3
Preserve arbitrary orders to break dependency on fixes
DomAyre Sep 29, 2025
f6fb965
Restore the functionality of --diff
DomAyre Oct 1, 2025
7d62b05
Satisfy azdev style
DomAyre Oct 1, 2025
0d73ba9
Only use infrastructure-svn on the infrastructure fragment
DomAyre Oct 1, 2025
9cfd2d6
Add mypy tests and fix the couple of issues it finds
DomAyre Oct 1, 2025
b08b012
Fix error message
DomAyre Oct 1, 2025
3a0701a
Prevent the new test failing at the --discover step
DomAyre Oct 1, 2025
21989a3
Fix skipping behaviour
DomAyre Oct 1, 2025
65c5286
Clean up test
DomAyre Oct 2, 2025
4e2eba1
Add missing licenses
DomAyre Oct 2, 2025
c940d6c
Don't consider test files for mypy tests
DomAyre Oct 2, 2025
d92c507
Merge remote-tracking branch 'origin' into dataclasses
DomAyre Oct 16, 2025
0ce74fd
Merge remote-tracking branch 'origin' into dataclasses
DomAyre Oct 17, 2025
19a55ae
Retrigger CI
DomAyre Oct 17, 2025
bb06acd
Bump version and history
DomAyre Oct 28, 2025
ab711ab
Bump version after merge of main
DomAyre Oct 28, 2025
a6cc05a
WIP: ca876f4ff [Release] Update index.json for extension [ containera…
DomAyre Oct 29, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/confcom/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,5 @@ azext_confcom/bin/*
**/.coverage

**/htmlcov

!lib/
11 changes: 8 additions & 3 deletions src/confcom/azext_confcom/container.py
Original file line number Diff line number Diff line change
Expand Up @@ -791,12 +791,17 @@ def from_json(
) -> "UserContainerImage":
image = super().from_json(container_json)
image.__class__ = UserContainerImage
mount_paths = {m["mountPath"] for m in image.get_mounts()}
# inject default mounts for user container
if (image.base not in config.BASELINE_SIDECAR_CONTAINERS) and (not is_vn2):
image.get_mounts().extend(_DEFAULT_MOUNTS)
if image.base not in config.BASELINE_SIDECAR_CONTAINERS and not is_vn2:
for mount in _DEFAULT_MOUNTS:
if mount["mountPath"] not in mount_paths:
image.get_mounts().append(mount)

if (image.base not in config.BASELINE_SIDECAR_CONTAINERS) and (is_vn2):
image.get_mounts().extend(_DEFAULT_MOUNTS_VN2)
for mount in _DEFAULT_MOUNTS_VN2:
if mount["mountPath"] not in mount_paths:
image.get_mounts().append(mount)

# Start with the customer environment rules
env_rules = copy.deepcopy(_INJECTED_CUSTOMER_ENV_RULES)
Expand Down
28 changes: 22 additions & 6 deletions src/confcom/azext_confcom/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------

import json
import os
import sys

Expand All @@ -17,7 +18,7 @@
from azext_confcom.kata_proxy import KataPolicyGenProxy
from azext_confcom.security_policy import OutputType
from azext_confcom.template_util import (
get_image_name, inject_policy_into_template, inject_policy_into_yaml,
extract_confidential_properties, get_image_name, inject_policy_into_template, inject_policy_into_yaml,
pretty_print_func, print_existing_policy_from_arm_template,
print_existing_policy_from_yaml, print_func, str_to_sha256)
from knack.log import get_logger
Expand Down Expand Up @@ -123,8 +124,7 @@ def acipolicygen_confcom(
debug_mode=debug_mode,
disable_stdio=disable_stdio,
approve_wildcards=approve_wildcards,
diff_mode=diff,
rego_imports=fragments_list,
included_fragments=fragments_list,
exclude_default_fragments=exclude_default_fragments,
)
elif image_name:
Expand Down Expand Up @@ -168,7 +168,23 @@ def acipolicygen_confcom(
for policy in container_group_policies:
policy.set_fragment_contents(fragment_policy_list)

for count, policy in enumerate(container_group_policies):
for idx, policy in enumerate(container_group_policies):

# We will deprecate diff mode in favour of a separate tool, so we want
# supporting code to be all in one place even if it makes it more nasty
if diff:
if arm_template:
with open(arm_template, 'r') as f:
# pylint: disable=protected-access
policy._existing_cce_policy = extract_confidential_properties(
[r for r in json.load(f)["resources"] if r["type"] in {
"Microsoft.ContainerInstance/containerGroups",
"Microsoft.ContainerInstance/containerGroupProfiles",
}][idx].get("properties", {}))[0]

elif virtual_node_yaml_path:
... # diff mode is handled in the load function

# this is where parameters and variables are populated
policy.populate_policy_content_for_all_images(
individual_image=bool(image_name), tar_mapping=tar_mapping, faster_hashing=faster_hashing
Expand All @@ -178,7 +194,7 @@ def acipolicygen_confcom(
exit_code = validate_sidecar_in_policy(policy, output_type == security_policy.OutputType.PRETTY_PRINT)
elif virtual_node_yaml_path and not (print_policy_to_terminal or outraw or outraw_pretty_print or diff):
result = inject_policy_into_yaml(
virtual_node_yaml_path, policy.get_serialized_output(omit_id=omit_id), count
virtual_node_yaml_path, policy.get_serialized_output(omit_id=omit_id), idx
)
if result:
print(str_to_sha256(policy.get_serialized_output(OutputType.RAW, omit_id=omit_id)))
Expand All @@ -187,7 +203,7 @@ def acipolicygen_confcom(
exit_code = get_diff_outputs(policy, output_type == security_policy.OutputType.PRETTY_PRINT)
elif arm_template and not (print_policy_to_terminal or outraw or outraw_pretty_print):
result = inject_policy_into_template(arm_template, arm_template_parameters,
policy.get_serialized_output(omit_id=omit_id), count)
policy.get_serialized_output(omit_id=omit_id), idx)
if result:
# this is always going to be the unencoded policy
print(str_to_sha256(policy.get_serialized_output(OutputType.RAW, omit_id=omit_id)))
Expand Down
79 changes: 79 additions & 0 deletions src/confcom/azext_confcom/lib/aci_policy_spec.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
from dataclasses import dataclass
from typing import Optional
from typing_extensions import Literal


@dataclass
class AciContainerPropertyEnvVariable:
name: str
value: str
strategy: str
required: bool = False


@dataclass
class AciContainerPropertyExecProcesses:
command: list[str]
signals: Optional[list[str]] = None
allow_stdio_access: bool = True


@dataclass
class AciContainerPropertyVolumeMounts:
mountPath: str
name: Optional[str] = None
readonly: bool = False
mountType: Optional[Literal["azureFile", "secret", "configMap", "emptyDir"]] = None


@dataclass
class AciContainerPropertySecurityContextCapabilities:
add: list[str]
drop: list[str]


@dataclass
class AciContainerPropertySecurityContext:
privileged: Optional[bool] = None
allowPrivilegeEscalation: Optional[bool] = None
runAsUser: Optional[int] = None
runAsGroup: Optional[int] = None
runAsNonRoot: Optional[bool] = None
readOnlyRootFilesystem: Optional[bool] = None
capabilities: Optional[AciContainerPropertySecurityContextCapabilities] = None
seccompProfile: Optional[str] = None


@dataclass
class AciContainerProperties():
image: str
allowStdioAccess: bool = True
environmentVariables: Optional[list[AciContainerPropertyEnvVariable]] = None
execProcesses: Optional[list[AciContainerPropertyExecProcesses]] = None
volumeMounts: Optional[list[AciContainerPropertyVolumeMounts]] = None
securityContext: Optional[AciContainerPropertySecurityContext] = None
command: Optional[list[str]] = None


# ------------------------------------------------------------------------------


@dataclass
class AciFragmentSpec:
feed: str
issuer: str
minimum_svn: str
includes: list[Literal["containers", "fragments"]]
path: Optional[str] = None


@dataclass
class AciContainerSpec:
name: str
properties: AciContainerProperties


@dataclass
class AciPolicySpec:
fragments: Optional[list[AciFragmentSpec]]
containers: Optional[list[AciContainerSpec]]
Loading
Loading