Skip to content
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

Feature/security context #18

Merged
merged 51 commits into from
Apr 27, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
532af61
bug fixes and adding a new flag for approving wildcards for headless …
SethHollandsworth Feb 28, 2023
62df83e
Merge pull request #15 from SethHollandsworth/feature/approve_wildcards
SethHollandsworth Mar 6, 2023
694fb41
Merge branch 'main' of https://github.com/Azure/azure-cli-extensions
hgarvison Mar 8, 2023
57fea59
updating method to get hcsshim files and updating cli version number
hgarvison Mar 8, 2023
f3d1646
making layer caching work across multiple container groups
SethHollandsworth Mar 8, 2023
0a11154
Merge pull request #16 from SethHollandsworth/bugfix/caching-template…
SethHollandsworth Mar 8, 2023
2142e36
securityContext: allowElevatedPrivilege
hgarvison Mar 8, 2023
df075de
Merge branch 'main' of https://github.com/SethHollandsworth/azure-cli…
hgarvison Mar 8, 2023
1bc55cb
runas temp
hgarvison Mar 9, 2023
a29d957
securityContext: user field
hgarvison Mar 10, 2023
eabccbd
securityContext: seccomp_profile
hgarvison Mar 10, 2023
12aa158
adding capabilities array for ARM input
SethHollandsworth Mar 10, 2023
1b56c47
Merge branch 'feature/security_context' into feature/capabilities
SethHollandsworth Mar 10, 2023
2c814d1
making capabilities its own function
SethHollandsworth Mar 10, 2023
905a314
fixing merge conflict
SethHollandsworth Mar 10, 2023
d829010
updating default value
SethHollandsworth Mar 10, 2023
0b9bd74
updating default capabilities and comments about priv escalation
SethHollandsworth Mar 10, 2023
231098a
Merge pull request #17 from SethHollandsworth/feature/capabilities
SethHollandsworth Mar 10, 2023
e21a744
temp
hgarvison Mar 10, 2023
9427d83
Merge branch 'feature/security_context' of https://github.com/SethHol…
hgarvison Mar 10, 2023
8d16134
adding tests for capabilities
SethHollandsworth Mar 10, 2023
200dda4
adding tests and fixing merge conflict
SethHollandsworth Mar 10, 2023
003185a
user/group tests
hgarvison Mar 10, 2023
6ccd646
merge conflicts
hgarvison Mar 10, 2023
f90d828
updated tests
hgarvison Mar 10, 2023
e4465e9
adding a couple bug fixes for using sha hashes
SethHollandsworth Mar 13, 2023
a62dc32
Merge pull request #19 from SethHollandsworth/bugfix/sha_hash_bug
SethHollandsworth Mar 13, 2023
369ed61
Merge branch 'main' of https://github.com/Azure/azure-cli-extensions
SethHollandsworth Mar 14, 2023
5b9f8a7
updating version number
SethHollandsworth Mar 14, 2023
2b9d4b4
style fixes
hgarvison Mar 14, 2023
96e38c1
Merge branch 'main' into feature/security_context
hgarvison Mar 14, 2023
df66d96
updating comment
hgarvison Mar 14, 2023
9054637
update to capabilities
hgarvison Mar 20, 2023
64c5cd9
resolving comments
hgarvison Mar 20, 2023
f4e9e70
fixing infra_svn bug and updating capabilities, adding tests
SethHollandsworth Mar 21, 2023
b97adae
fixing some tests and changing default values
SethHollandsworth Mar 22, 2023
88a8ef5
updating drop capabilities functionality and adding tests
hgarvison Mar 22, 2023
b168f14
resolving comments
hgarvison Mar 22, 2023
e30c749
removing print statement
hgarvison Mar 22, 2023
07b0755
updating version number
SethHollandsworth Mar 22, 2023
21dee19
updating method to check for 32-bit windows and pause container
hgarvison Mar 23, 2023
87f463e
updating logic for excluding win32
hgarvison Mar 23, 2023
f559d44
style checks
hgarvison Mar 23, 2023
fc6582c
bug fix for default value of no_new_privileges in some situations
SethHollandsworth Mar 23, 2023
351920d
removing framework_svn code
hgarvison Mar 29, 2023
96092b2
updating seccomp profile processing
hgarvison Mar 31, 2023
d4f4501
merge conflicts with main
hgarvison Mar 31, 2023
c9e63d4
adding tests and fixing syscall bug
hgarvison Apr 4, 2023
0b41182
Merge branch 'main' into feature/security_context
hgarvison Apr 25, 2023
5c88fd9
allow_elevated logic fixed
hgarvison Apr 26, 2023
91f5f5d
resolving comments
hgarvison Apr 27, 2023
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
Prev Previous commit
Next Next commit
adding capabilities array for ARM input
  • Loading branch information
