Commit Graph
6 Commits
Author SHA1 Message Date
9444049d60 feat: bring gitlab repositories to parity for git sync (#10938)
* feat: track and rotate gitlab git-sync repository tokens

* chore: point ee-repo-ref at the gitlab credential branch

* fix: strip server-owned credential status and correct expiry copy

* fix: gate credential maintenance on enterprise and alert on stalled renewal

* fix: alert on an auto-renewed token only once it has actually expired

* feat: receive gitlab push webhooks for instant git sync pull

* feat: open gitlab merge requests and post diff previews on them

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1xHmkxuxYb1GYvth1BS75

* fix: keep gitlab merge request previews out of the project's own pipeline

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1xHmkxuxYb1GYvth1BS75

* fix: bound the credential maintenance pass and gate the gitlab picker on a license

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1xHmkxuxYb1GYvth1BS75

* fix: create the gitlab picker's variable in the edited workspace

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1xHmkxuxYb1GYvth1BS75

* fix: make the gitlab picker's variable path collision-resistant

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1xHmkxuxYb1GYvth1BS75

* docs: state the gitlab scope and rotation facts the code relies on

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1xHmkxuxYb1GYvth1BS75

* fix: resolve the check marker's repository from its path, not a stored url

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1xHmkxuxYb1GYvth1BS75

* fix: refuse to finish a check whose repository has been repointed

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1xHmkxuxYb1GYvth1BS75

* fix: trust a check marker's captured url when it carries no identity

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1xHmkxuxYb1GYvth1BS75

* fix: recreate a missing webhook from credential maintenance

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1xHmkxuxYb1GYvth1BS75

* docs: state that relative-url gitlab installs are out of scope

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1xHmkxuxYb1GYvth1BS75

* fix: keep credential status out of exports and clear stale webhook warnings

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1xHmkxuxYb1GYvth1BS75

* fix: refuse an unprovable check and guard the picker on the stored repository

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1xHmkxuxYb1GYvth1BS75

* fix: re-check the picker's target path at the moment it is written

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1xHmkxuxYb1GYvth1BS75

* fix: snapshot the picker's inputs before it starts writing

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1xHmkxuxYb1GYvth1BS75

* docs: recommend a project access token per repository

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1xHmkxuxYb1GYvth1BS75

* [ee] feat: keep the git-sync credential in workspace settings

* [ee] fix: drop a removed repo's credential and honor the workspace override

* [ee] fix: resolve a fork's git credential from its whole ancestry

* [ee] refactor: reuse fork_ancestor_chain instead of a second ancestry walk

* [ee] fix: resolve an app installation from the whole ancestry, not the parent

* [ee] revert: keep the app installation fallback at one level

* fix: store the git credential only once the resource is saved

* fix: keep a repository's credential when it leaves git sync settings

* docs: cut the gitlab picker's token guidance down to what it needs

* feat: mark a repository whose credential windmill holds

* fix: ignore the managed-credential marker when the url carries a token

* docs: drop the picker's setup alert for a line by the token field

* feat: replace a repository's stored token from its resource

* fix: store a picked credential for its own workspace, before the resource

* refactor: key a stored git credential by its repository, not its resource

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1xHmkxuxYb1GYvth1BS75

* chore: refresh the sqlx cache for the repository-keyed credential queries

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1xHmkxuxYb1GYvth1BS75

* fix: gate the credential pass budget on the features that use it

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1xHmkxuxYb1GYvth1BS75

* fix: decide credential rotation ownership by repository, not resource path

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1xHmkxuxYb1GYvth1BS75

* refactor: renew only the credentials windmill holds, not tokens in a repo url

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1xHmkxuxYb1GYvth1BS75

* fix: authenticate the fork-branch poll and correct the renewal guidance

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1xHmkxuxYb1GYvth1BS75

* fix: do not claim a managed credential for a url the client cannot resolve

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1xHmkxuxYb1GYvth1BS75

* fix: define the credential facade for private builds without enterprise

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1xHmkxuxYb1GYvth1BS75

* fix: pin the listed token before the await and name the real renewal blocker

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1xHmkxuxYb1GYvth1BS75

* fix: pin the token the replace flow checked, and derive the scope test once

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1xHmkxuxYb1GYvth1BS75

* fix: classify the renewal state once so the card cannot contradict itself

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1xHmkxuxYb1GYvth1BS75

* refactor: ask only whether the token gets renewed, not why it does not

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1xHmkxuxYb1GYvth1BS75

* refactor: replace the managed-credential marker with a server answer

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1xHmkxuxYb1GYvth1BS75

* fix: read renewal from the credential and its origin, not a removed field

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1xHmkxuxYb1GYvth1BS75

* fix: read the provider for url-token repos, await the origin before defaulting, and visit unchecked repos last

The maintenance pass sorted repositories with no recorded check first on
the premise that they cost nothing, but a token-in-URL remote on a host
that is not GitLab is probed every pass and never records a check, so it
held the head of the list ahead of the tokens that expire. Such
repositories now sort last.

The card decided its delivery defaults before the origin lookup landed,
so a freshly picked GitLab repository never got webhook delivery; the two
lookups are awaited together. The resource editor offers to replace a
token only where it is held, not in a fork that borrows it, and the
replace flow refuses a URL it cannot parse instead of keying the token to
it. Attaching a stored credential to a commit-hash probe now requires
admin, matching the installation credential beside it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1xHmkxuxYb1GYvth1BS75

* docs: describe the gitlab listing token the way the picker and the setup guide do

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1xHmkxuxYb1GYvth1BS75

* refactor: a token in the repository url is a plain remote, not a tracked credential

Drops the status fingerprint that told one URL token from another, the
docs' promise that such a token's expiry is reported, and the test's
expectation that a URL-token repository declares a host.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1xHmkxuxYb1GYvth1BS75

* fix: the card reads the credential origin for managed controls and honours the licence for a borrowed token

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1xHmkxuxYb1GYvth1BS75

* chore: bump the ee ref

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1xHmkxuxYb1GYvth1BS75

* fix: hide a repository's credential line once nothing is held for the repository it names

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1xHmkxuxYb1GYvth1BS75

* docs: describe the exported credential status as it is

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1xHmkxuxYb1GYvth1BS75

* refactor: run the credential maintenance pass as its own task, without a budget

The pass ran inside the monitor's join, whose deadline cancels every
future in it, and a rotation cancelled between GitLab issuing a token and
Windmill storing it loses the token family. A wall-clock budget with a
least-recently-checked ordering kept it under the deadline. Spawning the
pass instead makes the deadline irrelevant, so the budget, the ordering
and the counter go; the advisory lock keeps a slow pass from overlapping
the next, as it already did.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1xHmkxuxYb1GYvth1BS75

* docs: say what detaching the maintenance pass buys, and what it does not

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1xHmkxuxYb1GYvth1BS75

* chore: run git sync on the hub script version that reads a stored credential

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1xHmkxuxYb1GYvth1BS75

* chore: run the deploy push and the connection test on the hub versions that read a stored credential

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1xHmkxuxYb1GYvth1BS75

* fix: keep App repositories and plain remotes out of the stored-credential paths

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1xHmkxuxYb1GYvth1BS75

* chore: host-neutral deploy preview wording, drop the project filter from the GitLab picker

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1xHmkxuxYb1GYvth1BS75

* chore: bump ee ref, rotation no longer retains a second connection per repository

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1xHmkxuxYb1GYvth1BS75

* chore: bump ee ref, the rotation write-back holds a single connection

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1xHmkxuxYb1GYvth1BS75

* chore: hold the credential maintenance lock in a transaction so a dead sweep releases it

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1xHmkxuxYb1GYvth1BS75

* docs: describe the credential-stored callback as it fires

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1xHmkxuxYb1GYvth1BS75

* fix: keep the credential maintenance lock past the pool's idle-in-transaction timeout

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C1xHmkxuxYb1GYvth1BS75

* chore: update ee-repo-ref to e092518ee60e33160fee9ae91a4d109566f7b0ee

This commit updates the EE repository reference after PR #771 was merged in windmill-ee-private.

Previous ee-repo-ref: 74481f7cc345757aebb2a8b04d3a22978328c348

New ee-repo-ref: e092518ee60e33160fee9ae91a4d109566f7b0ee

Automated by sync-ee-ref workflow.

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
2026-09-08 11:54:43 +02:00
Ruben FiszelandClaude Opus 4.8 fa7fbd348d fix(security): validate ansible git repository URLs before invoking git (#10759)
The Ansible executor passed the user-controlled git repository `url` (from
playbook YAML or a `git_repository` resource) straight into `git clone`,
`git ls-remote` and `git remote add` on the worker host. A URL that git parses
as an option — e.g. `--upload-pack=<cmd>` — turns `git ls-remote <url> HEAD`
into arbitrary command execution on the host, outside any job sandbox. Non-http
transports (`ext::`, `file://`, local paths) similarly run programs or read
host files.

Add `validate_git_repo_url` in windmill-common: reject a leading `-`, reject
remote-helper `::` syntax, and allow only the `http(s)`, `ssh`, `git` and
scp-like `[user@]host:path` transports. Also reject a `branch`/`commit` that
starts with `-`. Validation runs at every ansible entry point that spawns git,
covering both the inline-YAML and resource-provided URL paths.

CWE-88 (argument injection) / CWE-78. Reported by Nitin Gavhane.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-19 14:04:39 +02:00
Ruben FiszelandClaude Opus 4.8 ace7b68a28 fix: sanitize git credentials from ansible executor errors and logs (#9697)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 11:02:24 +02:00
2e430c4c0b feat: add GitHub Enterprise Server (GHES) support for GitHub App git sync (#8344)
* feat: add GitHub Enterprise Server (GHES) support for GitHub App git sync

Add a self-managed GitHub App mode alongside the existing managed
(stats.windmill.dev) mode, enabling git sync for GitHub Enterprise Server
and custom GitHub App installations.

Backend:
- Parameterize GitHub API URLs (no more hardcoded github.com)
- Add GITHUB_ENTERPRISE_APP_SETTING global setting
- Add OpenAPI specs for ghes_installation_callback and ghes_config endpoints

Frontend:
- Add instance settings UI for configuring self-managed GitHub Apps
  with setup instructions and validation
- GHES installation flow in gh_success page
- Dynamic installation URL based on GHES config
- Increase git sync test connection timeout to 10s
- Block "Review changes" save when settings are invalid

EE companion PR: windmill-labs/windmill-ee-private#<PR_NUMBER>

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: update ee-repo-ref to c74c86b78a66b976fd9968b21f77903723e668ec

This commit updates the EE repository reference after PR #459 was merged in windmill-ee-private.

Previous ee-repo-ref: 45e4550110799525b5502cf072c8af8132492638

New ee-repo-ref: c74c86b78a66b976fd9968b21f77903723e668ec

Automated by sync-ee-ref workflow.

* sqlx

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
Co-authored-by: Ruben Fiszel <ruben@windmill.dev>
2026-03-13 08:21:15 +00:00
Pyraandwindmill-internal-app[bot] fe56191422 feat(internal): runnable settings (#7298)
* rework everything again

Signed-off-by: pyranota <pyra@duck.com>

* updcate sqlx

Signed-off-by: pyranota <pyra@duck.com>

* update ref

Signed-off-by: pyranota <pyra@duck.com>

* fix things

Signed-off-by: pyranota <pyra@duck.com>

* fix function

Signed-off-by: pyranota <pyra@duck.com>

* final fixes

Signed-off-by: pyranota <pyra@duck.com>

* update sqlx

Signed-off-by: pyranota <pyra@duck.com>

* fix script creation

Signed-off-by: pyranota <pyra@duck.com>

* address todo

Signed-off-by: pyranota <pyra@duck.com>

* cleanup

Signed-off-by: pyranota <pyra@duck.com>

* remove dbg

Signed-off-by: pyranota <pyra@duck.com>

* cleanup

Signed-off-by: pyranota <pyra@duck.com>

* fix

Signed-off-by: pyranota <pyra@duck.com>

* fixups

Signed-off-by: pyranota <pyra@duck.com>

* fix cargo.toml

Signed-off-by: pyranota <pyra@duck.com>

* update ee repo

Signed-off-by: pyranota <pyra@duck.com>

* fix ci

Signed-off-by: pyranota <pyra@duck.com>

* nit

Signed-off-by: pyranota <pyra@duck.com>

* ref

Signed-off-by: pyranota <pyra@duck.com>

* fix

Signed-off-by: pyranota <pyra@duck.com>

* ee repo

Signed-off-by: pyranota <pyra@duck.com>

* sqlx

Signed-off-by: pyranota <pyra@duck.com>

* ee ref

Signed-off-by: pyranota <pyra@duck.com>

* remove dbg

Signed-off-by: pyranota <pyra@duck.com>

* sqlx

Signed-off-by: pyranota <pyra@duck.com>

* chore: update ee-repo-ref to 505eadbff32d102ea5245a2bef88ce6f1bb95395

This commit updates the EE repository reference after PR #348 was merged in windmill-ee-private.

Previous ee-repo-ref: 195243e56cc0eab55f8890fa57297206bfe2c18c

New ee-repo-ref: 505eadbff32d102ea5245a2bef88ce6f1bb95395

Automated by sync-ee-ref workflow.

* ci: force runnable settings

Signed-off-by: pyranota <pyra@duck.com>

---------

Signed-off-by: pyranota <pyra@duck.com>
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
2025-12-16 21:17:06 +00:00
wendrulandRuben Fiszel 32fae7a10c feat: ansible playbook execution git repo mode (repo viewer + UI utils) (#6831)
* Improve minio on flake.nix

* Add first asset parsing logic for ansible

* Correct html gt sign

* Decouple s3 file picker from drawer

* Factor duplicate code into snippet

* Update S3FilePickerInner to be compatible

* Fix pane shrinking issue

* Git repo viewer

* Change GitRepoViewer

* Endpoints for git repo visualizer

* Move git repo viewer to its own component

* Add button to populate git repo viewer

* Update parser yaml for new ansisble features (repo viewer)

* Reflect parser changes for ansible

* Add button to add the git repo mode of declaration for ansible

* Factor function

* Playbook + inventories into the drawer

* Add button to add inventories from s3

* Move tests to lib.rs

* Inventory loading from s3

* Move get github app token logic to be reused by ansible

* Update parser and ansible executor

* Use the correct path for inventories

* Add nushell to flake for wasm builds

* Add published parser

* Update hubPaths with clone and upload to s3

* Update ee-repo to the branch ref

* Fix npm run check

* Update cargo.lock

* Change labels on buttons

* Remove debug log

* Update ee-repo-ref

* Fix ee issues

* Update ee-repo ref

* Fix typo

* Fix ee

* Update ee-repo-ref

* Fix missing imports

* Unused var

* Fix typo

* Layout improvents

* Fix typos

* Remove unused function and log

---------

Co-authored-by: Ruben Fiszel <ruben@windmill.dev>
2025-10-16 09:08:18 +00:00