diff --git a/.vale.ini b/.vale.ini new file mode 100644 index 0000000000..e51fa3bce5 --- /dev/null +++ b/.vale.ini @@ -0,0 +1,16 @@ +StylesPath = docs/styles +Vocab = edgeless + +[*.md] +BasedOnStyles = Vale, Microsoft, Google + +# Disable rules +Vale.Terms = NO + +# decrease to suggestion +Microsoft.HeadingAcronyms = suggestion # doesn't consider well-known ones +Microsoft.GeneralURL = suggestion # ok for technical users + +# increase to warning +Microsoft.OxfordComma = warning +Microsoft.SentenceLength = warning diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3e4f17a05f..47c89c9d69 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -5,8 +5,8 @@ 1. [Install Nix](https://zero-to-nix.com/concepts/nix-installer) 2. (Optional) configure Nix to allow use of extra substituters, and profit from our - cachix remote cache. To allow using additional substituters from the flake.nix, - add yourself (or the wheel group) as trusted-user in your nix config. + cachix remote cache. To allow using additional substituters from the `flake.nix`, + add your user name (or the wheel group) as trusted-user in your nix config. On NixOS (in your config): @@ -30,10 +30,10 @@ nix develop .# ``` - Or activate [direnv](https://direnv.net/) to automatically enter the nix shell. - It is recommended to use [nix-direnv](https://github.com/nix-community/nix-direnv). - If your system ships outdated bash, [install direnv](https://direnv.net/docs/installation.html) via package manager. - Additionally, you may want to add the [vscode extension](https://github.com/direnv/direnv-vscode). + Or activate [`direnv`](https://direnv.net/) to automatically enter the nix shell. + It's recommended to use [`nix-direnv`](https://github.com/nix-community/nix-direnv). + If your system ships outdated bash, [install `direnv`](https://direnv.net/docs/installation.html) via package manager. + Additionally, you may want to add the [VSCode extension](https://github.com/direnv/direnv-vscode). ```sh direnv allow @@ -60,7 +60,7 @@ ### Deploy -The ususally dev flow is available as a single target to execute: +The usually developer flow is available as a single target to execute: ```sh just [default ] @@ -71,7 +71,7 @@ Ensure the pushed container images are accessible to your cluster. The manifest will the be generated (`contrast generate`). Further the flow will deploy the selected deployment and wait for components to come up. -The manifest will automatically be set (`contrast set`) and the Coordinator will will be verified +The manifest will automatically be set (`contrast set`) and the Coordinator will be verified (`contrast verify`). The flow will also wait for the workload to get ready. This target is idempotent and will delete an existing deployment before re-deploying. diff --git a/README.md b/README.md index f29df12507..1e686934c5 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Contrast currently targets the [CoCo preview on AKS](https://learn.microsoft.com ## Goal -Contrast is designed to keep all data always encrypted and to prevent access from the infrastructure layer, i.e., remove the infrastructure from the trusted computing base (TCB). This includes access from datacenter employees, privileged cloud admins, own cluster administrators, and attackers coming through the infrastructure, e.g., malicious co-tenants escalating their privileges. +Contrast is designed to keep all data always encrypted and to prevent access from the infrastructure layer. It removes the infrastructure provider from the trusted computing base (TCB). This includes access from datacenter employees, privileged cloud admins, own cluster administrators, and attackers coming through the infrastructure, for example, malicious co-tenants escalating their privileges. Contrast integrates fluently with the existing Kubernetes workflows. It's compatible with managed Kubernetes, can be installed as a day-2 operation and imposes only minimal changes to your deployment flow. @@ -71,20 +71,20 @@ A third party can use this to verify the integrity of your distributed app, maki ### The Manifest The manifest is the configuration file for the Coordinator, defining your confidential deployment. -It is automatically generated from your deployment by the Contrast CLI. +It's automatically generated from your deployment by the Contrast CLI. It currently consists of the following parts: * *Policies*: The identities of your Pods, represented by the hashes of their respective runtime policies. -* *Reference Values*: The remote attestation reference values for the Kata confidential micro-VM that is the runtime environment of your Pods. +* *Reference Values*: The remote attestation reference values for the Kata confidential micro-VM that's the runtime environment of your Pods. * *WorkloadOwnerKeyDigest*: The workload owner's public key digest. Used for authenticating subsequent manifest updates. ### Runtime Policies -Runtime Policies are a mechanism to enable the use of the (untrusted) Kubernetes API for orchestration while ensuring the confidentiality and integrity of your confidential containers. +Runtime Policies are a mechanism to enable the use of the untrusted Kubernetes API for orchestration while ensuring the confidentiality and integrity of your confidential containers. They allow us to enforce the integrity of your containers' runtime environment as defined in your deployment files. -The runtime policy mechanism is based on the Open Policy Agent (OPA) and translates the Kubernetes deployment YAMLs into OPA's Rego policy language. +The runtime policy mechanism is based on the Open Policy Agent (OPA) and translates the Kubernetes deployment YAML into the Rego policy language of OPA. The Kata Agent inside the confidential micro-VM then enforces the policy by only acting on permitted requests. -The Contrast CLI provides the tooling for automatically translating Kubernetes deployment YAMLs into OPA's Rego policy language. +The Contrast CLI provides the tooling for automatically translating Kubernetes deployment YAML into the Rego policy language of OPA. The trust chain goes as follows: @@ -97,7 +97,7 @@ The trust chain goes as follows: 7. The CLI sets a manifest in the Contrast Coordinator, including a list of permitted policies. 8. The Contrast Coordinator verifies that the started pod has a permitted policy hash in its `HOSTDATA` field. -After the last step, we know that the policy has not been tampered with and, thus, that the workload is as intended. +After the last step, we know that the policy hasn't been tampered with and, thus, that the workload is as intended. ### The Contrast Initializer @@ -196,7 +196,7 @@ helm template release-name chart-name > resources/all.yml To specify that a workload (pod, deployment, etc.) should be deployed as confidential containers, add `runtimeClassName: kata-cc-isolation` to the pod spec (pod definition or template). In addition, add the Contrast Initializer as `initContainers` to these workloads and configure the -workload to use the certificates written to the `tls-certs` volumeMount. +workload to use the certificates written to a `volumeMount` named `tls-certs`. ```yaml spec: # v1.PodSpec @@ -243,8 +243,8 @@ coordinator=$(kubectl get svc coordinator -o=jsonpath='{.status.loadBalancer.ing ``` > [!NOTE] -> `kubectl port-forward` uses a CRI method that is not supported by the Kata shim. If you -> cannot use a public load balancer, you can deploy a [deployments/simple/portforwarder.yml] and +> `kubectl port-forward` uses a CRI method that isn't supported by the Kata shim. If you +> can't use a public load balancer, you can deploy a [deployments/simple/portforwarder.yml] and > expose that with `kubectl port-forward` instead. > > Tracking issue: . @@ -284,7 +284,7 @@ lbip=$(kubectl get svc ${MY_SERVICE} -o=jsonpath='{.status.loadBalancer.ingress[ echo $lbip ``` -Note: All workload certificates are created with a wildcard DNS entry. Since we are accessing the load balancer via IP, the SAN checks the certificate for IP entries in the SAN field. Since the certificate doesn't contain any IP entries as SAN, the validation fails. +Note: All workload certificates are created with a wildcard DNS entry. Since we're accessing the load balancer via IP, the SAN checks the certificate for IP entries in the SAN field. Since the certificate doesn't contain any IP entries as SAN, the validation fails. Hence, with curl you need to skip the validation: ```sh @@ -308,7 +308,7 @@ As a result, there are currently certain limitations from which we try to docume - Persistent volumes currently not supported in CoCo - While workload policies are functional in general, but [not covering all edge cases](https://github.com/microsoft/kata-containers/releases/tag/genpolicy-0.6.2-5) - Port-forwarding isn't supported by Kata Containers yet -- CLI is only available for Linux (mostly because upstream dependencies are not available for other platforms) +- CLI is only available for Linux (mostly because upstream dependencies aren't available for other platforms) ## Upcoming Contrast features diff --git a/dev-docs/aks/nested-virt-internals.md b/dev-docs/aks/nested-virt-internals.md index 0aa30203b9..e6cdf32763 100644 --- a/dev-docs/aks/nested-virt-internals.md +++ b/dev-docs/aks/nested-virt-internals.md @@ -6,7 +6,7 @@ The instance types used are from the [DCas_cc_v5 and DCads_cc_v5-series](https:/ ## Using nested CVM-in-VM outside of AKS -The instance types and images can be used for regular VMs (and scalesets): +The instance types and images can be used for regular VMs (and scale sets): ```sh LOCATION=westeurope @@ -21,13 +21,13 @@ az vm create \ az ssh vm --resource-group "${RG}" --vm-name nested-virt-test ``` -The VM has access to hyperv as a paravisor via `/dev/mshv` (and *not* `/dev/kvm`, which would be expected for nested virt on Linux). The userspace component for spawning nested VMs on mshv is part of [rust-vmm](https://github.com/rust-vmm/mshv). -This feature is enabled by kernel patches which are not yet upstream. At the time of writing, the VM image uses a kernel with a uname of `5.15.126.mshv9-2.cm2` and this additional kernel cmdline parameter: `hyperv_resvd_new=0x1000!0x933000,0x17400000!0x104e00000,0x1000!0x1000,0x4e00000!0x100000000`. +The VM has access to hyperv as a paravisor via `/dev/mshv` (and *not* `/dev/kvm`, which would be expected for nested virtualization on Linux). The user space component for spawning nested VMs on `mshv` is part of [rust-vmm](https://github.com/rust-vmm/mshv). +This feature is enabled by kernel patches which aren't yet upstream. At the time of writing, the VM image uses a kernel with a `uname` of `5.15.126.mshv9-2.cm2` and this additional kernel cmdline parameter: `hyperv_resvd_new=0x1000!0x933000,0x17400000!0x104e00000,0x1000!0x1000,0x4e00000!0x100000000`. The Kernel is built from a CBL Mariner [spec file](https://github.com/microsoft/CBL-Mariner/blob/2.0/SPECS/kernel-mshv/kernel-mshv.spec) and the Kernel source is [publicly accessible](https://cblmarinerstorage.blob.core.windows.net/sources/core/kernel-mshv-5.15.126.mshv9.tar.gz). MicroVM guests use a newer Kernel ([spec](https://github.com/microsoft/CBL-Mariner/tree/2.0/SPECS/kernel-uvm-cvm)). -The image also ships parts of the confidential-containers tools, the kata-runtime, cloud-hypervisor and related tools (kata-runtime, cloud-hypervisor, [containerd](https://github.com/microsoft/confidential-containers-containerd)), some of which contain patches that are not yet upstream, as well as a custom guest image under `/opt`: +The image also ships parts of the confidential-containers tools, the kata-runtime, cloud-hypervisor and related tools (kata-runtime, cloud-hypervisor, [containerd](https://github.com/microsoft/confidential-containers-containerd)), some of which contain patches that aren't yet upstream, as well as a custom guest image under `/opt`:
$ find /opt/confidential-containers/ @@ -56,7 +56,7 @@ The image also ships parts of the confidential-containers tools, the kata-runtim ```
-With those components, it is possible to use the `containerd-shim-kata-cc-v2` runtime for containerd (or add it as a runtime class in k8s). +With those components, it's possible to use the `containerd-shim-kata-cc-v2` runtime for containerd (or add it as a runtime class in k8s).
/etc/containerd/config.toml @@ -116,7 +116,7 @@ oom_score = 0
-Runtime options extraced by crictl inspect CONTAINER_ID | jq .info (truncated) +Runtime options extracted by crictl inspect CONTAINER_ID | jq .info (truncated) ```json { @@ -131,7 +131,7 @@ oom_score = 0
With the containerd configuration from above, the following commands can be used to start the [tardev-snapshotter](https://github.com/kata-containers/tardev-snapshotter) and spawn a container using the `kata-cc` runtime class. -Please note that while this example almost works, it does not currently result in a working container outside of AKS. +Please note that while this example almost works, it doesn't currently result in a working container outside of AKS. This is probably due to a mismatch of exact arguments or configuration files. Maybe a policy annotation is required for booting. @@ -171,15 +171,15 @@ EOF ### Resource Management -There's [AKS documentation for resource managment] which explains the basics of how CPU and +There's [AKS documentation for resource management] which explains the basics of how CPU and memory are allocated for a Kata VM. -The default memory allocation is quite high at 2GiB, which fills up the node pretty quickly. -It's unclear why this deafult is chosen, given that the container limit is added on top of this +The default memory allocation is quite high at 2GiB, which fills up the node fast. +It's unclear why this default is chosen, given that the container limit's added on top of this value. Forcing a size with the pod annotation `io.katacontainers.config.hypervisor.default_memory` would be possible, but the annotation would -need to be allowlisted in the config setting `enable_annotations`. +need to be allow-listed in the config setting `enable_annotations`. -[AKS documentation for resource managment]: https://learn.microsoft.com/en-us/azure/aks/confidential-containers-overview#resource-allocation-overview +[AKS documentation for resource management]: https://learn.microsoft.com/en-us/azure/aks/confidential-containers-overview#resource-allocation-overview
Relevant config snippet diff --git a/dev-docs/aks/serial-console.md b/dev-docs/aks/serial-console.md index 4660b01594..e44234e7f2 100644 --- a/dev-docs/aks/serial-console.md +++ b/dev-docs/aks/serial-console.md @@ -1,7 +1,7 @@ # Obtain a serial console inside the podvm Get a shell on the AKS node. If in doubt, use [nsenter-node.sh](https://github.com/alexei-led/nsenter/blob/master/nsenter-node.sh). -Now run the following commands to use a debug [igvm](https://docs.google.com/presentation/d/1uWeyqtYV53Vtxd3ayYWWTLbxasYNr35a/) and enable debugging for the kata runtime. +Now run the following commands to use a debug [IGVM](https://docs.google.com/presentation/d/1uWeyqtYV53Vtxd3ayYWWTLbxasYNr35a/) and enable debugging for the Kata runtime. ```sh sed -i -e 's#^igvm = "\(.*\)"#igvm = "/opt/confidential-containers/share/kata-containers/kata-containers-igvm-debug.img"#g' /opt/confidential-containers/share/defaults/kata-containers/configuration-clh-snp.toml @@ -9,7 +9,7 @@ sed -i -e 's/^#enable_debug = true/enable_debug = true/g' /opt/confidential-cont systemctl restart containerd ``` -Now you need to reconnect to the host. Use the following commands to print the sandbox ids of kata VMs. +Now you need to reconnect to the host. Use the following commands to print the sandbox ids of Kata VMs. Please note that only the pause container of every pod has the `clh.sock`. Other containers are part of the same VM. ```shell-session @@ -17,22 +17,22 @@ $ ctr --namespace k8s.io container ls "runtime.name==io.containerd.kata-cc.v2" $ sandbox_id=ENTER_SANDBOX_ID_HERE ``` -And attach to the serial console using socat. You need to type `CONNECT 1026` to get a shell. +And attach to the serial console using `socat`. You need to type `CONNECT 1026` to get a shell. ```shell-session $ cd /var/run/vc/vm/${sandbox_id}/ && socat stdin unix-connect:clh.sock CONNECT 1026 ``` -Alternatively, you can use `kata-runtime exec`, which gives you proper tty behavior including tab completion. -First ensure the kata-monitor is running, then connect. +Alternatively, you can use `kata-runtime exec`, which gives you proper TTY behavior including tab completion. +First ensure the `kata-monitor` is running, then connect. ``` $ kata-monitor & $ kata-runtime exec ${sandbox_id} ``` -If you are done, use the following commands to go back to a release igvm. +If you are done, use the following commands to go back to a release IGVM. ```sh sed -i -e 's#^igvm = "\(.*\)"#igvm = "/opt/confidential-containers/share/kata-containers/kata-containers-igvm.img"#g' /opt/confidential-containers/share/defaults/kata-containers/configuration-clh-snp.toml diff --git a/dev-docs/coco/policy.md b/dev-docs/coco/policy.md index a9708bd176..9e4b91b1c5 100644 --- a/dev-docs/coco/policy.md +++ b/dev-docs/coco/policy.md @@ -12,41 +12,41 @@ The Kata Runtime actually consists of two parts: 1. The runtime implementation runs on the Kubernetes node. 2. The Kata Agent runs in the confidential guest. -The runtime and the agent communicate over [vsocks], exchanging [AgentService] messages. +The runtime and the agent communicate over [VSOCK], exchanging [AgentService] messages. [OCI Runtime]: https://github.com/opencontainers/runtime-spec [Containerd ShimV2 API]: https://pkg.go.dev/github.com/containerd/containerd@v1.7.13/api/runtime/task/v2#TaskService -[vsocks]: https://www.man7.org/linux/man-pages/man7/vsock.7.html +[VSOCK]: https://www.man7.org/linux/man-pages/man7/vsock.7.html [AgentService]: https://github.com/kata-containers/kata-containers/blob/89c76d7/src/libs/protocols/protos/agent.proto#L21-L76 ## Trust -In CoCo, the agent is part of the TEE but the runtime is not. -In order to trust the agent, we need to ensure that the agent only serves permitted requests. +In CoCo, the agent is part of the TEE but the runtime isn't. +To trust the agent, we need to ensure that the agent only serves permitted requests. For Contrast, the chain of trust looks like this: 1. The CLI generates a policy and attaches it to the pod definition. -2. Kubernetes schedules the pod on a node with kata-cc-isolation runtime. +2. Kubernetes schedules the pod on a node with `kata-cc-isolation` runtime. 3. Containerd takes the node, starts the Kata Shim and creates the pod sandbox. 4. The Kata runtime starts a CVM with the policy's digest as `HOSTDATA`. 5. The Kata runtime sets the policy using the `SetPolicy` method. 6. The Kata agent verifies that the incoming policy's digest matches `HOSTDATA`. 7. The CLI sets a manifest at the Contrast Coordinator, including a list of permitted policies. -8. The Contrast Coordinator verifies that the started pod has a permitted poilicy hash in its `HOSTDATA` field. +8. The Contrast Coordinator verifies that the started pod has a permitted policy hash in its `HOSTDATA` field. -After the last step, we know that the policy has not been tampered with and thus that the workload is as intended. +After the last step, we know that the policy hasn't been tampered with and thus that the workload is as intended. ## Policy Structure The policy is written in [Rego] and consists of *rules* and *data*. -The rules are somewhat static - in case of Contrast, they are baked into the CLI. +The rules are somewhat static - in case of Contrast, they're baked into the CLI. The upstream tool `genpolicy` supports an additional settings file to augment the rules with site-specific information. The data section is specific to the pod at hand and is generated from the deployment YAML. Next to this document, you can find a [pod definition](example-policy.yaml) and the corresponding [generated policy](example-policy.rego). -The policy was created with `nix run .#cli-release` at commit 6d25a1b4c82adeb4fff2771453bc38ca44cde466. +The policy was created with `nix run .#cli-release` at commit `6d25a1b4c82adeb4fff2771453bc38ca44cde466`. [Rego]: https://www.openpolicyagent.org/docs/latest/policy-language/ @@ -63,7 +63,7 @@ The rules can be divided into two major checks: *OCI spec* and *storage*. ### OCI Rules The OCI spec check is concerned with the content of the [OCI config] requested by the Kubelet. -This includes command line arguments, env vars and security configuration. +This includes command line arguments, environment variables and security configuration. [OCI config]: https://github.com/opencontainers/runtime-spec/blob/cb7ae92/specs-go/config.go#L6-L34 @@ -72,7 +72,7 @@ This includes command line arguments, env vars and security configuration. The storage check is concerned with the integrity of the various mount points for the container. Of particular interest is the container's root filesystem. The host's containerd snapshot plugin pulls the image layer tarballs. -These are published to the guest as block devices, which the guest then maps with dm-verity, mounts as tarfs and combines into an overlayfs. +These are published to the guest as block devices, which the guest then maps with dm-verity, mounts as tarFS and combines into an overlayFS. The expected verity hashes are part of the policy data, the actual hashes are injected into the request. TODO(burgerdev): discuss ConfigMaps, ephemeral mounts, etc. @@ -91,7 +91,7 @@ The request template data is appended to the rules file, and together they form The only practical way to debug policy decisions right now is to look at OPA logs inside the guest image. For that, you need to [enable serial console access](../aks/serial-console.md) and log into the guest VM. -Stepping through policy evaluation is not supported by OPA. +Stepping through policy evaluation isn't supported by OPA. The generated policies contain some print statements that give a rough impression of what's going on. An alternative strategy for testing policies is to launch a pod, collect the `CreateContainerRequest` observed by the agent and evaluate the policy locally. @@ -103,7 +103,7 @@ opa eval -i request.json -d policy.rego 'data.agent_policy.CreateContainerReque ## Problems with Generated Policy -Notice that the policy is generated from Kubernetes resource specs, but is applied to, say, `CreateContainerRequest` protos. +Notice that the policy is generated from Kubernetes resource specs, but is applied to, say, `CreateContainerRequest` protobuf resource. The following problem categories emerge from this design decision: * Policy evaluation on API requests can't prevent events from *not* happening. @@ -112,33 +112,33 @@ The following problem categories emerge from this design decision: ### Absence of Required Events -Today's policy evaluation cannot verify the order of containers, or even their presence. +Today's policy evaluation can't verify the order of containers, or even their presence. This is particularly damaging for init containers that maintain security invariants. Fixing this would require a stateful policy evaluation that takes previous requests into account. -However, verifying the presence of non-init containers is not feasible with this approach, but also less security critical. +However, verifying the presence of non-init containers isn't feasible with this approach, but also less security critical. Also affected by this are pod lifecycle hooks and probes. ### Ambiguity -The mapping from pod spec to OCI spec is not specified, and the exact outcome strongly depends on the CRI. +The mapping from pod spec to OCI spec isn't specified, and the exact outcome strongly depends on the CRI. For example, the CRI might set additional environment variables or mount points, or the Kubelet adds a `resolv.conf` mount. The pause container used by CRIs is also a good example of an unspecified addition that needs to manifest in policy. -On the other hand, the policy needs to be explicit about what is allowed into the TEE, because many of the underspecified things can pose security risk - think `LD_PRELOAD` or mounting over `/bin/sh`. -Thus, the genpolicy tool needs to reproduce inner logic of the Kubelet and the target CRI to allow exactly what they are going to add to the spec. +On the other hand, the policy needs to be explicit about what's allowed into the TEE, because many of the underspecified things can pose security risk - think `LD_PRELOAD` or mounting over `/bin/sh`. +Thus, the `genpolicy` tool needs to reproduce inner logic of the Kubelet and the target CRI to allow exactly what they're going to add to the spec. This is primarily an engineering issue that makes CoCo difficult to port, but it also makes generated policies more obscure. ### Sharp Edges -Some parts of the container environment cannot be checked by policy. +Some parts of the container environment can't be checked by policy. This puts the onus on the application to not trust these parts, deteriorating the lift-and-shift experience. Examples include: -* env vars with dynamic information (such as provided by `PodSpec.enableServiceLinks`) +* Environment variables with dynamic information (such as provided by `PodSpec.enableServiceLinks`) * DNS *configuration* (DNS *servers* can not be trusted anyway, which is a good reason to scrutinize DNS config) -* other little things like downward API, generated names +* Other little things like downward API, generated names ## Open Questions diff --git a/dev-docs/release.md b/dev-docs/release.md index e321700003..c66fa29c39 100644 --- a/dev-docs/release.md +++ b/dev-docs/release.md @@ -2,7 +2,7 @@ ## Minor -1. Ensure all needed PRs were were merged. +1. Ensure all needed PRs were merged. 2. Export the release you want to make: @@ -11,7 +11,7 @@ echo "Releasing $REL_VER" ``` -3. Create a new temporary branch for the relese: +3. Create a new temporary branch for the release: ```sh git switch -c "tmp/$REL_VER" @@ -26,7 +26,7 @@ 5. Review the release notes, test the binary artifact. -6. Review and merge the auto-generated update PR for main. +6. Review and merge the auto generated update PR for main. 7. Publish the GitHub release. @@ -57,7 +57,7 @@ git pull ``` -4. Create a new temporary branch for the relese: +4. Create a new temporary branch for the release: ```sh git switch -c "tmp/$REL_VER" diff --git a/dev-docs/user-manual.md b/dev-docs/user-manual.md index 653310ef79..9a14380f13 100644 --- a/dev-docs/user-manual.md +++ b/dev-docs/user-manual.md @@ -44,20 +44,20 @@ A third party can use this to verify the integrity of your distributed app, maki ### The Manifest The manifest is the configuration file for the Coordinator, defining your confidential deployment. -It is automatically generated from your deployment by the Contrast CLI. +It's automatically generated from your deployment by the Contrast CLI. It currently consists of the following parts: * *Policies*: The identities of your Pods, represented by the hashes of their respective runtime policies. -* *Reference Values*: The remote attestation reference values for the Kata confidential micro-VM that is the runtime environment of your Pods. +* *Reference Values*: The remote attestation reference values for the Kata confidential micro-VM that's the runtime environment of your Pods. * *WorkloadOwnerKeyDigest*: The workload owner's public key digest. Used for authenticating subsequent manifest updates. ### Runtime Policies Runtime Policies are a mechanism to enable the use of the (untrusted) Kubernetes API for orchestration while ensuring the confidentiality and integrity of your confidential containers. They allow us to enforce the integrity of your containers' runtime environment as defined in your deployment files. -The runtime policy mechanism is based on the Open Policy Agent (OPA) and translates the Kubernetes deployment YAMLs into OPA's Rego policy language. +The runtime policy mechanism is based on the Open Policy Agent (OPA) and translates the Kubernetes deployment YAML into Rego policy language of OPA. The Kata Agent inside the confidential micro-VM then enforces the policy by only acting on permitted requests. -The Contrast CLI provides the tooling for automatically translating Kubernetes deployment YAMLs into OPA's Rego policy language. +The Contrast CLI provides the tooling for automatically translating Kubernetes deployment YAML into Rego policy language of OPA. The trust chain goes as follows: @@ -70,7 +70,7 @@ The trust chain goes as follows: 7. The CLI sets a manifest in the Contrast Coordinator, including a list of permitted policies. 8. The Contrast Coordinator verifies that the started pod has a permitted policy hash in its `HOSTDATA` field. -After the last step, we know that the policy has not been tampered with and, thus, that the workload is as intended. +After the last step, we know that the policy hasn't been tampered with and, thus, that the workload is as intended. ### The Contrast Initializer @@ -86,7 +86,7 @@ As a result, there are currently certain limitations from which we try to docume - Persistent volumes currently not supported in CoCo - While workload policies are functional in general, but [not covering all edge cases](https://github.com/microsoft/kata-containers/releases/tag/genpolicy-0.6.2-5) - Port-forwarding isn't supported by Kata Containers yet -- CLI is only available for Linux (mostly because upstream dependencies are not available for other platforms) +- CLI is only available for Linux (mostly because upstream dependencies aren't available for other platforms) ## Upcoming Contrast features diff --git a/docs/docs/examples/emojivoto.md b/docs/docs/examples/emojivoto.md index d6151c0430..9670a49814 100644 --- a/docs/docs/examples/emojivoto.md +++ b/docs/docs/examples/emojivoto.md @@ -4,9 +4,10 @@ ![screenshot of the emojivoto UI](../../static/img/emoijvoto.png) This tutorial guides you through deploying [emojivoto](https://github.com/BuoyantIO/emojivoto) as a -confidential Contrast deployment. Emojivoto is an example app that allows users to vote for different emojis and view votes cast on a leaderboard. It has a microservice architecture consisting of a +confidential Contrast deployment. Emojivoto is an example app that allows users to vote for different +emojis and view votes cast on a leader board. It has a microservice architecture consisting of a web frontend (`web`), a gRPC backend for listing available emojis (`emoji`), and a backend for -the voting and leaderboard logic (`voting`). The `vote-bot` simulates user traffic by submitting +the voting and leader board logic (`voting`). The `vote-bot` simulates user traffic by submitting votes to the frontend. @@ -72,7 +73,7 @@ contrast set -c "${coordinator}:1313" deployment/ ``` The CLI will use the embedded reference values to attest the Coordinator deployment -during the TLS handshake. If the connection succeeds, we are ensured that the Coordinator +during the TLS handshake. If the connection succeeds, we're ensured that the Coordinator deployment hasn't been tampered with. ### Deploy emojivoto @@ -87,15 +88,15 @@ kubectl apply -f deployment/ :::note[Inter-deployment communication] The Contrast Coordinator issues mesh certificates after successfully validating workloads. -These certificates can be used for sercure inter-deployment communication. The Initializer +These certificates can be used for secure inter-deployment communication. The Initializer sends an attestation report to the Coordinator, retrieves certificates and a private key in return -and writes them to a volumeMount. The emojivoto version we are using is patched to only communicate +and writes them to a `volumeMount`. The emojivoto version we're using is patched to only communicate via mTLS (the original app talks plain HTTP). The different parts of the workload are configured -to use the credentials from the volumeMount when communicating with each other. +to use the credentials from the `volumeMount` when communicating with each other. ::: -## Voter's perspective: verifying the ballot +## Voter's perspective: Verifying the ballot As voters, we want to verify the fairness and confidentiality of the deployment before deciding to vote. Regardless of the scale of our distributed deployment, Contrast only @@ -142,7 +143,7 @@ echo $lbip :::info -By default, certificates are issued with a wildcard DNS entry. Since we are accessing the load balancer via IP, the SAN checks the certificate for IP entries in the SAN field. Since the certificate doesn't contain any IP entries as SAN, the validation fails. +By default, certificates are issued with a wildcard DNS entry. Since we're accessing the load balancer via IP, the SAN checks the certificate for IP entries in the SAN field. Since the certificate doesn't contain any IP entries as SAN, the validation fails. Hence, certificate validation will fail with using curl: ```sh diff --git a/docs/docs/intro.md b/docs/docs/intro.md index ff88b89458..d7c376efe1 100644 --- a/docs/docs/intro.md +++ b/docs/docs/intro.md @@ -15,7 +15,7 @@ Contrast currently targets the [CoCo preview on AKS](https://learn.microsoft.com ## Goal -Contrast is designed to keep all data always encrypted and to prevent access from the infrastructure layer, i.e., remove the infrastructure from the trusted computing base (TCB). This includes access from datacenter employees, privileged cloud admins, own cluster administrators, and attackers coming through the infrastructure, e.g., malicious co-tenants escalating their privileges. +Contrast is designed to keep all data always encrypted and to prevent access from the infrastructure layer. It removes the infrastructure provider from the trusted computing base (TCB). This includes access from datacenter employees, privileged cloud admins, own cluster administrators, and attackers coming through the infrastructure, for example, malicious co-tenants escalating their privileges. Contrast integrates fluently with the existing Kubernetes workflows. It's compatible with managed Kubernetes, can be installed as a day-2 operation and imposes only minimal changes to your deployment flow. diff --git a/docs/styles/Google/Periods.yml b/docs/styles/Google/Periods.yml new file mode 100644 index 0000000000..d24a6a6c03 --- /dev/null +++ b/docs/styles/Google/Periods.yml @@ -0,0 +1,7 @@ +extends: existence +message: "Don't use periods with acronyms or initialisms such as '%s'." +link: 'https://developers.google.com/style/abbreviations' +level: error +nonword: true +tokens: + - '\b(?:[A-Z]\.){3,}' diff --git a/docs/styles/Google/Slang.yml b/docs/styles/Google/Slang.yml new file mode 100644 index 0000000000..63f4c248a8 --- /dev/null +++ b/docs/styles/Google/Slang.yml @@ -0,0 +1,11 @@ +extends: existence +message: "Don't use internet slang abbreviations such as '%s'." +link: 'https://developers.google.com/style/abbreviations' +ignorecase: true +level: error +tokens: + - 'tl;dr' + - ymmv + - rtfm + - imo + - fwiw diff --git a/docs/styles/Google/Spelling.yml b/docs/styles/Google/Spelling.yml new file mode 100644 index 0000000000..527ac07d31 --- /dev/null +++ b/docs/styles/Google/Spelling.yml @@ -0,0 +1,10 @@ +extends: existence +message: "In general, use American spelling instead of '%s'." +link: 'https://developers.google.com/style/spelling' +ignorecase: true +level: warning +tokens: + - '(?:\w+)nised?' + - 'colour' + - 'labour' + - 'centre' diff --git a/docs/styles/Google/Units.yml b/docs/styles/Google/Units.yml new file mode 100644 index 0000000000..53522ab2de --- /dev/null +++ b/docs/styles/Google/Units.yml @@ -0,0 +1,8 @@ +extends: existence +message: "Put a nonbreaking space between the number and the unit in '%s'." +link: "https://developers.google.com/style/units-of-measure" +nonword: true +level: error +tokens: + - \b\d+(?:B|kB|MB|GB|TB) + - \b\d+(?:ns|ms|s|min|h|d) diff --git a/docs/styles/Microsoft/AMPM.yml b/docs/styles/Microsoft/AMPM.yml new file mode 100644 index 0000000000..8b9fed162a --- /dev/null +++ b/docs/styles/Microsoft/AMPM.yml @@ -0,0 +1,9 @@ +extends: existence +message: Use 'AM' or 'PM' (preceded by a space). +link: https://docs.microsoft.com/en-us/style-guide/a-z-word-list-term-collections/term-collections/date-time-terms +level: error +nonword: true +tokens: + - '\d{1,2}[AP]M' + - '\d{1,2} ?[ap]m' + - '\d{1,2} ?[aApP]\.[mM]\.' diff --git a/docs/styles/Microsoft/Accessibility.yml b/docs/styles/Microsoft/Accessibility.yml new file mode 100644 index 0000000000..05bf927390 --- /dev/null +++ b/docs/styles/Microsoft/Accessibility.yml @@ -0,0 +1,25 @@ +extends: existence +message: "Don't use language (such as '%s') that defines people by their disability." +link: https://docs.microsoft.com/en-us/style-guide/a-z-word-list-term-collections/term-collections/accessibility-terms +level: suggestion +ignorecase: true +tokens: + - a victim of + - able-bodied + - affected by + - an epileptic + - crippled + - disabled + - dumb + - handicapped + - handicaps + - healthy + - lame + - maimed + - missing a limb + - mute + - normal + - sight-impaired + - stricken with + - suffers from + - vision-impaired diff --git a/docs/styles/Microsoft/Acronyms.yml b/docs/styles/Microsoft/Acronyms.yml new file mode 100644 index 0000000000..308ff7c0ed --- /dev/null +++ b/docs/styles/Microsoft/Acronyms.yml @@ -0,0 +1,64 @@ +extends: conditional +message: "'%s' has no definition." +link: https://docs.microsoft.com/en-us/style-guide/acronyms +level: suggestion +ignorecase: false +# Ensures that the existence of 'first' implies the existence of 'second'. +first: '\b([A-Z]{3,5})\b' +second: '(?:\b[A-Z][a-z]+ )+\(([A-Z]{3,5})\)' +# ... with the exception of these: +exceptions: + - API + - ASP + - CLI + - CPU + - CSS + - CSV + - DEBUG + - DOM + - DPI + - FAQ + - GCC + - GDB + - GET + - GPU + - GTK + - GUI + - HTML + - HTTP + - HTTPS + - IDE + - JAR + - JSON + - JSX + - LESS + - LLDB + - NET + - NOTE + - NVDA + - OSS + - PATH + - PDF + - PHP + - POST + - RAM + - REPL + - RSA + - SCM + - SCSS + - SDK + - SQL + - SSH + - SSL + - SVG + - TBD + - TCP + - TODO + - URI + - URL + - USB + - UTF + - XML + - XSS + - YAML + - ZIP diff --git a/docs/styles/Microsoft/Adverbs.yml b/docs/styles/Microsoft/Adverbs.yml new file mode 100644 index 0000000000..07d98d83e3 --- /dev/null +++ b/docs/styles/Microsoft/Adverbs.yml @@ -0,0 +1,270 @@ +extends: existence +message: "Consider removing '%s'." +link: https://docs.microsoft.com/en-us/style-guide/word-choice/use-simple-words-concise-sentences +ignorecase: true +level: warning +action: + name: remove +tokens: + - abnormally + - absentmindedly + - accidentally + - adventurously + - anxiously + - arrogantly + - awkwardly + - bashfully + - beautifully + - bitterly + - bleakly + - blindly + - blissfully + - boastfully + - boldly + - bravely + - briefly + - brightly + - briskly + - broadly + - busily + - calmly + - carefully + - carelessly + - cautiously + - cheerfully + - cleverly + - closely + - coaxingly + - colorfully + - continually + - coolly + - courageously + - crossly + - cruelly + - curiously + - daintily + - dearly + - deceivingly + - deeply + - defiantly + - deliberately + - delightfully + - diligently + - dimly + - doubtfully + - dreamily + - easily + - elegantly + - energetically + - enormously + - enthusiastically + - excitedly + - extremely + - fairly + - faithfully + - famously + - ferociously + - fervently + - fiercely + - fondly + - foolishly + - fortunately + - frankly + - frantically + - freely + - frenetically + - frightfully + - furiously + - generally + - generously + - gently + - gladly + - gleefully + - gracefully + - gratefully + - greatly + - greedily + - happily + - hastily + - healthily + - heavily + - helplessly + - honestly + - hopelessly + - hungrily + - innocently + - inquisitively + - intensely + - intently + - interestingly + - inwardly + - irritably + - jaggedly + - jealously + - jovially + - joyfully + - joyously + - jubilantly + - judgmentally + - justly + - keenly + - kiddingly + - kindheartedly + - knavishly + - knowingly + - knowledgeably + - lazily + - lightly + - limply + - lively + - loftily + - longingly + - loosely + - loudly + - lovingly + - loyally + - madly + - majestically + - meaningfully + - mechanically + - merrily + - miserably + - mockingly + - mortally + - mysteriously + - naturally + - nearly + - neatly + - nervously + - nicely + - noisily + - obediently + - obnoxiously + - oddly + - offensively + - optimistically + - overconfidently + - painfully + - partially + - patiently + - perfectly + - playfully + - politely + - poorly + - positively + - potentially + - powerfully + - promptly + - properly + - punctually + - quaintly + - queasily + - queerly + - questionably + - quickly + - quietly + - quirkily + - quizzically + - randomly + - rapidly + - rarely + - readily + - really + - reassuringly + - recklessly + - regularly + - reluctantly + - repeatedly + - reproachfully + - restfully + - righteously + - rightfully + - rigidly + - roughly + - rudely + - safely + - scarcely + - scarily + - searchingly + - sedately + - seemingly + - selfishly + - separately + - seriously + - shakily + - sharply + - sheepishly + - shrilly + - shyly + - silently + - sleepily + - slowly + - smoothly + - softly + - solemnly + - solidly + - speedily + - stealthily + - sternly + - strictly + - suddenly + - supposedly + - surprisingly + - suspiciously + - sweetly + - swiftly + - sympathetically + - tenderly + - tensely + - terribly + - thankfully + - thoroughly + - thoughtfully + - tightly + - tremendously + - triumphantly + - truthfully + - ultimately + - unabashedly + - unaccountably + - unbearably + - unethically + - unexpectedly + - unfortunately + - unimpressively + - unnaturally + - unnecessarily + - urgently + - usefully + - uselessly + - utterly + - vacantly + - vaguely + - vainly + - valiantly + - vastly + - verbally + - very + - viciously + - victoriously + - violently + - vivaciously + - voluntarily + - warmly + - weakly + - wearily + - wetly + - wholly + - wildly + - willfully + - wisely + - woefully + - wonderfully + - worriedly + - yawningly + - yearningly + - yieldingly + - youthfully + - zealously + - zestfully + - zestily diff --git a/docs/styles/Microsoft/Auto.yml b/docs/styles/Microsoft/Auto.yml new file mode 100644 index 0000000000..4da4393530 --- /dev/null +++ b/docs/styles/Microsoft/Auto.yml @@ -0,0 +1,11 @@ +extends: existence +message: "In general, don't hyphenate '%s'." +link: https://docs.microsoft.com/en-us/style-guide/a-z-word-list-term-collections/a/auto +ignorecase: true +level: error +action: + name: convert + params: + - simple +tokens: + - 'auto-\w+' diff --git a/docs/styles/Microsoft/Avoid.yml b/docs/styles/Microsoft/Avoid.yml new file mode 100644 index 0000000000..dab7822c79 --- /dev/null +++ b/docs/styles/Microsoft/Avoid.yml @@ -0,0 +1,14 @@ +extends: existence +message: "Don't use '%s'. See the A-Z word list for details." +# See the A-Z word list +link: https://docs.microsoft.com/en-us/style-guide +ignorecase: true +level: error +tokens: + - abortion + - and so on + - app(?:lication)?s? (?:developer|program) + - app(?:lication)? file + - backbone + - backend + - contiguous selection diff --git a/docs/styles/Microsoft/ComplexWords.yml b/docs/styles/Microsoft/ComplexWords.yml new file mode 100644 index 0000000000..65b7a34721 --- /dev/null +++ b/docs/styles/Microsoft/ComplexWords.yml @@ -0,0 +1,120 @@ +extends: substitution +message: "Consider using '%s' instead of '%s'." +link: https://docs.microsoft.com/en-us/style-guide/word-choice/use-simple-words-concise-sentences +ignorecase: true +level: suggestion +action: + name: replace +swap: + "approximate(?:ly)?": about + abundance: plenty + accelerate: speed up + accentuate: stress + accompany: go with + accomplish: carry out|do + accorded: given + accordingly: so + accrue: add + accurate: right|exact + acquiesce: agree + acquire: get|buy + additional: more|extra + address: discuss + addressees: you + adjacent to: next to + adjustment: change + admissible: allowed + advantageous: helpful + advise: tell + aggregate: total + aircraft: plane + alleviate: ease + allocate: assign|divide + alternatively: or + alternatives: choices|options + ameliorate: improve + amend: change + anticipate: expect + apparent: clear|plain + ascertain: discover|find out + assistance: help + attain: meet + attempt: try + authorize: allow + belated: late + bestow: give + cease: stop|end + collaborate: work together + commence: begin + compensate: pay + component: part + comprise: form|include + concept: idea + concerning: about + confer: give|award + consequently: so + consolidate: merge + constitutes: forms + contains: has + convene: meet + demonstrate: show|prove + depart: leave + designate: choose + desire: want|wish + determine: decide|find + detrimental: bad|harmful + disclose: share|tell + discontinue: stop + disseminate: send|give + eliminate: end + elucidate: explain + employ: use + enclosed: inside|included + encounter: meet + endeavor: try + enumerate: count + equitable: fair + equivalent: equal + exclusively: only + expedite: hurry + facilitate: ease + females: women + finalize: complete|finish + frequently: often + identical: same + incorrect: wrong + indication: sign + initiate: start|begin + itemized: listed + jeopardize: risk + liaise: work with|partner with + maintain: keep|support + methodology: method + modify: change + monitor: check|watch + multiple: many + necessitate: cause + notify: tell + numerous: many + objective: aim|goal + obligate: bind|compel + optimum: best|most + permit: let + portion: part + possess: own + previous: earlier + previously: before + prioritize: rank + procure: buy + provide: give|offer + purchase: buy + relocate: move + solicit: request + state-of-the-art: latest + subsequent: later|next + substantial: large + sufficient: enough + terminate: end + transmit: send + utilization: use + utilize: use diff --git a/docs/styles/Microsoft/Contractions.yml b/docs/styles/Microsoft/Contractions.yml new file mode 100644 index 0000000000..bc53216958 --- /dev/null +++ b/docs/styles/Microsoft/Contractions.yml @@ -0,0 +1,38 @@ +extends: substitution +message: "Use '%s' instead of '%s'." +link: https://docs.microsoft.com/en-us/style-guide/word-choice/use-contractions +level: error +ignorecase: true +action: + name: replace +swap: + are not: aren't + cannot: can't + could not: couldn't + did not: didn't + do not: don't + does not: doesn't + has not: hasn't + have not: haven't + how is: how's + is not: isn't + 'it is(?!\.)': it's + 'it''s(?=\.)': it is + should not: shouldn't + "that is(?![.,])": that's + 'that''s(?=\.)': that is + 'they are(?!\.)': they're + 'they''re(?=\.)': they are + was not: wasn't + 'we are(?!\.)': we're + 'we''re(?=\.)': we are + 'we have(?!\.)': we've + 'we''ve(?=\.)': we have + were not: weren't + 'what is(?!\.)': what's + 'what''s(?=\.)': what is + 'when is(?!\.)': when's + 'when''s(?=\.)': when is + 'where is(?!\.)': where's + 'where''s(?=\.)': where is + will not: won't diff --git a/docs/styles/Microsoft/Dashes.yml b/docs/styles/Microsoft/Dashes.yml new file mode 100644 index 0000000000..2894cf7229 --- /dev/null +++ b/docs/styles/Microsoft/Dashes.yml @@ -0,0 +1,13 @@ +extends: existence +message: "Remove the spaces around '%s'." +link: https://docs.microsoft.com/en-us/style-guide/punctuation/dashes-hyphens/emes +ignorecase: true +nonword: true +level: error +action: + name: edit + params: + - remove + - ' ' +tokens: + - '[—–]\s|\s[—–]' diff --git a/docs/styles/Microsoft/DateFormat.yml b/docs/styles/Microsoft/DateFormat.yml new file mode 100644 index 0000000000..196531394a --- /dev/null +++ b/docs/styles/Microsoft/DateFormat.yml @@ -0,0 +1,8 @@ +extends: existence +message: Use 'July 31, 2016' format, not '%s'. +link: https://docs.microsoft.com/en-us/style-guide/a-z-word-list-term-collections/term-collections/date-time-terms +ignorecase: true +level: error +nonword: true +tokens: + - '\d{1,2} (?:Jan(?:uary)?|Feb(?:ruary)?|Mar(?:ch)?|Apr(?:il)|May|Jun(?:e)|Jul(?:y)|Aug(?:ust)|Sep(?:tember)?|Oct(?:ober)|Nov(?:ember)?|Dec(?:ember)?) \d{4}' diff --git a/docs/styles/Microsoft/DateNumbers.yml b/docs/styles/Microsoft/DateNumbers.yml new file mode 100644 index 0000000000..14d46747ca --- /dev/null +++ b/docs/styles/Microsoft/DateNumbers.yml @@ -0,0 +1,40 @@ +extends: existence +message: "Don't use ordinal numbers for dates." +link: https://docs.microsoft.com/en-us/style-guide/numbers#numbers-in-dates +level: error +nonword: true +ignorecase: true +raw: + - \b(?:Jan(?:uary)?|Feb(?:ruary)?|Mar(?:ch)?|Apr(?:il)|May|Jun(?:e)|Jul(?:y)|Aug(?:ust)|Sep(?:tember)?|Oct(?:ober)|Nov(?:ember)?|Dec(?:ember)?)\b\s* +tokens: + - first + - second + - third + - fourth + - fifth + - sixth + - seventh + - eighth + - ninth + - tenth + - eleventh + - twelfth + - thirteenth + - fourteenth + - fifteenth + - sixteenth + - seventeenth + - eighteenth + - nineteenth + - twentieth + - twenty-first + - twenty-second + - twenty-third + - twenty-fourth + - twenty-fifth + - twenty-sixth + - twenty-seventh + - twenty-eighth + - twenty-ninth + - thirtieth + - thirty-first diff --git a/docs/styles/Microsoft/DateOrder.yml b/docs/styles/Microsoft/DateOrder.yml new file mode 100644 index 0000000000..12d69ba51e --- /dev/null +++ b/docs/styles/Microsoft/DateOrder.yml @@ -0,0 +1,8 @@ +extends: existence +message: "Always spell out the name of the month." +link: https://docs.microsoft.com/en-us/style-guide/numbers#numbers-in-dates +ignorecase: true +level: error +nonword: true +tokens: + - '\b\d{1,2}/\d{1,2}/(?:\d{4}|\d{2})\b' diff --git a/docs/styles/Microsoft/Ellipses.yml b/docs/styles/Microsoft/Ellipses.yml new file mode 100644 index 0000000000..320457a8bc --- /dev/null +++ b/docs/styles/Microsoft/Ellipses.yml @@ -0,0 +1,9 @@ +extends: existence +message: "In general, don't use an ellipsis." +link: https://docs.microsoft.com/en-us/style-guide/punctuation/ellipses +nonword: true +level: warning +action: + name: remove +tokens: + - '\.\.\.' diff --git a/docs/styles/Microsoft/FirstPerson.yml b/docs/styles/Microsoft/FirstPerson.yml new file mode 100644 index 0000000000..77761af883 --- /dev/null +++ b/docs/styles/Microsoft/FirstPerson.yml @@ -0,0 +1,16 @@ +extends: existence +message: "Use first person (such as '%s') sparingly." +link: https://docs.microsoft.com/en-us/style-guide/grammar/person +ignorecase: true +level: warning +nonword: true +tokens: + - (?:^|\s)I\s + - (?:^|\s)I,\s + - \bI'd\b + - \bI'll\b + - \bI'm\b + - \bI've\b + - \bme\b + - \bmy\b + - \bmine\b diff --git a/docs/styles/Microsoft/Foreign.yml b/docs/styles/Microsoft/Foreign.yml new file mode 100644 index 0000000000..0d3d6002a9 --- /dev/null +++ b/docs/styles/Microsoft/Foreign.yml @@ -0,0 +1,13 @@ +extends: substitution +message: "Use '%s' instead of '%s'." +link: https://docs.microsoft.com/en-us/style-guide/word-choice/use-us-spelling-avoid-non-english-words +ignorecase: true +level: error +nonword: true +action: + name: replace +swap: + '\b(?:eg|e\.g\.)[\s,]': for example + '\b(?:ie|i\.e\.)[\s,]': that is + '\b(?:viz\.)[\s,]': namely + '\b(?:ergo)[\s,]': therefore diff --git a/docs/styles/Microsoft/Gender.yml b/docs/styles/Microsoft/Gender.yml new file mode 100644 index 0000000000..47c0802479 --- /dev/null +++ b/docs/styles/Microsoft/Gender.yml @@ -0,0 +1,8 @@ +extends: existence +message: "Don't use '%s'." +link: https://github.com/MicrosoftDocs/microsoft-style-guide/blob/master/styleguide/grammar/nouns-pronouns.md#pronouns-and-gender +level: error +ignorecase: true +tokens: + - he/she + - s/he diff --git a/docs/styles/Microsoft/GenderBias.yml b/docs/styles/Microsoft/GenderBias.yml new file mode 100644 index 0000000000..0bdeb57843 --- /dev/null +++ b/docs/styles/Microsoft/GenderBias.yml @@ -0,0 +1,44 @@ +extends: substitution +message: "Consider using '%s' instead of '%s'." +ignorecase: true +level: error +swap: + (?:alumna|alumnus): graduate + (?:alumnae|alumni): graduates + air(?:m[ae]n|wom[ae]n): pilot(s) + anchor(?:m[ae]n|wom[ae]n): anchor(s) + authoress: author + camera(?:m[ae]n|wom[ae]n): camera operator(s) + chair(?:m[ae]n|wom[ae]n): chair(s) + congress(?:m[ae]n|wom[ae]n): member(s) of congress + door(?:m[ae]|wom[ae]n): concierge(s) + draft(?:m[ae]n|wom[ae]n): drafter(s) + fire(?:m[ae]n|wom[ae]n): firefighter(s) + fisher(?:m[ae]n|wom[ae]n): fisher(s) + fresh(?:m[ae]n|wom[ae]n): first-year student(s) + garbage(?:m[ae]n|wom[ae]n): waste collector(s) + lady lawyer: lawyer + ladylike: courteous + landlord: building manager + mail(?:m[ae]n|wom[ae]n): mail carriers + man and wife: husband and wife + man enough: strong enough + mankind: human kind + manmade: manufactured + manpower: personnel + men and girls: men and women + middle(?:m[ae]n|wom[ae]n): intermediary + news(?:m[ae]n|wom[ae]n): journalist(s) + ombuds(?:man|woman): ombuds + oneupmanship: upstaging + poetess: poet + police(?:m[ae]n|wom[ae]n): police officer(s) + repair(?:m[ae]n|wom[ae]n): technician(s) + sales(?:m[ae]n|wom[ae]n): salesperson or sales people + service(?:m[ae]n|wom[ae]n): soldier(s) + steward(?:ess)?: flight attendant + tribes(?:m[ae]n|wom[ae]n): tribe member(s) + waitress: waiter + woman doctor: doctor + woman scientist[s]?: scientist(s) + work(?:m[ae]n|wom[ae]n): worker(s) diff --git a/docs/styles/Microsoft/GeneralURL.yml b/docs/styles/Microsoft/GeneralURL.yml new file mode 100644 index 0000000000..dcef503d99 --- /dev/null +++ b/docs/styles/Microsoft/GeneralURL.yml @@ -0,0 +1,11 @@ +extends: existence +message: "For a general audience, use 'address' rather than 'URL'." +link: https://docs.microsoft.com/en-us/style-guide/urls-web-addresses +level: warning +action: + name: replace + params: + - URL + - address +tokens: + - URL diff --git a/docs/styles/Microsoft/HeadingAcronyms.yml b/docs/styles/Microsoft/HeadingAcronyms.yml new file mode 100644 index 0000000000..9dc3b6c2de --- /dev/null +++ b/docs/styles/Microsoft/HeadingAcronyms.yml @@ -0,0 +1,7 @@ +extends: existence +message: "Avoid using acronyms in a title or heading." +link: https://docs.microsoft.com/en-us/style-guide/acronyms#be-careful-with-acronyms-in-titles-and-headings +level: warning +scope: heading +tokens: + - '[A-Z]{2,4}' diff --git a/docs/styles/Microsoft/HeadingColons.yml b/docs/styles/Microsoft/HeadingColons.yml new file mode 100644 index 0000000000..7013c39148 --- /dev/null +++ b/docs/styles/Microsoft/HeadingColons.yml @@ -0,0 +1,8 @@ +extends: existence +message: "Capitalize '%s'." +link: https://docs.microsoft.com/en-us/style-guide/punctuation/colons +nonword: true +level: error +scope: heading +tokens: + - ':\s[a-z]' diff --git a/docs/styles/Microsoft/HeadingPunctuation.yml b/docs/styles/Microsoft/HeadingPunctuation.yml new file mode 100644 index 0000000000..af04b02ebf --- /dev/null +++ b/docs/styles/Microsoft/HeadingPunctuation.yml @@ -0,0 +1,13 @@ +extends: existence +message: "Don't use end punctuation in headings." +link: https://docs.microsoft.com/en-us/style-guide/punctuation/periods +nonword: true +level: warning +scope: heading +action: + name: edit + params: + - remove + - '.?!' +tokens: + - '[a-z][.?!](?:\s|$)' diff --git a/docs/styles/Microsoft/Headings.yml b/docs/styles/Microsoft/Headings.yml new file mode 100644 index 0000000000..63624edc1b --- /dev/null +++ b/docs/styles/Microsoft/Headings.yml @@ -0,0 +1,28 @@ +extends: capitalization +message: "'%s' should use sentence-style capitalization." +link: https://docs.microsoft.com/en-us/style-guide/capitalization +level: suggestion +scope: heading +match: $sentence +indicators: + - ':' +exceptions: + - Azure + - CLI + - Code + - Cosmos + - Docker + - Emmet + - I + - Kubernetes + - Linux + - macOS + - Marketplace + - MongoDB + - REPL + - Studio + - TypeScript + - URLs + - Visual + - VS + - Windows diff --git a/docs/styles/Microsoft/Hyphens.yml b/docs/styles/Microsoft/Hyphens.yml new file mode 100644 index 0000000000..90bbb5def9 --- /dev/null +++ b/docs/styles/Microsoft/Hyphens.yml @@ -0,0 +1,14 @@ +extends: existence +message: "'%s' doesn't need a hyphen." +link: https://docs.microsoft.com/en-us/style-guide/punctuation/dashes-hyphens/hyphens +level: warning +ignorecase: false +nonword: true +action: + name: edit + params: + - replace + - '-' + - ' ' +tokens: + - '\s[^\s-]+ly-' diff --git a/docs/styles/Microsoft/Negative.yml b/docs/styles/Microsoft/Negative.yml new file mode 100644 index 0000000000..d6ff2f2243 --- /dev/null +++ b/docs/styles/Microsoft/Negative.yml @@ -0,0 +1,13 @@ +extends: existence +message: "Form a negative number with an en dash, not a hyphen." +link: https://docs.microsoft.com/en-us/style-guide/numbers +nonword: true +level: error +action: + name: edit + params: + - replace + - '-' + - '–' +tokens: + - '\s-\d+\s' diff --git a/docs/styles/Microsoft/Ordinal.yml b/docs/styles/Microsoft/Ordinal.yml new file mode 100644 index 0000000000..e3483e380c --- /dev/null +++ b/docs/styles/Microsoft/Ordinal.yml @@ -0,0 +1,13 @@ +extends: existence +message: "Don't add -ly to an ordinal number." +link: https://docs.microsoft.com/en-us/style-guide/numbers +level: error +action: + name: edit + params: + - trim + - ly +tokens: + - firstly + - secondly + - thirdly diff --git a/docs/styles/Microsoft/OxfordComma.yml b/docs/styles/Microsoft/OxfordComma.yml new file mode 100644 index 0000000000..493b55c3ce --- /dev/null +++ b/docs/styles/Microsoft/OxfordComma.yml @@ -0,0 +1,8 @@ +extends: existence +message: "Use the Oxford comma in '%s'." +link: https://docs.microsoft.com/en-us/style-guide/punctuation/commas +scope: sentence +level: suggestion +nonword: true +tokens: + - '(?:[^\s,]+,){1,} \w+ (?:and|or) \w+[.?!]' diff --git a/docs/styles/Microsoft/Passive.yml b/docs/styles/Microsoft/Passive.yml new file mode 100644 index 0000000000..102d377cac --- /dev/null +++ b/docs/styles/Microsoft/Passive.yml @@ -0,0 +1,183 @@ +extends: existence +message: "'%s' looks like passive voice." +ignorecase: true +level: suggestion +raw: + - \b(am|are|were|being|is|been|was|be)\b\s* +tokens: + - '[\w]+ed' + - awoken + - beat + - become + - been + - begun + - bent + - beset + - bet + - bid + - bidden + - bitten + - bled + - blown + - born + - bought + - bound + - bred + - broadcast + - broken + - brought + - built + - burnt + - burst + - cast + - caught + - chosen + - clung + - come + - cost + - crept + - cut + - dealt + - dived + - done + - drawn + - dreamt + - driven + - drunk + - dug + - eaten + - fallen + - fed + - felt + - fit + - fled + - flown + - flung + - forbidden + - foregone + - forgiven + - forgotten + - forsaken + - fought + - found + - frozen + - given + - gone + - gotten + - ground + - grown + - heard + - held + - hidden + - hit + - hung + - hurt + - kept + - knelt + - knit + - known + - laid + - lain + - leapt + - learnt + - led + - left + - lent + - let + - lighted + - lost + - made + - meant + - met + - misspelt + - mistaken + - mown + - overcome + - overdone + - overtaken + - overthrown + - paid + - pled + - proven + - put + - quit + - read + - rid + - ridden + - risen + - run + - rung + - said + - sat + - sawn + - seen + - sent + - set + - sewn + - shaken + - shaven + - shed + - shod + - shone + - shorn + - shot + - shown + - shrunk + - shut + - slain + - slept + - slid + - slit + - slung + - smitten + - sold + - sought + - sown + - sped + - spent + - spilt + - spit + - split + - spoken + - spread + - sprung + - spun + - stolen + - stood + - stridden + - striven + - struck + - strung + - stuck + - stung + - stunk + - sung + - sunk + - swept + - swollen + - sworn + - swum + - swung + - taken + - taught + - thought + - thrived + - thrown + - thrust + - told + - torn + - trodden + - understood + - upheld + - upset + - wed + - wept + - withheld + - withstood + - woken + - won + - worn + - wound + - woven + - written + - wrung diff --git a/docs/styles/Microsoft/Percentages.yml b/docs/styles/Microsoft/Percentages.yml new file mode 100644 index 0000000000..b68a7363f4 --- /dev/null +++ b/docs/styles/Microsoft/Percentages.yml @@ -0,0 +1,7 @@ +extends: existence +message: "Use a numeral plus the units." +link: https://docs.microsoft.com/en-us/style-guide/numbers +nonword: true +level: error +tokens: + - '\b[a-zA-z]+\spercent\b' diff --git a/docs/styles/Microsoft/Plurals.yml b/docs/styles/Microsoft/Plurals.yml new file mode 100644 index 0000000000..1bb6660ade --- /dev/null +++ b/docs/styles/Microsoft/Plurals.yml @@ -0,0 +1,7 @@ +extends: existence +message: "Don't add '%s' to a singular noun. Use plural instead." +ignorecase: true +level: error +link: https://learn.microsoft.com/en-us/style-guide/a-z-word-list-term-collections/s/s-es +raw: + - '\(s\)|\(es\)' diff --git a/docs/styles/Microsoft/Quotes.yml b/docs/styles/Microsoft/Quotes.yml new file mode 100644 index 0000000000..38f4976061 --- /dev/null +++ b/docs/styles/Microsoft/Quotes.yml @@ -0,0 +1,7 @@ +extends: existence +message: 'Punctuation should be inside the quotes.' +link: https://docs.microsoft.com/en-us/style-guide/punctuation/quotation-marks +level: error +nonword: true +tokens: + - '["“][^"”“]+["”][.,]' diff --git a/docs/styles/Microsoft/RangeFormat.yml b/docs/styles/Microsoft/RangeFormat.yml new file mode 100644 index 0000000000..f1d736e9de --- /dev/null +++ b/docs/styles/Microsoft/RangeFormat.yml @@ -0,0 +1,13 @@ +extends: existence +message: "Use an en dash in a range of numbers." +link: https://docs.microsoft.com/en-us/style-guide/numbers +nonword: true +level: error +action: + name: edit + params: + - replace + - '-' + - '–' +tokens: + - '\b\d+\s?[-]\s?\d+\b' diff --git a/docs/styles/Microsoft/RangeTime.yml b/docs/styles/Microsoft/RangeTime.yml new file mode 100644 index 0000000000..cdd4b3346e --- /dev/null +++ b/docs/styles/Microsoft/RangeTime.yml @@ -0,0 +1,13 @@ +extends: existence +message: "Use 'to' instead of a dash in '%s'." +link: https://docs.microsoft.com/en-us/style-guide/numbers +nonword: true +level: error +action: + name: edit + params: + - replace + - '[-–]' + - 'to' +tokens: + - '\b(?:AM|PM)\s?[-–]\s?.+(?:AM|PM)\b' diff --git a/docs/styles/Microsoft/Ranges.yml b/docs/styles/Microsoft/Ranges.yml new file mode 100644 index 0000000000..67d9702b0f --- /dev/null +++ b/docs/styles/Microsoft/Ranges.yml @@ -0,0 +1,7 @@ +extends: existence +message: "In most cases, use 'from' or 'through' to describe a range of numbers." +link: 'https://docs.microsoft.com/en-us/style-guide/numbers' +nonword: true +level: warning +tokens: + - '\b\d+\s?[-–]\s?\d+\b' diff --git a/docs/styles/Microsoft/Semicolon.yml b/docs/styles/Microsoft/Semicolon.yml new file mode 100644 index 0000000000..4d905467dd --- /dev/null +++ b/docs/styles/Microsoft/Semicolon.yml @@ -0,0 +1,8 @@ +extends: existence +message: "Try to simplify this sentence." +link: https://docs.microsoft.com/en-us/style-guide/punctuation/semicolons +nonword: true +scope: sentence +level: suggestion +tokens: + - ';' diff --git a/docs/styles/Microsoft/SentenceLength.yml b/docs/styles/Microsoft/SentenceLength.yml new file mode 100644 index 0000000000..82e265634d --- /dev/null +++ b/docs/styles/Microsoft/SentenceLength.yml @@ -0,0 +1,6 @@ +extends: occurrence +message: "Try to keep sentences short (< 30 words)." +scope: sentence +level: suggestion +max: 30 +token: \b(\w+)\b diff --git a/docs/styles/Microsoft/Spacing.yml b/docs/styles/Microsoft/Spacing.yml new file mode 100644 index 0000000000..bbd10e51df --- /dev/null +++ b/docs/styles/Microsoft/Spacing.yml @@ -0,0 +1,8 @@ +extends: existence +message: "'%s' should have one space." +link: https://docs.microsoft.com/en-us/style-guide/punctuation/periods +level: error +nonword: true +tokens: + - '[a-z][.?!] {2,}[A-Z]' + - '[a-z][.?!][A-Z]' diff --git a/docs/styles/Microsoft/Suspended.yml b/docs/styles/Microsoft/Suspended.yml new file mode 100644 index 0000000000..7282e9c9cf --- /dev/null +++ b/docs/styles/Microsoft/Suspended.yml @@ -0,0 +1,7 @@ +extends: existence +message: "Don't use '%s' unless space is limited." +link: https://docs.microsoft.com/en-us/style-guide/punctuation/dashes-hyphens/hyphens +ignorecase: true +level: warning +tokens: + - '\w+- and \w+-' diff --git a/docs/styles/Microsoft/Terms.yml b/docs/styles/Microsoft/Terms.yml new file mode 100644 index 0000000000..400915fa75 --- /dev/null +++ b/docs/styles/Microsoft/Terms.yml @@ -0,0 +1,40 @@ +extends: substitution +message: "Prefer '%s' over '%s'." +# term preference should be based on microsoft style guide, such as +link: https://learn.microsoft.com/en-us/style-guide/a-z-word-list-term-collections/a/adapter +level: warning +ignorecase: true +action: + name: replace +swap: + "(?:drive C:|drive C>|C: drive)": drive C + "(?:internet bot|web robot)s?": bot(s) + "(?:microsoft cloud|the cloud)": cloud + "(?:mobile|smart) ?phone": phone + "24/7": every day + "audio(?:-| )book": audiobook + "back(?:-| )light": backlight + "chat ?bots?": chatbot(s) + adaptor: adapter + administrate: administer + afterwards: afterward + alphabetic: alphabetical + alphanumerical: alphanumeric + anti-aliasing: antialiasing + anti-malware: antimalware + anti-spyware: antispyware + anti-virus: antivirus + appendixes: appendices + artificial intelligence: AI + "(?:assembler|machine language)": assembly language + caap: CaaP + conversation-as-a-platform: conversation as a platform + eb: EB + gb: GB + gbps: Gbps + kb: KB + keypress: keystroke + mb: MB + pb: PB + tb: TB + zb: ZB diff --git a/docs/styles/Microsoft/URLFormat.yml b/docs/styles/Microsoft/URLFormat.yml new file mode 100644 index 0000000000..c81b486c4c --- /dev/null +++ b/docs/styles/Microsoft/URLFormat.yml @@ -0,0 +1,9 @@ +extends: substitution +message: "Use '%s' instead of '%s'." +ignorecase: true +level: error +action: + name: replace +swap: + URL for: URL of + an URL: a URL diff --git a/docs/styles/Microsoft/Units.yml b/docs/styles/Microsoft/Units.yml new file mode 100644 index 0000000000..f062418ee0 --- /dev/null +++ b/docs/styles/Microsoft/Units.yml @@ -0,0 +1,16 @@ +extends: existence +message: "Don't spell out the number in '%s'." +link: https://docs.microsoft.com/en-us/style-guide/a-z-word-list-term-collections/term-collections/units-of-measure-terms +level: error +raw: + - '[a-zA-Z]+\s' +tokens: + - '(?:centi|milli)?meters' + - '(?:kilo)?grams' + - '(?:kilo)?meters' + - '(?:mega)?pixels' + - cm + - inches + - lb + - miles + - pounds diff --git a/docs/styles/Microsoft/Vocab.yml b/docs/styles/Microsoft/Vocab.yml new file mode 100644 index 0000000000..eebe97b15e --- /dev/null +++ b/docs/styles/Microsoft/Vocab.yml @@ -0,0 +1,25 @@ +extends: existence +message: "Verify your use of '%s' with the A-Z word list." +link: 'https://docs.microsoft.com/en-us/style-guide' +level: suggestion +ignorecase: true +tokens: + - above + - accessible + - actionable + - against + - alarm + - alert + - alias + - allows? + - and/or + - as well as + - assure + - author + - avg + - beta + - ensure + - he + - insure + - sample + - she diff --git a/docs/styles/Microsoft/We.yml b/docs/styles/Microsoft/We.yml new file mode 100644 index 0000000000..97c901c1ba --- /dev/null +++ b/docs/styles/Microsoft/We.yml @@ -0,0 +1,11 @@ +extends: existence +message: "Try to avoid using first-person plural like '%s'." +link: https://docs.microsoft.com/en-us/style-guide/grammar/person#avoid-first-person-plural +level: warning +ignorecase: true +tokens: + - we + - we'(?:ve|re) + - ours? + - us + - let's diff --git a/docs/styles/Microsoft/Wordiness.yml b/docs/styles/Microsoft/Wordiness.yml new file mode 100644 index 0000000000..22a4c932c8 --- /dev/null +++ b/docs/styles/Microsoft/Wordiness.yml @@ -0,0 +1,122 @@ +extends: substitution +message: "Consider using '%s' instead of '%s'." +link: https://docs.microsoft.com/en-us/style-guide/word-choice/use-simple-words-concise-sentences +ignorecase: true +level: warning +action: + name: replace +swap: + (?:give|gave) rise to: lead to + (?:previous|prior) to: before + a (?:large)? majority of: most + a (?:large)? number of: many + a myriad of: myriad + adversely impact: hurt + all across: across + all of a sudden: suddenly + all of these: these + all of: all + all-time record: record + almost all: most + almost never: seldom + along the lines of: similar to + an adequate number of: enough + an appreciable number of: many + an estimated: about + any and all: all + are in agreement: agree + as a matter of fact: in fact + as a means of: to + as a result of: because of + as of yet: yet + as per: per + at a later date: later + at all times: always + at the present time: now + at this point in time: at this point + based in large part on: based on + based on the fact that: because + basic necessity: necessity + because of the fact that: because + came to a realization: realized + came to an abrupt end: ended abruptly + carry out an evaluation of: evaluate + close down: close + closed down: closed + complete stranger: stranger + completely separate: separate + concerning the matter of: regarding + conduct a review of: review + conduct an investigation: investigate + conduct experiments: experiment + continue on: continue + despite the fact that: although + disappear from sight: disappear + drag and drop: drag + drag-and-drop: drag + doomed to fail: doomed + due to the fact that: because + during the period of: during + during the time that: while + emergency situation: emergency + except when: unless + excessive number: too many + extend an invitation: invite + fall down: fall + fell down: fell + for the duration of: during + gather together: gather + has the ability to: can + has the capacity to: can + has the opportunity to: could + hold a meeting: meet + if this is not the case: if not + in a careful manner: carefully + in a thoughtful manner: thoughtfully + in a timely manner: timely + in an effort to: to + in between: between + in lieu of: instead of + in many cases: often + in most cases: usually + in order to: to + in some cases: sometimes + in spite of the fact that: although + in spite of: despite + in the (?:very)? near future: soon + in the event that: if + in the neighborhood of: roughly + in the vicinity of: close to + it would appear that: apparently + lift up: lift + made reference to: referred to + make reference to: refer to + mix together: mix + none at all: none + not in a position to: unable + not possible: impossible + of major importance: important + perform an assessment of: assess + pertaining to: about + place an order: order + plays a key role in: is essential to + present time: now + readily apparent: apparent + some of the: some + span across: span + subsequent to: after + successfully complete: complete + sufficient number (?:of)?: enough + take action: act + take into account: consider + the question as to whether: whether + there is no doubt but that: doubtless + this day and age: this age + this is a subject that: this subject + time (?:frame|period): time + under the provisions of: under + until such time as: until + used for fuel purposes: used for fuel + whether or not: whether + with regard to: regarding + with the exception of: except for diff --git a/docs/styles/Microsoft/meta.json b/docs/styles/Microsoft/meta.json new file mode 100644 index 0000000000..297719bbbf --- /dev/null +++ b/docs/styles/Microsoft/meta.json @@ -0,0 +1,4 @@ +{ + "feed": "https://github.com/errata-ai/Microsoft/releases.atom", + "vale_version": ">=1.0.0" +} diff --git a/docs/styles/config/vocabularies/edgeless/accept.txt b/docs/styles/config/vocabularies/edgeless/accept.txt new file mode 100644 index 0000000000..12a80ed3dd --- /dev/null +++ b/docs/styles/config/vocabularies/edgeless/accept.txt @@ -0,0 +1,102 @@ +Affero +agent +Ansys +API +Asciinema +ASG +auditable +autoscaler +autoscaling +AWS +backend +backport +Bazel +bootloader +Bootstrapper +cachix +cloud +cmdline +config +Containerd +CPU +CRD +CRI +CSP +cyber +datacenter +Datadog +deallocate +DEK +Dockerfile +Dynatrace +Emojivoto +etcd +Filebeat +Filestash +Filestore +filesystem +Fluentd +frontend +Fulcio +Gbps +GCP +gRPC +Grype +hyperv +IAM +Initializer +initramfs +iodepth +IPSec +Istio +journald +Kata +KEK +KMS +kubeadm +kubectl +kubelet +Kustomization +libcryptsetup +Logstash +Mbps +MicroK8s +namespace +Nginx +paravisor +PCR +plaintext +protobuf +proxied +QEMU +Rego +Rekor +resizable +resourceGroup +rollout +SBOM +sigstore +SSD +substituters +superset +Syft +systemd +Terraform +Tink +TPM +underspecified +unencrypted +unspoofable +untrusted +updatable +UUID +vCPU +virsh +VM +VSCode +walkthrough +whitepaper +WireGuard +Xeon +xsltproc +Zipkin diff --git a/rfc/001-service-mesh.md b/rfc/001-service-mesh.md index d880debac1..3a7f24b996 100644 --- a/rfc/001-service-mesh.md +++ b/rfc/001-service-mesh.md @@ -39,18 +39,18 @@ For ingress traffic, we define a port mapping from the proxy to the application. All traffic that target the proxy on that port will be forwarded to the other port. We also need to protect the application from being talked to directly via the port it exposes. To achieve that, we block all incoming traffic to the application -via iptables. +via `iptables`. For egress traffic, we configure a port and an endpoint. The proxy will listen locally on the port and forward all traffic to the specified endpoint. We set the endpoint in the application setting to `localhost:port`. -### Routing Solution 2: iptables based re-routing +### Routing Solution 2: `iptables` based re-routing With this solution we take care of the correct routing for the user and have no requirements regarding configuration of endpoints. -One example of iptables based routing is Istio [1] [2] [3]. +One example of `iptables` based routing is Istio [1] [2] [3]. In contrast to Istio, we don't need a way to configure anything dynamically, since we don't have the concept of virtual services and also our certificates are wildcard certificates per default. @@ -61,16 +61,16 @@ are wildcard certificates per default. [3] -### Proxy Solution 1: Custom implemented tproxy +### Proxy Solution 1: Custom implemented TPROXY TPROXY [1] is a kernel feature to allow applications to proxy traffic without -changing the actual packets e.g., when re-routing them via NAT. +changing the actual packets, for example when re-routing them via NAT. -The proxy can implement custom user-space logic to handle traffic and easily +The proxy can implement custom user-space logic to handle traffic and route the traffic to the original destination (see a simple Go example [2]). We likely re-implement parts of Envoy (see below), but have more -flexibility regarding additional verification, e.g. should we decide to also +flexibility regarding additional verification, for example in case we decide to also use custom client certificate extensions. [1] @@ -80,13 +80,13 @@ use custom client certificate extensions. ### Proxy Solution 2: Envoy Envoy is a L3/4/7 proxy used by Istio and Cilium. In combination with either -iptables REDIRECT or TPROXY it can be used to handle TLS origination and +`iptables REDIRECT` or TPROXY it can be used to handle TLS origination and termination [1]. The routing will be done via the original destination filter [2]. For TLS origination we wrap all outgoing connections in TLS since we -cannot rely on DNS to be secure. Istio uses "secure naming" [3] to at least +can't rely on DNS to be secure. Istio uses "secure naming" [3] to at least protect HTTP/HTTPS traffic from DNS spoofing, but r.g., raw TCP or UDP traffic -is not secured. +isn't secured. [1] @@ -130,7 +130,7 @@ map it to a remote service domain. If possible, we don't want to touch the port of the packets so that we can transparently proxy all ports of a service. -Note that this is not secure by default. If the user doesn't configure the +Note that this isn't secure by default. If the user doesn't configure the endpoints in their application, traffic is send out unencrypted and without authentication. @@ -138,13 +138,13 @@ authentication. ### Step 2: Ingress -For ingress traffic we deploy iptable rules which redirect all traffic to -Envoy via tproxy iptable rules. After Envoy has terminated the TLS connection, +For ingress traffic we deploy `iptables` rules which redirect all traffic to +Envoy via TPROXY `iptables` rules. After Envoy has terminated the TLS connection, it sends out the traffic again to the workload. The routing is similar to what Istio does [1]. -The user can configure an allowlist of ports which should not be redirected to -Envoy. Also traffic originating from the uid the proxy is started with, is not +The user can configure an allow list of ports which shouldn't be redirected to +Envoy. Also traffic originating from the UID the proxy is started with, isn't redirected. Since by default all traffic is routed to Envoy, the workload's ingress endpoint are secure by default. @@ -155,17 +155,17 @@ ingress endpoint are secure by default. Ideally, we also want to also have secure by default egress. But this comes with additional tradeoffs. If we assume that the workload does _NOT_ talk to any other endpoints outside of the service mesh, then we can redirect all traffic -through the proxy. Since we cannot assume this to be true for all workloads, +through the proxy. Since we can't assume this to be true for all workloads, we still need the explicit configuration method described above. -Since we need to allow DNS for Kubernetes service lookups, we can only redirect +Since we need to allow DNS for Kubernetes service lookup, we can only redirect all TCP traffic via the proxy. ### Optional: Egress capturing via DNS If we want to allow additional endpoints, we also need to touch the pod's -DNS resolution. An easy way would be to resolve the allowlisted entries to -either directly the correct endpoint or to a special ip of the proxy. +DNS resolution. An easy way would be to resolve the allow-listed entries to +either directly the correct endpoint or to a special IP of the proxy. This required the application to not implement basic DNS (over UDP) and not DNS-over-HTTPS, DNS-over-QUIC, or similar. @@ -173,6 +173,6 @@ DNS-over-HTTPS, DNS-over-QUIC, or similar. Especially for ingress but also for egress as described in step 3, we must ensure that the sidecar/init container runs -before the workloads receives traffic. Otherwise, it might be that the iptable -rules are not configured yet and the traffic is send without TLS and without +before the workloads receives traffic. Otherwise, it might be that the `iptables` +rules aren't configured yet and the traffic is send without TLS and without client verification. diff --git a/rfc/002-secure-set-manifest-endpoint.md b/rfc/002-secure-set-manifest-endpoint.md index b9500e72bd..eaeb65b704 100644 --- a/rfc/002-secure-set-manifest-endpoint.md +++ b/rfc/002-secure-set-manifest-endpoint.md @@ -7,8 +7,8 @@ The SetManifest endpoint should only be accessible by the entity that first call The manifest enforced by the coordinator can be updated. This will become increasingly relevant once stateful applications are supported by CoCo upstream. The proposed solution follows a trust on first use (TOFU) model, -where the initial call to the SetManifest endpoint is not protected with the same mechanism. -Protecting the initial access is not in scope for this document, +where the initial call to the SetManifest endpoint isn't protected with the same mechanism. +Protecting the initial access isn't in scope for this document, although it may still be useful in practice to protect this endpoint using other methods, such as firewall rules, password authentication or other means. The secure SetManifest endpoint should thus allow any entity to set the initial manifest @@ -25,28 +25,28 @@ The coordinator can be in one of three states: ## Key exchange The coordinator trusts a list of x509 key pairs that belong to the entity that first called the SetManifest endpoint. -The key pair(s) are called workload owner keys. +The key pairs are called workload owner keys. A workload owner key must not be signed by the root CA / mesh CA so there is no potential for impersonation between the workload owner and mesh certificates. The client sends a list of trusted public keys as part of manifest in the initial call. In the default case, a single public key is used, allowing the owner of the secret key to update the manifest. -If the list is empty, nobody can update the manifest after the initial call and the client does not need to store a secret key on disk. +If the list is empty, nobody can update the manifest after the initial call and the client doesn't need to store a secret key on disk. Multiple keys can be specified to allow multiple parties to perform updates. This can later be extended as described below. The list of trusted public keys must always be included in the manifest. This way, the data owner can validate who is allowed to update the manifest and the trusted public keys can be rotated (or any further updates prevented) as part of the manifest. -Another consideration is whether the same grpc endpoint should be used in both states (initial, updating) or if a split is beneficial. +Another consideration is whether the same grpc endpoint should be used in both states (initial, updating) or if a split's beneficial. This is merely an implementation detail and not important for the overall design. We will attempt to reuse the same endpoint. ## Enforcement of mutual TLS with client authentication on manifest updates -In the initial state, TLS client authentication is not enforced. +In the initial state, TLS client authentication isn't enforced. This allows any client to establish a TLS connection and set a manifest. In the updatable state, the coordinator enforces TLS client authentication on the SetManifest endpoint. This architecture could be reused for future authenticated grpc endpoints. -The mechanism for performing cert validation has to account for the fact that some grpc endpoints require client authentication, while others do not. +The mechanism for performing cert validation has to account for the fact that some grpc endpoints require client authentication, while others don't. In particular, this requires any certificate validation to be performed after the grpc endpoint is known (after the TLS handshake). If this is infeasible, multiple listeners may be used to perform validation during the handshake instead. @@ -65,6 +65,6 @@ A similar mechanism exists today in MarbleRun[1]. ## Alternatives considered: Signed manifest updates -With this solution, the manifest data used when calling the SetManifest endpoint for updates must be signed by a trusted key and the signature must be sent together with the manifest data. TLS client authentication is not used. +With this solution, the manifest data used when calling the SetManifest endpoint for updates must be signed by a trusted key and the signature must be sent together with the manifest data. TLS client authentication isn't used. The same ways to establish trusted signing keys apply. -As a positive side effect, the signed manifest could be handed to the data owner to proof that the workload owner performed the SetManifest call. As a downside, the signed manifest could be replayed by an attacker if the signature does not incorporate replay protection. Such a protection could be implemented using a challenge/response mechanism, by rejecting already seen manifest signatures (and using a nonce), or by adding a revision counter. +As a positive side effect, the signed manifest could be handed to the data owner to proof that the workload owner performed the SetManifest call. As a downside, the signed manifest could be replayed by an attacker if the signature doesn't incorporate replay protection. Such a protection could be implemented using a challenge/response mechanism, by rejecting already seen manifest signatures (and using a nonce), or by adding a revision counter. diff --git a/treefmt.nix b/treefmt.nix index 81567163de..5ea821f84b 100644 --- a/treefmt.nix +++ b/treefmt.nix @@ -1,4 +1,4 @@ -_: +{ lib, pkgs, ... }: { projectRootFile = "flake.nix"; programs = { @@ -19,4 +19,18 @@ _: yamlfmt.enable = true; # keep-sorted end }; + settings.formatter = { + vale = { + command = "${lib.getExe pkgs.vale}"; + options = [ + "--no-wrap" + ]; + includes = [ + "*.md" + ]; + excludes = [ + "CODE_OF_CONDUCT.md" + ]; + }; + }; }