SethHollandsworth committed Mar 10, 2023
commit 12aa158756c0be8fa74c68f71e67adb4e391db33
14 changes: 14 additions & 0 deletions src/confcom/azext_confcom/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@
ACI_FIELD_TEMPLATE_MOUNTS_READONLY = "readOnly"
ACI_FIELD_TEMPLATE_CONFCOM_PROPERTIES = "confidentialComputeProperties"
ACI_FIELD_TEMPLATE_CCE_POLICY = "ccePolicy"
ACI_FIELD_CONTAINERS_PRIVILEGED = "privileged"
ACI_FIELD_CONTAINERS_CAPABILITIES = "capabilities"
ACI_FIELD_CONTAINERS_CAPABILITIES_ADD = "add"
ACI_FIELD_CONTAINERS_CAPABILITIES_DROP = "drop"


# output json values
Expand Down Expand Up @@ -97,6 +101,12 @@
POLICY_FIELD_CONTAINERS_ELEMENTS_USER_GROUP_IDNAMES = "group_idnames"
POLICY_FIELD_CONTAINERS_ELEMENTS_USER_UMASK = "umask"
POLICY_FIELD_CONTAINERS_ELEMENTS_USER_PATTERN = "pattern"
POLICY_FIELD_CONTAINERS_ELEMENTS_CAPABILITIES = "capabilities"
POLICY_FIELD_CONTAINERS_ELEMENTS_CAPABILITIES_BOUNDING = "bounding"
POLICY_FIELD_CONTAINERS_ELEMENTS_CAPABILITIES_EFFECTIVE = "effective"
POLICY_FIELD_CONTAINERS_ELEMENTS_CAPABILITIES_INHERITABLE = "inheritable"
POLICY_FIELD_CONTAINERS_ELEMENTS_CAPABILITIES_PERMITTED = "permitted"
POLICY_FIELD_CONTAINERS_ELEMENTS_CAPABILITIES_AMBIENT = "ambient"
POLICY_FIELD_CONTAINERS_ELEMENTS_USER_STRATEGY = "strategy"
POLICY_FIELD_CONTAINERS_ELEMENTS_ALLOW_STDIO_ACCESS = "allow_stdio_access"
POLICY_FIELD_CONTAINERS_ELEMENTS_REGO_FRAGMENTS = "fragments"
Expand Down Expand Up @@ -156,3 +166,7 @@
DEFAULT_CONTAINERS = _config["default_containers"]
# default container user config to be added for security context
DEFAULT_USER = _config["default_user"]
# default unpriviliged user capabilities to be added for security context
DEFAULT_UNPRIVILEGED_CAPABILITIES = _config["default_unprivileged_capabilities"]
# default priviliged user capabilities to be added for security context
DEFAULT_PRIVILEGED_CAPABILITIES = _config["default_privileged_capabilities"]
132 changes: 120 additions & 12 deletions src/confcom/azext_confcom/container.py
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ def extract_allow_stdio_access(container_json: Any) -> bool:
def extract_user(container_json: Any) -> Dict:
security_context = case_insensitive_dict_get(
container_json, config.ACI_FIELD_CONTAINERS_SECURITY_CONTEXT
)
)

user = copy.deepcopy(_DEFAULT_USER)
# assumes that securityContext field is optional
Expand Down Expand Up @@ -279,28 +279,136 @@ def extract_user(container_json: Any) -> Dict:
config.POLICY_FIELD_CONTAINERS_ELEMENTS_USER_PATTERN: str(run_as_group_value),
config.POLICY_FIELD_CONTAINERS_ELEMENTS_USER_STRATEGY: "id"
}

# get the field for privileged
privileged_value = case_insensitive_dict_get(
security_context, config.ACI_FIELD_CONTAINERS_PRIVILEGED
)
if not isinstance(privileged_value, bool) and not isinstance(privileged_value, str):
eprint(
f'Field ["{config.ACI_FIELD_CONTAINERS}"]["{config.ACI_FIELD_CONTAINERS_SECURITY_CONTEXT}"]'
+ f'["{config.ACI_FIELD_CONTAINERS_PRIVILEGED}"] can only be a boolean or string value.'
)

