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
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ Operators can set up third-party integrations such as [Dependency-Track](https:/

Ops can mix and match with different integrations while **not requiring developers to make any changes on their side**!

You can see the list of available integrations by running `chainloop integration available list` or by browsing [their source code](./app/controlplane/extensions/).

### Role-tailored experience

Chainloop makes sure to clearly define the responsibilities, experience and functional scope of the **two main personas, Security/Operation (SecOps) and Development/Application teams**.
Expand Down
4 changes: 4 additions & 0 deletions app/controlplane/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ It's implemented following(ish) [Hexagonal architecture](https://netflixtechblog
- Business layer `./internal/biz`. Implementation of use-cases referenced by the service layer and definition of the data repository abstractions.
- Data layer `./internal/data`. Implementation of data repositories interfaces defined in the business layer.

## Extensions

The source code and documentation for the different supported extensions can be found at `./extensions`.

## System Dependencies

The control plane has 4 main dependencies
Expand Down
119 changes: 90 additions & 29 deletions app/controlplane/extensions/README.md
Original file line number Diff line number Diff line change
@@ -1,52 +1,113 @@
# Chainloop Extensions

Chainloop extensions are a way to extend the functionality of the Chainloop.
Chainloop extensions are a way to add functionality to Chainloop by integrating with third-parties.

Currently we only support one type, fanOut extensions. A FanOut extension implements logic that will get executed when attestations or materials are received. This logic can be anything from sending a Slack message, uploading the attestation to a storage backend or sending a Software Bill Of Materials (SBOMs) to Dependency-Track for analysis, for example.

![FanOut Extension](../../../docs/img/fanout.png)

## Lifecycle

An fanOut extension goes through 4 different stages. Loading, Registration, Attachment and Execution.

### Loading Stage

The loading stage is when the extension gets enabled in the Chainloop Control Plane. This is implemented via the extension constructor. It is when you, as a extension developer, will define:

- The extension identifier, version and description.
- What kind of input you want your extension to receive, materials, attestations or both.
- Available input properties for the registration and attachment phases. These schemas will be shown to the user and will be used to validate the input.

Once loaded, the extension will be available to be registered on any organization and will be shown in the list of available extensions.

```console
$ chainloop integration available list
┌─────────────────┬─────────┬──────────────────────┬───────────────────────────────────────────────────────────┐
│ ID │ VERSION │ MATERIAL REQUIREMENT │ DESCRIPTION │
├─────────────────┼─────────┼──────────────────────┼───────────────────────────────────────────────────────────┤
│ dependencytrack │ 0.2 │ SBOM_CYCLONEDX_JSON │ Send CycloneDX SBOMs to your Dependency-Track instance │
├─────────────────┼─────────┼──────────────────────┼───────────────────────────────────────────────────────────┤
│ smtp │ 0.1 │ │ Send emails with information about a received attestation │
├─────────────────┼─────────┼──────────────────────┼───────────────────────────────────────────────────────────┤
│ oci-registry │ 0.1 │ │ Send attestations to a compatible OCI registry │
├─────────────────┼─────────┼──────────────────────┼───────────────────────────────────────────────────────────┤
│ discord-webhook │ 0.1 │ │ Send attestations to Discord │
└─────────────────┴─────────┴──────────────────────┴───────────────────────────────────────────────────────────
```

And the information of how to use it can be found in the describe command.

```console
$ chainloop integration available describe --id dependencytrack
┌─────────────────┬─────────┬──────────────────────┬────────────────────────────────────────────────────────┐
│ ID │ VERSION │ MATERIAL REQUIREMENT │ DESCRIPTION │
├─────────────────┼─────────┼──────────────────────┼────────────────────────────────────────────────────────┤
│ dependencytrack │ 0.2 │ SBOM_CYCLONEDX_JSON │ Send CycloneDX SBOMs to your Dependency-Track instance │
└─────────────────┴─────────┴──────────────────────┴────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────────────────────────┐
│ Registration inputs │
├─────────────────┬──────────────┬──────────┬──────────────────────────────────────────┤
│ FIELD │ TYPE │ REQUIRED │ DESCRIPTION │
├─────────────────┼──────────────┼──────────┼──────────────────────────────────────────┤
│ allowAutoCreate │ boolean │ no │ Support of creating projects on demand │
│ apiKey │ string │ yes │ The API key to use for authentication │
│ instanceURI │ string (uri) │ yes │ The URL of the Dependency-Track instance │
└─────────────────┴──────────────┴──────────┴──────────────────────────────────────────┘
┌───────────────────────────────────────────────────────────────────────────────────────────┐
│ Attachment inputs │
├─────────────┬────────┬──────────┬─────────────────────────────────────────────────────────┤
│ FIELD │ TYPE │ REQUIRED │ DESCRIPTION │
├─────────────┼────────┼──────────┼─────────────────────────────────────────────────────────┤
│ projectID │ string │ no │ The ID of the existing project to send the SBOMs to │
│ projectName │ string │ no │ The name of the project to create and send the SBOMs to │
└─────────────┴────────┴──────────┴─────────────────────────────────────────────────────────┘
```

In addition to the constructor 3 more handlers need to be implemented.

![FanOut sdk](../../../docs/img/fanout-sdk.png)

### Registration Stage

Currently we only support one type, fan-out extensions. FanOut extensions implement logic that will get executed when attestations or materials are received,

## Anatomy of a FanOut Extension

### Lifecycle

An fanOut extension goes through 4 different stages. Loading, Registration, Attachment and Execution

#### Loading

Loading is when the extension gets enabled in the Chainloop Control plane. This is implemented via the extension constructor. At this time is when you, as a developer, can configure the identity of the extension and what kind of input you are expecting to receive. Materials, attestations or both.

Example:
Registration is when a specific instance of the extension is configured on a Chainloop organization. A registered instance is then available to be attached to any workflow, more on that later.

- Load the dependency track instance extension
This handler will receive the input from the user, will validate it against the defined schema and run any custom logic. The handler's returned value will be stored in the extension state, which will make it available to the other handlers.

#### Registration
Examples:

Registration is when a specific instance of the extension is configured on a Chainloop organization. A registered instance is then available to be attached to any workflow, more on that later.
- Register a Dependency-Track instance by receiving its URL and API key. At this stage, the extension will make sure that the provided information is valid and store it for later use.
- Register a Discord instance by receiving its webhook URL. The handler will store the webhook URL securely for later use.

Example:
### Attachment Stage

- Register a dependency track instance by receiving its URL and API key. At this stage, the extension will make sure that the provided information is valid and store it for later use.
In order for an user to use a registered instance, it needs to be attached to a workflow. This stage can be also used to optionally customize the behavior of the extension for a specific workflow.

#### Attachment
This handler **will receive not only the input from the user but also the output from the registration state**. Similarly to the registration handler, the handler returned output value will be stored in the state for later use.

Attachment happens when a registered instance is attached to a Workflow. This means that any attestations or materials that are received by the workflow will be sent to the attached extension for processing.
Examples:

Example:
- Tell the already registered Dependency Track instance to send the SBOMs **to a specific project**.
- Tell the already registered Discord instance to send all attestations to the configured channel

- Tell the already registered dependency track instance to send the SBOMs to a specific project.
### Execution Stage

#### Execution
This is the actual execution of the extension. This is where the extension will do its work. i.e call a workflow or send a notification.

This is the actual execution of the extension. This is where the extension will do its work. i.e call a workflow, or send a notification.
This handler **will also have access to the outputs from the registration and attachment phases**.

Example:
Examples:

In the dependency track use-case we will
A Dependency-Track SBOM extension will

- Get the instance URL and API key from the state stored during the registration phase
- Get the specific project where we want to post the SBOMs from the attachment phase
- Send the SBOMs to the dependency track instance

## How to create a new extension
A Discord webhook extension will

- Get the Webhook URL from the state stored during the registration phase
- Craft message to send to the Discord webhook

## How to create a new extension

We offer a starter template in `./core/template`. Just copy it to a new folder and follow the steps shown in its readme.
We offer a [starter template](./core/template). Just copy it to a new folder and follow the steps shown in its readme file.
9 changes: 3 additions & 6 deletions app/controlplane/extensions/core/template/v1/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,13 @@ You can use this template as a placeholder to create your own fan-out extension.

These are the required steps

### Setup:
### Pre-requisites

- Copy and rename the folder to your extension name
- Replace all the occurrences of `template` with your extension name
- Add it to the list of available extensions [here](`../../../../../extensions.go`). This will make this extension available the next time the control plane starts. More on its lifecycle [here](https://github.com/chainloop-dev/chainloop/blob/main/app/controlplane/extensions/README.md)

### Implementation

- Define the API request payloads for both Registration and Attachment
- Implement the [FanOutExtension interface](https://github.com/chainloop-dev/chainloop/blob/main/app/controlplane/extensions/sdk/v1/fanout.go#L55). The template comes prefilled with some commented out code.

### Enable extension for

- Add it to the list of available extensions [here](`../../../../../extensions.go`). This will make this extension available the next time the control plane starts.
- Implement the [FanOutExtension interface](https://github.com/chainloop-dev/chainloop/blob/main/app/controlplane/extensions/sdk/v1/fanout.go#L55). The template comes prefilled with some commented out code.
5 changes: 5 additions & 0 deletions devel/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@ You will get redirected to the pre-configured local OIDC provider (DEX) where th

Once logged in, please refer to our [Getting Started guide](https://docs.chainloop.dev/getting-started/setup) to learn how to setup an OCI registry.

## Developing Extensions / Integrations

Refer to the [Extensions](../app/controlplane/extensions/README.md) documentation for more information.


## Troubleshooting

### Integration tests failing on OSX with Docker Desktop
Expand Down
Binary file added docs/img/fanout-sdk.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/img/fanout.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.