Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 7 additions & 0 deletions src/confcom/HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@
Release History
===============

1.2.5
++++++
* consolidating functions for --input policygen
* bugfix for "scenario" field in json input
* updating tests and examples to use azurelinux
* "name" field is required when using --input

1.2.4
++++++
* rolling back genpolicy version for Azure Linux V2 support instead of V3
Expand Down
152 changes: 126 additions & 26 deletions src/confcom/azext_confcom/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,69 @@ Because the ARM Template does not have a value defined for the "placeholderValue
az deployment group create --template-file "template.json" --parameters "parameters.json"
```

Example 13: Another way to add additional flexibility to a security policy is by using a "pure json" approach to the config file.
This gives the flexibility of using regular expressions for environment variables and including fragments without the need for the `--fragments-json` flag.
It uses the same format as `acifragmentgen` such that if there needs to be different deployments with similar configs, very few changes are needed.
Note that a name for each container is required.

```json
{
"fragments": [
{
"feed": "contoso.azurecr.io/example",
"includes": [
"containers",
"fragments"
],
"issuer": "did:x509:0:sha256:mLzv0uyBNQvC6hi4y9qy8hr6NSZuYFv6gfCwAEWBNqc::subject:CN:Contoso",
"minimum_svn": "1"
}
],
"containers": [
{
"name": "my-image",
"properties": {
"image": "mcr.microsoft.com/acc/samples/aci/helloworld:2.9",
"environmentVariables": [
{
"name": "PATH",
"value": "/customized/path/value"
},
{
"name": "TEST_REGEXP_ENV",
"value": "test_regexp_env(.*)",
"regex": true
}
],
"execProcesses": [
{
"command": [
"ls"
]
}
],
"volumeMounts": [
{
"name": "mymount",
"mountPath": "/mount/mymount",
"mountType": "emptyDir",
"readOnly": false
}
],
"command": [
"python3",
"main.py"
]
}
}
]
}
```

```bash
az confcom acipolicygen -i config.json
```

## dmverity Layer Hashing

To ensure the container that is being deployed is the intended container, the `confcom` tooling uses [dmverity hashing](https://www.kernel.org/doc/html/latest/admin-guide/device-mapper/verity.html). This is done by downloading the container locally with the Docker Daemon (or using a pre-downloaded tar file of the OCI image) and performing the dmverity hashing using the [dmverity-vhd tool](https://github.com/microsoft/hcsshim/tree/main/cmd/dmverity-vhd). These layer hashes are placed into the Rego security policy in the "layers" field of their respective container. Note that these dmverity layer hashes are different than the layer hashes reported by `docker image inspect`.
Expand Down Expand Up @@ -287,18 +350,32 @@ To generate a security policy using a policy config file for Virtual Node, the `
{
"name": "my-image",
"properties": {
"image": "mcr.microsoft.com/acc/samples/aci/helloworld:2.8"
"image": "mcr.microsoft.com/acc/samples/aci/helloworld:2.9"
}
}
]
}
```

This `scenario` field adds the necessary environment variables and mount values to containers in the config file.
This `scenario` field adds the necessary environment variables and mount values to containers in the config file. Currently `vn2` and `aci` are the only supported values for `scenario`, but others may be added in the future as more products onboard to the `confcom` extension. `aci` is the default value.

### Workload Identity

To use workload identities with VN2, the associated label [described here](https://learn.microsoft.com/en-us/azure/aks/workload-identity-overview?tabs=dotnet#pod-labels) must be present. Having this will add the requisite environment variables and mounts to each container's policy.
To generate a policy with workload identity capabilities for VN2 using the JSON format, the following `labels` key and nested values must be present:

```json
{
"version": "1.0",
"scenario": "vn2",
"labels": {
"azure.workload.identity/use": true
},
"containers": [
...
]
}
```

> [!NOTE]
> The `acipolicygen` command is specific to generating policies for ACI-based containers. For generating security policies for the [Confidential Containers on AKS](https://learn.microsoft.com/en-us/azure/aks/confidential-containers-overview) feature, use the `katapolicygen` command.
Expand Down Expand Up @@ -698,29 +775,29 @@ The config file is a JSON file that contains the following information:

```json
{
"containers": [
{
"name": "my-image",
"properties": {
"image": "mcr.microsoft.com/acc/samples/aci/helloworld:2.8",
"environmentVariables": [
{
"name": "PATH",
"value": "/customized/path/value"
},
{
"name": "TEST_REGEXP_ENV",
"value": "test_regexp_env(.*)",
"regex": true
}
],
"command": [
"python3",
"main.py"
"containers": [
{
"name": "my-image",
"properties": {
"image": "mcr.microsoft.com/acc/samples/aci/helloworld:2.9",
"environmentVariables": [
{
"name": "PATH",
"value": "/customized/path/value"
},
{
"name": "TEST_REGEXP_ENV",
"value": "test_regexp_env(.*)",
"regex": true
}
],
"command": [
"python3",
"main.py"
]
}
}
]
}
}
]
}
```

Expand Down Expand Up @@ -766,6 +843,29 @@ az confcom acifragmentgen --chain ./samples/certs/intermediateCA/certs/www.conto

This could be useful in scenarios where an image-attached fragment is required but the fragment's feed is different from the image's location.

Example 5: This format can also be used to generate fragments used for VN2. Adding the `scenario` key with the value `vn2` tells confcom which default values need to be added. Save this file as `fragment_config.json`:

```json
{
"version": "1.0",
"scenario": "vn2",
"containers": [
{
"name": "my-image",
"properties": {
"image": "mcr.microsoft.com/acc/samples/aci/helloworld:2.9"
}
}
]
}
```

Using the same command, the default mounts and environment variables used by VN2 will be added to the policy fragment.

```bash
az confcom acifragmentgen --input ./fragment_config.json --svn 1 --namespace contoso
```

## Microsoft Azure CLI 'confcom katapolicygen' Extension Examples

Run `az confcom katapolicygen --help` to see a list of supported arguments along with explanations. The following commands demonstrate the usage of different arguments to generate confidential computing security policies.
Expand Down Expand Up @@ -809,11 +909,11 @@ The `--print-policy` argument is included to display the policy on the command l
Example 2: This command injects a security policy into the pod spec based on input from a config map so that there is no need to change the pod spec to pass variables into the security policy:

```bash
az confcom katapolicygen -y .\\pod.yaml -c .\\config-map.yaml
az confcom katapolicygen -y ./pod.yaml -c ./config-map.yaml
```

Example 3: This command caches the layer hashes and stores them locally on your computer to make future computations faster if the same images are used:

```bash
az confcom katapolicygen -y .\\pod.yaml -u
az confcom katapolicygen -y ./pod.yaml -u
```
3 changes: 1 addition & 2 deletions src/confcom/azext_confcom/cose_proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,7 @@ def create_issuer(self, cert_path: str) -> str:
return item.stdout.decode("utf-8")

# generate an import statement from a signed policy fragment
def generate_import_from_path(self, fragment_path: str, minimum_svn: int) -> str:
# TODO: make sure the fragment is signed correctly
def generate_import_from_path(self, fragment_path: str, minimum_svn: str) -> str:
if not os.path.exists(fragment_path):
eprint(f"The fragment file at {fragment_path} does not exist")

Expand Down
6 changes: 3 additions & 3 deletions src/confcom/azext_confcom/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ def acipolicygen_confcom(
)
# error checking for making sure an input is provided is above
if input_path:
container_group_policies = security_policy.load_policy_from_file(
container_group_policies = security_policy.load_policy_from_json_file(
input_path,
debug_mode=debug_mode,
infrastructure_svn=infrastructure_svn,
Expand Down Expand Up @@ -228,7 +228,7 @@ def acifragmentgen_confcom(
feed: str,
key: str,
chain: str,
minimum_svn: int,
minimum_svn: str,
image_target: str = "",
algo: str = "ES384",
fragment_path: str = None,
Expand Down Expand Up @@ -292,7 +292,7 @@ def acifragmentgen_confcom(
# this is using --input
if not tar_mapping:
tar_mapping = os_util.load_tar_mapping_from_config_file(input_path)
policy = security_policy.load_policy_from_config_file(
policy = security_policy.load_policy_from_json_file(
input_path, debug_mode=debug_mode, disable_stdio=disable_stdio
)
# get all of the fragments that are being used in the policy
Expand Down
2 changes: 1 addition & 1 deletion src/confcom/azext_confcom/data/internal_config.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "1.2.4",
"version": "1.2.5",
"hcsshim_config": {
"maxVersion": "1.0.0",
"minVersion": "0.0.1"
Expand Down
2 changes: 1 addition & 1 deletion src/confcom/azext_confcom/oras_proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ def attach_fragment_to_image(image_name: str, filename: str):
print(f"Fragment attached to image '{image_name}' with Digest:{digest}")


def generate_imports_from_image_name(image_name: str, minimum_svn: int) -> List[dict]:
def generate_imports_from_image_name(image_name: str, minimum_svn: str) -> List[dict]:
cose_proxy = CoseSignToolProxy()
fragment_hashes = discover(image_name)
import_list = []
Expand Down
Loading
Loading