# force the field into a bool
if isinstance(privileged_value, str):
privileged_value = privileged_value.lower() == "true"

output_capabilities = {
config.POLICY_FIELD_CONTAINERS_ELEMENTS_CAPABILITIES_BOUNDING: [],
config.POLICY_FIELD_CONTAINERS_ELEMENTS_CAPABILITIES_EFFECTIVE: [],
config.POLICY_FIELD_CONTAINERS_ELEMENTS_CAPABILITIES_INHERITABLE: [],
config.POLICY_FIELD_CONTAINERS_ELEMENTS_CAPABILITIES_PERMITTED: [],
config.POLICY_FIELD_CONTAINERS_ELEMENTS_CAPABILITIES_AMBIENT: [],
}


# if privileged is true, then set all capabilities to true
# else, get the capabilities field from the ARM Template
if privileged_value:
for key in output_capabilities.keys():
output_capabilities[key] = copy.deepcopy(config.DEFAULT_PRIVILEGED_CAPABILITIES)
else:
# get the capabilities field
capabilities = case_insensitive_dict_get(
security_context, config.ACI_FIELD_CONTAINERS_CAPABILITIES
)
if capabilities:
# error check if capabilities is not a dict
if not isinstance(capabilities, dict):
eprint(
f'Field ["{config.ACI_FIELD_CONTAINERS}"]["{config.ACI_FIELD_CONTAINERS_SECURITY_CONTEXT}"]'
+ f'["{config.ACI_FIELD_CONTAINERS_CAPABILITIES}"] can only be a dictionary.'
)

non_added_fields = [
config.POLICY_FIELD_CONTAINERS_ELEMENTS_CAPABILITIES_BOUNDING,
config.POLICY_FIELD_CONTAINERS_ELEMENTS_CAPABILITIES_EFFECTIVE,
config.POLICY_FIELD_CONTAINERS_ELEMENTS_CAPABILITIES_PERMITTED,
]

# drop the capabilities from the output
for key in non_added_fields:
output_capabilities[key] = copy.deepcopy(config.DEFAULT_UNPRIVILEGED_CAPABILITIES)

# get the add field
add = case_insensitive_dict_get(
capabilities, config.ACI_FIELD_CONTAINERS_CAPABILITIES_ADD
)
if add:
# error check if add is not a list
if not isinstance(add, list):
eprint(
f'Field ["{config.ACI_FIELD_CONTAINERS}"]["{config.ACI_FIELD_CONTAINERS_SECURITY_CONTEXT}"]'
+ f'["{config.ACI_FIELD_CONTAINERS_CAPABILITIES_ADD}"] can only be a list.'
)

# add the capabilities to the output
for value in output_capabilities.values():
for capability in add:
if not isinstance(capability, str):
eprint(
f'Field ["{config.ACI_FIELD_CONTAINERS}"]["{config.ACI_FIELD_CONTAINERS_SECURITY_CONTEXT}"]'
+ f'["{config.ACI_FIELD_CONTAINERS_CAPABILITIES_ADD}"] can only contain strings.'
)
value.append(capability)

# get the drop field
drop = case_insensitive_dict_get(
capabilities, config.ACI_FIELD_CONTAINERS_CAPABILITIES_DROP
)
if drop:
# error check if drop is not a list
if not isinstance(drop, list):
eprint(
f'Field ["{config.ACI_FIELD_CONTAINERS}"]["{config.ACI_FIELD_CONTAINERS_SECURITY_CONTEXT}"]'
+ f'["{config.ACI_FIELD_CONTAINERS_CAPABILITIES_DROP}"] can only be a list.'
)

# drop the capabilities from the output
for value in non_added_fields:
for capability in drop:
if not isinstance(capability, str):
eprint(
f'Field ["{config.ACI_FIELD_CONTAINERS}"]["{config.ACI_FIELD_CONTAINERS_SECURITY_CONTEXT}"]'
+ f'["{config.ACI_FIELD_CONTAINERS_CAPABILITIES_DROP}"] can only contain strings.'
)
output_capabilities[value].append(capability)

# de-duplicate the capabilities
for key, value in output_capabilities.items():
output_capabilities[key] = list(set(value))

user[config.POLICY_FIELD_CONTAINERS_ELEMENTS_CAPABILITIES] = output_capabilities


