mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2026-03-15 17:13:46 +01:00
Allow to configure a config extension per repo (#3349)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: qwerty287 <80460567+qwerty287@users.noreply.github.com>
This commit is contained in:
160
docs/docs/20-usage/72-extensions/40-configuration-extension.md
Normal file
160
docs/docs/20-usage/72-extensions/40-configuration-extension.md
Normal file
@@ -0,0 +1,160 @@
|
||||
# Configuration extension
|
||||
|
||||
The configuration extension can be used to modify or generate Woodpeckers pipeline configurations. You can configure an HTTP endpoint in the repository settings in the extensions tab.
|
||||
|
||||
Using such an extension can be useful if you want to:
|
||||
|
||||
<!-- cSpell:words templating,Starlark,Jsonnet -->
|
||||
|
||||
- Preprocess the original configuration file with something like Go templating
|
||||
- Convert custom attributes to Woodpecker attributes
|
||||
- Add defaults to the configuration like default steps
|
||||
- Convert configuration files from a totally different format like Gitlab CI config, Starlark, Jsonnet, ...
|
||||
- Centralize configuration for multiple repositories in one place
|
||||
|
||||
## Security
|
||||
|
||||
:::warning
|
||||
As Woodpecker will pass private information like tokens and will execute the returned configuration, it is extremely important to secure the external extension. Therefore Woodpecker signs every request. Read more about it in the [security section](./index.md#security).
|
||||
:::
|
||||
|
||||
## Global configuration
|
||||
|
||||
In addition to the ability to configure the extension per repository, you can also configure a global endpoint in the Woodpecker server configuration. This can be useful if you want to use the extension for all repositories. Be careful if
|
||||
you share your Woodpecker server with others as they will also use your configuration extension.
|
||||
|
||||
The global configuration will be called before the repository specific configuration extension if both are configured.
|
||||
|
||||
```ini title="Server"
|
||||
WOODPECKER_CONFIG_SERVICE_ENDPOINT=https://example.com/ciconfig
|
||||
```
|
||||
|
||||
## How it works
|
||||
|
||||
When a pipeline is triggered Woodpecker will fetch the pipeline configuration from the repository, then make a HTTP POST request to the configured extension with a JSON payload containing some data like the repository, pipeline information and the current config files retrieved from the repository. The extension can then send back modified or even new pipeline configurations following Woodpeckers official yaml format that should be used.
|
||||
|
||||
### Request
|
||||
|
||||
The extension receives an HTTP POST request with the following JSON payload:
|
||||
|
||||
```ts
|
||||
class Request {
|
||||
repo: Repo;
|
||||
pipeline: Pipeline;
|
||||
netrc: Netrc;
|
||||
configuration: {
|
||||
name: string; // filename of the configuration file
|
||||
data: string; // content of the configuration file
|
||||
}[];
|
||||
}
|
||||
```
|
||||
|
||||
Checkout the following models for more information:
|
||||
|
||||
- [repo model](https://github.com/woodpecker-ci/woodpecker/blob/main/server/model/repo.go)
|
||||
- [pipeline model](https://github.com/woodpecker-ci/woodpecker/blob/main/server/model/pipeline.go)
|
||||
- [netrc model](https://github.com/woodpecker-ci/woodpecker/blob/main/server/model/netrc.go)
|
||||
|
||||
:::tip
|
||||
The `netrc` data is pretty powerful as it contains credentials to access the repository. You can use this to clone the repository or even use the forge (Github or Gitlab, ...) API to get more information about the repository.
|
||||
:::
|
||||
|
||||
Example request:
|
||||
|
||||
```json
|
||||
{
|
||||
"repo": {
|
||||
"id": 100,
|
||||
"uid": "",
|
||||
"user_id": 0,
|
||||
"namespace": "",
|
||||
"name": "woodpecker-test-pipeline",
|
||||
"slug": "",
|
||||
"scm": "git",
|
||||
"git_http_url": "",
|
||||
"git_ssh_url": "",
|
||||
"link": "",
|
||||
"default_branch": "",
|
||||
"private": true,
|
||||
"visibility": "private",
|
||||
"active": true,
|
||||
"config": "",
|
||||
"trusted": false,
|
||||
"protected": false,
|
||||
"ignore_forks": false,
|
||||
"ignore_pulls": false,
|
||||
"cancel_pulls": false,
|
||||
"timeout": 60,
|
||||
"counter": 0,
|
||||
"synced": 0,
|
||||
"created": 0,
|
||||
"updated": 0,
|
||||
"version": 0
|
||||
},
|
||||
"pipeline": {
|
||||
"author": "myUser",
|
||||
"author_avatar": "https://myforge.com/avatars/d6b3f7787a685fcdf2a44e2c685c7e03",
|
||||
"author_email": "my@email.com",
|
||||
"branch": "main",
|
||||
"changed_files": ["some-filename.txt"],
|
||||
"commit": "2fff90f8d288a4640e90f05049fe30e61a14fd50",
|
||||
"created_at": 0,
|
||||
"deploy_to": "",
|
||||
"enqueued_at": 0,
|
||||
"error": "",
|
||||
"event": "push",
|
||||
"finished_at": 0,
|
||||
"id": 0,
|
||||
"link_url": "https://myforge.com/myUser/woodpecker-testpipe/commit/2fff90f8d288a4640e90f05049fe30e61a14fd50",
|
||||
"message": "test old config\n",
|
||||
"number": 0,
|
||||
"parent": 0,
|
||||
"ref": "refs/heads/main",
|
||||
"refspec": "",
|
||||
"clone_url": "",
|
||||
"reviewed_at": 0,
|
||||
"reviewed_by": "",
|
||||
"sender": "myUser",
|
||||
"signed": false,
|
||||
"started_at": 0,
|
||||
"status": "",
|
||||
"timestamp": 1645962783,
|
||||
"title": "",
|
||||
"updated_at": 0,
|
||||
"verified": false
|
||||
},
|
||||
"configs": [
|
||||
{
|
||||
"name": ".woodpecker.yaml",
|
||||
"data": "steps:\n - name: backend\n image: alpine\n commands:\n - echo \"Hello there from Repo (.woodpecker.yaml)\"\n"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Response
|
||||
|
||||
The extension should respond with a JSON payload containing the new configuration files in Woodpecker's official YAML format.
|
||||
If the extension wants to keep the existing configuration files, it can respond with HTTP status `204 No Content`.
|
||||
|
||||
```ts
|
||||
class Response {
|
||||
configs: {
|
||||
name: string; // filename of the configuration file
|
||||
data: string; // content of the configuration file
|
||||
}[];
|
||||
}
|
||||
```
|
||||
|
||||
Example response:
|
||||
|
||||
```json
|
||||
{
|
||||
"configs": [
|
||||
{
|
||||
"name": "central-override",
|
||||
"data": "steps:\n - name: backend\n image: alpine\n commands:\n - echo \"Hello there from ConfigAPI\"\n"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
7
docs/docs/20-usage/72-extensions/_category_.yaml
Normal file
7
docs/docs/20-usage/72-extensions/_category_.yaml
Normal file
@@ -0,0 +1,7 @@
|
||||
label: 'Extensions'
|
||||
# position: 3
|
||||
collapsible: true
|
||||
collapsed: true
|
||||
link:
|
||||
type: 'doc'
|
||||
id: 'index'
|
||||
34
docs/docs/20-usage/72-extensions/index.md
Normal file
34
docs/docs/20-usage/72-extensions/index.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# Extensions
|
||||
|
||||
Woodpecker allows you to replace internal logic with external extensions by using pre-defined http endpoints.
|
||||
|
||||
There is currently one type of extension available:
|
||||
|
||||
- [Configuration extension](./40-configuration-extension.md) to modify or generate pipeline configurations on the fly.
|
||||
|
||||
## Security
|
||||
|
||||
:::warning
|
||||
You need to trust the extensions as they are receiving private information like secrets and tokens and might return harmful
|
||||
data like malicious pipeline configurations that could be executed.
|
||||
:::
|
||||
|
||||
To prevent your extensions from such attacks, Woodpecker is signing all HTTP requests using [HTTP signatures](https://tools.ietf.org/html/draft-cavage-http-signatures). Woodpecker therefore uses a public-private ed25519 key pair.
|
||||
To verify the requests your extension has to verify the signature of all request using the public key with some library like [httpsign](https://github.com/yaronf/httpsign).
|
||||
You can get the public Woodpecker key by opening `http://my-woodpecker.tld/api/signature/public-key` or by visiting the Woodpecker UI, going to you repo settings and opening the extensions page.
|
||||
|
||||
## Example extensions
|
||||
|
||||
A simplistic service providing endpoints for a config and secrets extension can be found here: [https://github.com/woodpecker-ci/example-extensions](https://github.com/woodpecker-ci/example-extensions)
|
||||
|
||||
## Configuration
|
||||
|
||||
To prevent extensions from calling local services by default only external hosts / ip-addresses are allowed. You can change this behavior by setting the `WOODPECKER_EXTENSIONS_ALLOWED_HOSTS` environment variable. You can use a comma separated list of:
|
||||
|
||||
- Built-in networks:
|
||||
- `loopback`: 127.0.0.0/8 for IPv4 and ::1/128 for IPv6, localhost is included.
|
||||
- `private`: RFC 1918 (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) and RFC 4193 (FC00::/7). Also called LAN/Intranet.
|
||||
- `external`: A valid non-private unicast IP, you can access all hosts on public internet.
|
||||
- `*`: All hosts are allowed.
|
||||
- CIDR list: `1.2.3.0/8` for IPv4 and `2001:db8::/32` for IPv6
|
||||
- (Wildcard) hosts: `example.com`, `*.example.com`, `192.168.100.*`
|
||||
@@ -1071,6 +1071,15 @@ Specify a configuration service endpoint, see [Configuration Extension](#externa
|
||||
|
||||
---
|
||||
|
||||
### EXTENSIONS_ALLOWED_HOSTS
|
||||
|
||||
- Name: `WOODPECKER_EXTENSIONS_ALLOWED_HOSTS`
|
||||
- Default: `external`
|
||||
|
||||
Comma-separated list of hosts that are allowed to be contacted by extensions. Possible values are `loopback`, `private`, `external`, `*` or CIDR list.
|
||||
|
||||
---
|
||||
|
||||
### FORGE_TIMEOUT
|
||||
|
||||
- Name: `WOODPECKER_FORGE_TIMEOUT`
|
||||
|
||||
@@ -4,9 +4,17 @@ To enhance the usability of Woodpecker and meet evolving security standards, occ
|
||||
|
||||
## `next`
|
||||
|
||||
### User-facing migrations
|
||||
|
||||
- (Kubernetes) Deprecated `step` label on pod in favor of new namespaced label `woodpecker-ci.org/step`. The `step` label will be removed in a future update.
|
||||
- deprecated `CI_COMMIT_AUTHOR_AVATAR` and `CI_PREV_COMMIT_AUTHOR_AVATAR` env vars in favor of `CI_PIPELINE_AVATAR` and `CI_PREV_PIPELINE_AVATAR`
|
||||
|
||||
### Admin-facing migrations
|
||||
|
||||
#### Extensions
|
||||
|
||||
Extension HTTP calls (as of now the configuration extension) will by default only be allowed to contact external hosts. Set `WOODPECKER_EXTENSIONS_ALLOWED_HOSTS` accordingly to allow additional hosts as needed.
|
||||
|
||||
## 3.0.0
|
||||
|
||||
### User-facing migrations
|
||||
|
||||
Reference in New Issue
Block a user