From 1c1af6b4c9c595b162518f694cb1bafdee94ad7b Mon Sep 17 00:00:00 2001 From: Mohamed Habib Date: Fri, 28 Jun 2024 17:36:32 +0100 Subject: [PATCH] add page on external providers code execution (#1595) * add page on external providers code execution, add notes about spec signing --- docs/mint.json | 7 ++ docs/securing-digger/external-provider.mdx | 16 ++++ docs/securing-digger/spec-signing.mdx | 93 ++++++++++++++++++++++ 3 files changed, 116 insertions(+) create mode 100644 docs/securing-digger/external-provider.mdx create mode 100644 docs/securing-digger/spec-signing.mdx diff --git a/docs/mint.json b/docs/mint.json index 7f4be28a5..288f41447 100644 --- a/docs/mint.json +++ b/docs/mint.json @@ -149,6 +149,13 @@ "troubleshooting/action-errors", "troubleshooting/comments" ] + }, + { + "group": "Securing Digger", + "pages": [ + "securing-digger/external-provider", + "securing-digger/spec-signing" + ] } ], "footerSocials": { diff --git a/docs/securing-digger/external-provider.mdx b/docs/securing-digger/external-provider.mdx new file mode 100644 index 000000000..78d299725 --- /dev/null +++ b/docs/securing-digger/external-provider.mdx @@ -0,0 +1,16 @@ +--- +title: "External providers code execution" +--- + +Digger executes terraform in github actions within previlliged environments. Since terraform has the ability +to execute arbitrary code based on data blocks or external providers this can lead to a user with mallicious +intent to expose the environment variables within the CI environment, potentially leaking cloud secrets. + +How to avoid this? +--- +Currently we are exploring solutions to avoid this security threat. The first thing you should do is to +not use long-lived credentials to connect to your cloud account. Instead rely on OIDC for short-lived +credentials to minimise the exposure from this threat. Secondly its important to ensure that only trusted +individuals are allowed to update the terraform code. We are also working on additional solutions to secure +against this threat. For more details and to engage in the discussion please take a look at this github issue: +https://github.com/diggerhq/digger/issues/1530 diff --git a/docs/securing-digger/spec-signing.mdx b/docs/securing-digger/spec-signing.mdx new file mode 100644 index 000000000..6830aef9b --- /dev/null +++ b/docs/securing-digger/spec-signing.mdx @@ -0,0 +1,93 @@ +--- +title: "Digger spec signatures" +--- + + +A note about backendless mode +------- +This guide assumes that you are running digger with the orchestrator backend (cloud or self-hosted). +Digger can also be run in backendless mode as a pure cli. While we do rely on the same spec in backendless +mode for the sake of code reusability, this document is mainly aimed at folks using digger with the orchestrator. + +About digger Spec +---- + +As you know digger has two main components: the cli and the orchestrator backend. The orchestrator listens +for events and triggers jobs in the CI system. The job will invoke the cli which then executes the terraform +commands. The environment in which the cli runs in is previlliged and needs to be protected. This is because +it has access to the cloud accounts and can provision resources. Therefore it has (through api keys or other keyless +methods) access to read and write sensitive resources on cloud accounts. The way in which digger orchestrator +communicates with the cli is through a `spec`. The spec is a self-contained JSON which defines the intended behaviour +of the cli. You can think of it as an instruction to the cli to run a particular command. But it also contains further +information about the context. Here is an example of a spec JSON: + +``` +{ + spec: { + "job_id": "abc123", + "run_name": "digger plan staging-vpc By: motatoes", + Job: { + # .... + "commands": ["digger plan"] + "workflow_file": "digger_workflow.yml" + }, + reporter: { + "reporting_strategy": "comments_per_run", + "reporter_type": "lazy", + }, + lock: { + lock_type: "noop", + }, + "backend": { + "backend_hostname": "cloud.digger.dev", + "backend_organisation_name": "digger", + "backend_job_token": "j:abc123-1234-1234-1234", + "backend_type": "backend", + }, + "vcs": { + "vcs_type": "github", + "actor": "motatoes", + "repo_owner": "diggerhq", + "repo_name": "demo-opentofu", + }, + "policy": { + "policy_type": "http", + }, + "plan_storage": { + "storage_type": "github_artefact" + } + } + } + +``` + +As you can see in the spec it has information about who performed the command, what vcs is used. Where the cli should +comment and what commands should be run. Also about where the cli can find the policies to check against. Where to store +plan artefacts. The sepc is a self-contained struct that can instruct the cli to do its job. + +How to secure the spec +------ + +By now you are probably wondering how one can ensure that no malicious actors can manipulate the spec. For example +what is to stop a bad actor from capturing a spec from a previous job and modifying it to bypass previlleges? Maybe he +can change the actor and gain access to an environment that they are not supposed to have access to by invoking +the CI job directly, bypassing the orchestrator. This is where spec signing comes into play. Just like JWT tokens are +signed to validate that they were generated by a server and not tampered with, the spec is also signed by the orchestrator. +This is what a signed spec payload will look like: + +``` +{ + spec: { + ...... + expiry: 1719595950 # in 1 hour + }, + signature: { + signature: "xxxxxxxyyyyyyyyzzzzzzz", + verify: true + } +} +``` + +When the cli sees that a signature has been sent it will verify it based on the public key that was supplied to it as an environment variable. +If verification fails the cli will halt with a `signatureCerificationFailed` error. It will also check that the payload has not expired. +In this way we are only allowing the orchestrator to trigger jobs in the CI. It is advised to turn on signature verification if you are using digger for any usecase outside of a POC phase. \ No newline at end of file