return user


def extract_allow_privilege_escalation(container_json: Any) -> bool:
security_context = case_insensitive_dict_get(
container_json, config.ACI_FIELD_CONTAINERS_SECURITY_CONTEXT
)
)

allow_privilege_escalation = True
hgarvison marked this conversation as resolved.
Show resolved Hide resolved
# assumes that securityContext field is optional
if security_context:
try:
# get the field for allow privilege escalation, default to true
allow_privilege_escalation_value = bool(case_insensitive_dict_get(
security_context, config.ACI_FIELD_CONTAINERS_ALLOW_PRIVILEGE_ESCALATION
))
allow_privilege_escalation = allow_privilege_escalation_value
except ValueError:

# get the field for allow privilege escalation, default to true
allow_privilege_escalation = case_insensitive_dict_get(
security_context, config.ACI_FIELD_CONTAINERS_ALLOW_PRIVILEGE_ESCALATION
)

if not isinstance(allow_privilege_escalation, bool) and not isinstance(allow_privilege_escalation, str):
eprint(
f'Field ["{config.ACI_FIELD_CONTAINERS}"]["{config.ACI_FIELD_CONTAINERS_SECURITY_CONTEXT}"]'
+ f'["{config.ACI_FIELD_CONTAINERS_ALLOW_PRIVILEGE_ESCALATION}"] can only be a boolean value.'
+ f'["{config.ACI_FIELD_CONTAINERS_PRIVILEGED}"] can only be a boolean or string value.'
)

# force the field into a bool
if isinstance(allow_privilege_escalation, str):
allow_privilege_escalation = allow_privilege_escalation.lower() == "true"

return allow_privilege_escalation


Expand Down Expand Up @@ -396,7 +504,7 @@ def __init__(
self._mounts = mounts
self._allow_elevated = allow_elevated
self._allow_stdio_access = allowStdioAccess
self._user = user or {},
self._user = user or {}
self._allow_privilege_escalation = allowPrivilegeEscalation
self._policy_json = None
self._policy_json_str = None
Expand Down
61 changes: 60 additions & 1 deletion src/confcom/azext_confcom/data/internal_config.json
Original file line number Diff line number Diff line change
Expand Up @@ -219,5 +219,64 @@
}
],
"umask": "0022"
}
},
"default_unprivileged_capabilities": [
"CAP_CHOWN",
"CAP_DAC_OVERRIDE",
"CAP_FSETID",
"CAP_FOWNER",
"CAP_MKNOD",
"CAP_NET_RAW",
"CAP_SETGID",
"CAP_SETUID",
"CAP_SETFCAP",
"CAP_SETPCAP",
"CAP_NET_BIND_SERVICE",
"CAP_SYS_CHROOT",
"CAP_KILL",
"CAP_AUDIT_WRITE"
],
"default_privileged_capabilities": [
"CAP_CHOWN",
"CAP_DAC_OVERRIDE",
"CAP_DAC_READ_SEARCH",
"CAP_FOWNER",
"CAP_FSETID",
"CAP_KILL",
"CAP_SETGID",
"CAP_SETUID",
"CAP_SETPCAP",
"CAP_LINUX_IMMUTABLE",
"CAP_NET_BIND_SERVICE",
"CAP_NET_BROADCAST",
"CAP_NET_ADMIN",
"CAP_NET_RAW",
"CAP_IPC_LOCK",
"CAP_IPC_OWNER",
"CAP_SYS_MODULE",
"CAP_SYS_RAWIO",
"CAP_SYS_CHROOT",
"CAP_SYS_PTRACE",
"CAP_SYS_PACCT",
"CAP_SYS_ADMIN",
"CAP_SYS_BOOT",
"CAP_SYS_NICE",
"CAP_SYS_RESOURCE",
"CAP_SYS_TIME",
"CAP_SYS_TTY_CONFIG",
"CAP_MKNOD",
"CAP_LEASE",
"CAP_AUDIT_WRITE",
"CAP_AUDIT_CONTROL",
"CAP_SETFCAP",
"CAP_MAC_OVERRIDE",
"CAP_MAC_ADMIN",
"CAP_SYSLOG",
"CAP_WAKE_ALARM",
"CAP_BLOCK_SUSPEND",
"CAP_AUDIT_READ",
"CAP_PERFMON",
"CAP_BPF",
"CAP_CHECKPOINT_RESTORE"
]
}