forked from mirrors/kingfisher
preparing for v1.99.0
This commit is contained in:
parent
d88e19e0e1
commit
aca11be36d
4 changed files with 473 additions and 41 deletions
|
|
@ -425,11 +425,31 @@ kingfisher scan ./my-project \
|
|||
### Project configuration file (`kingfisher.yaml`)
|
||||
|
||||
Most `kingfisher scan` flags can be set as project defaults via a
|
||||
`kingfisher.yaml` file in the repo root (or any ancestor directory). CLI
|
||||
flags always win; config values fill in defaults. Lists are concatenated.
|
||||
`kingfisher.yaml` file. CLI flags always win; config values fill in
|
||||
defaults. Lists are concatenated.
|
||||
|
||||
The config file is **never auto-discovered** — pass `--config FILE`
|
||||
explicitly or it is not loaded.
|
||||
|
||||
**Step 1 — generate the config from your existing CLI command** (don't
|
||||
write the YAML by hand):
|
||||
|
||||
```bash
|
||||
kingfisher config init \
|
||||
--confidence high \
|
||||
--redact \
|
||||
--exclude vendor/ \
|
||||
--exclude '**/node_modules/**' \
|
||||
--format sarif \
|
||||
--output ./kingfisher.sarif \
|
||||
--alert-webhook https://hooks.slack.com/services/T0/B0/AAA \
|
||||
> kingfisher.yaml
|
||||
```
|
||||
|
||||
The resulting `kingfisher.yaml`:
|
||||
|
||||
```yaml
|
||||
# kingfisher.yaml
|
||||
# kingfisher.yaml — generated by `kingfisher config init`.
|
||||
scan:
|
||||
confidence: high
|
||||
redact: true
|
||||
|
|
@ -443,21 +463,19 @@ filters:
|
|||
alerts:
|
||||
webhooks:
|
||||
- url: https://hooks.slack.com/services/T0/B0/AAA
|
||||
format: slack
|
||||
```
|
||||
|
||||
**Step 2 — run the scan, passing the config explicitly:**
|
||||
|
||||
```bash
|
||||
kingfisher scan . # auto-discovers ./kingfisher.yaml
|
||||
kingfisher scan . --config /etc/kf.yaml # explicit path
|
||||
kingfisher scan . --config ./kingfisher.yaml
|
||||
```
|
||||
|
||||
Don't write the YAML by hand. If you already have a long `kingfisher scan`
|
||||
command, run the same flags under `kingfisher config init` to generate it:
|
||||
You can override any config value on the CLI for a single run:
|
||||
|
||||
```bash
|
||||
kingfisher config init \
|
||||
--confidence high --redact --exclude vendor/ --format sarif \
|
||||
> kingfisher.yaml
|
||||
kingfisher scan . --config ./kingfisher.yaml --confidence low
|
||||
# scan.confidence: high in YAML → CLI flag wins, runs at low confidence
|
||||
```
|
||||
|
||||
See [`docs/CONFIG.md`](../usage/configuration.md) for the full schema and precedence rules.
|
||||
|
|
@ -728,6 +746,60 @@ kingfisher scan https://github.com/org/repo.git --repo-artifacts
|
|||
KF_GITHUB_TOKEN="ghp_…" kingfisher scan https://github.com/org/private_repo.git --repo-artifacts
|
||||
```
|
||||
|
||||
### Scan a GitHub Enterprise / self-hosted GitHub instance
|
||||
|
||||
For GitHub Enterprise Server (GHES) or any self-hosted GitHub install, you
|
||||
need two flags:
|
||||
|
||||
- `--github-api-url <URL>` — points the **enumeration / clone** flow at the
|
||||
custom API root (typically `https://ghe.example.com/api/v3/`).
|
||||
- `--endpoint github=<URL>` — points the **token validation / revocation**
|
||||
flow at the same instance, so any GitHub PATs Kingfisher discovers in the
|
||||
scanned source are checked against your GHE rather than `api.github.com`.
|
||||
|
||||
```bash
|
||||
# 1. Scan every org repo on GHE and validate discovered tokens against the same instance
|
||||
KF_GITHUB_TOKEN="ghp_…" kingfisher scan github \
|
||||
--organization my-org \
|
||||
--github-api-url https://ghe.corp.example.com/api/v3/ \
|
||||
--endpoint github=https://ghe.corp.example.com
|
||||
|
||||
# 2. Scan a single GHE repo by URL (positional target)
|
||||
KF_GITHUB_TOKEN="ghp_…" kingfisher scan https://ghe.corp.example.com/org/repo.git \
|
||||
--endpoint github=https://ghe.corp.example.com
|
||||
|
||||
# 3. Scan ALL orgs on a GHE instance (requires non-default --github-api-url)
|
||||
KF_GITHUB_TOKEN="ghp_…" kingfisher scan github \
|
||||
--all-orgs \
|
||||
--github-api-url https://ghe.corp.example.com/api/v3/ \
|
||||
--endpoint github=https://ghe.corp.example.com
|
||||
|
||||
# 4. GHE on a private network — add --allow-internal-ips so the validator
|
||||
# can reach RFC1918 / loopback hosts (SSRF guard is on by default).
|
||||
KF_GITHUB_TOKEN="ghp_…" kingfisher scan github \
|
||||
--organization my-org \
|
||||
--github-api-url https://ghe.internal/api/v3/ \
|
||||
--endpoint github=https://ghe.internal \
|
||||
--allow-internal-ips
|
||||
|
||||
# 5. Validate a single PAT against GHE without scanning anything
|
||||
kingfisher validate --rule github \
|
||||
--endpoint github=https://ghe.corp.example.com \
|
||||
"ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||
|
||||
# 6. Revoke (delete) a confirmed-leaked PAT against GHE
|
||||
kingfisher revoke --rule github \
|
||||
--endpoint github=https://ghe.corp.example.com \
|
||||
"ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||
```
|
||||
|
||||
> **Why two URLs?** `--github-api-url` is the GHE *cloning* root that
|
||||
> Kingfisher walks to enumerate orgs, repos, and contributors.
|
||||
> `--endpoint github=…` is the *validator* root used to live-check
|
||||
> discovered tokens. They are usually the same host, but they're separate
|
||||
> flags because some deployments front-load auth (an SSO portal for repo
|
||||
> access vs. a direct API endpoint for token validation).
|
||||
|
||||
---
|
||||
|
||||
## GitLab
|
||||
|
|
@ -788,6 +860,99 @@ kingfisher scan https://gitlab.com/group/project.git --repo-artifacts
|
|||
KF_GITLAB_TOKEN="glpat-…" kingfisher scan https://gitlab.com/group/private_project.git --repo-artifacts
|
||||
```
|
||||
|
||||
### Scan a self-hosted (Omnibus / Cloud Native) GitLab instance
|
||||
|
||||
For GitLab self-hosted (Omnibus, Helm, or Cloud Native), pair the
|
||||
enumeration flag with a matching validation endpoint, just like with GHE:
|
||||
|
||||
- `--gitlab-api-url <URL>` — points the **enumeration / clone** flow at
|
||||
the custom GitLab root (typically `https://gitlab.example.com/`).
|
||||
- `--endpoint gitlab=<URL>` — points the **token validation / revocation**
|
||||
flow at the same instance, so any GitLab PATs found in the scanned
|
||||
source are checked against your self-hosted GitLab rather than
|
||||
`gitlab.com`.
|
||||
|
||||
```bash
|
||||
# 1. Scan a self-hosted group and validate discovered tokens against the same instance
|
||||
KF_GITLAB_TOKEN="glpat-…" kingfisher scan gitlab \
|
||||
--group my-group \
|
||||
--include-subgroups \
|
||||
--gitlab-api-url https://gitlab.corp.example.com/ \
|
||||
--endpoint gitlab=https://gitlab.corp.example.com
|
||||
|
||||
# 2. Scan a single self-hosted GitLab project by URL
|
||||
KF_GITLAB_TOKEN="glpat-…" kingfisher scan https://gitlab.corp.example.com/group/project.git \
|
||||
--endpoint gitlab=https://gitlab.corp.example.com
|
||||
|
||||
# 3. Scan ALL groups on a self-hosted GitLab (requires non-default --gitlab-api-url)
|
||||
KF_GITLAB_TOKEN="glpat-…" kingfisher scan gitlab \
|
||||
--all-groups \
|
||||
--gitlab-api-url https://gitlab.corp.example.com/ \
|
||||
--endpoint gitlab=https://gitlab.corp.example.com
|
||||
|
||||
# 4. Self-hosted GitLab on a private network — add --allow-internal-ips so
|
||||
# the validator can reach RFC1918 / loopback hosts.
|
||||
KF_GITLAB_TOKEN="glpat-…" kingfisher scan gitlab \
|
||||
--group my-group \
|
||||
--gitlab-api-url https://gitlab.internal/ \
|
||||
--endpoint gitlab=https://gitlab.internal \
|
||||
--allow-internal-ips
|
||||
|
||||
# 5. Validate a single PAT against self-hosted GitLab without scanning anything
|
||||
kingfisher validate --rule gitlab \
|
||||
--endpoint gitlab=https://gitlab.corp.example.com \
|
||||
"glpat-xxxxxxxxxxxxxxxxxxxx"
|
||||
|
||||
# 6. Revoke (delete) a confirmed-leaked PAT against self-hosted GitLab
|
||||
kingfisher revoke --rule gitlab \
|
||||
--endpoint gitlab=https://gitlab.corp.example.com \
|
||||
"glpat-xxxxxxxxxxxxxxxxxxxx"
|
||||
```
|
||||
|
||||
### Many endpoints at once: `--endpoint-config`
|
||||
|
||||
If you maintain a fleet of self-hosted instances (GHE, self-hosted GitLab,
|
||||
Gitea, Jira DC, Confluence, Artifactory), put them in a single YAML file
|
||||
and reference it instead of repeating `--endpoint` on every command:
|
||||
|
||||
```yaml
|
||||
# kingfisher-endpoints.yml
|
||||
endpoints:
|
||||
github: https://ghe.corp.example.com
|
||||
gitlab: https://gitlab.corp.example.com
|
||||
gitea: https://gitea.corp.example.com
|
||||
jira: https://jira.corp.example.com
|
||||
confluence: https://wiki.corp.example.com
|
||||
artifactory: http://artifactory.internal:8081
|
||||
```
|
||||
|
||||
```bash
|
||||
KF_GITHUB_TOKEN="ghp_…" KF_GITLAB_TOKEN="glpat-…" kingfisher scan github \
|
||||
--organization my-org \
|
||||
--github-api-url https://ghe.corp.example.com/api/v3/ \
|
||||
--endpoint-config ./kingfisher-endpoints.yml \
|
||||
--allow-internal-ips
|
||||
```
|
||||
|
||||
### Tip: bake the endpoints into `kingfisher.yaml`
|
||||
|
||||
Once you've worked out the right flags, capture them as project defaults
|
||||
so every scan uses the same config:
|
||||
|
||||
```bash
|
||||
kingfisher config init \
|
||||
--github-api-url https://ghe.corp.example.com/api/v3/ \
|
||||
--gitlab-api-url https://gitlab.corp.example.com/ \
|
||||
--endpoint github=https://ghe.corp.example.com \
|
||||
--endpoint gitlab=https://gitlab.corp.example.com \
|
||||
--allow-internal-ips \
|
||||
> kingfisher.yaml
|
||||
|
||||
# Then every scan inherits the same self-hosted defaults:
|
||||
KF_GITHUB_TOKEN="ghp_…" kingfisher scan github --organization my-org \
|
||||
--config ./kingfisher.yaml
|
||||
```
|
||||
|
||||
### List GitLab repositories
|
||||
|
||||
```bash
|
||||
|
|
|
|||
|
|
@ -219,8 +219,9 @@ KF_GITHUB_TOKEN="ghp_…" kingfisher scan https://github.com/org/private_repo.gi
|
|||
For GitHub Enterprise Server (GHES) or any self-hosted GitHub install, you
|
||||
need two flags:
|
||||
|
||||
- `--github-api-url <URL>` — points the **enumeration / clone** flow at the
|
||||
custom API root (typically `https://ghe.example.com/api/v3/`).
|
||||
- `--api-url <URL>` (on `kingfisher scan github`) — points the
|
||||
**enumeration / clone** flow at the custom API root (typically
|
||||
`https://ghe.example.com/api/v3/`).
|
||||
- `--endpoint github=<URL>` — points the **token validation / revocation**
|
||||
flow at the same instance, so any GitHub PATs Kingfisher discovers in the
|
||||
scanned source are checked against your GHE rather than `api.github.com`.
|
||||
|
|
@ -229,43 +230,43 @@ need two flags:
|
|||
# 1. Scan every org repo on GHE and validate discovered tokens against the same instance
|
||||
KF_GITHUB_TOKEN="ghp_…" kingfisher scan github \
|
||||
--organization my-org \
|
||||
--github-api-url https://ghe.corp.example.com/api/v3/ \
|
||||
--api-url https://ghe.corp.example.com/api/v3/ \
|
||||
--endpoint github=https://ghe.corp.example.com
|
||||
|
||||
# 2. Scan a single GHE repo by URL (positional target)
|
||||
KF_GITHUB_TOKEN="ghp_…" kingfisher scan https://ghe.corp.example.com/org/repo.git \
|
||||
--endpoint github=https://ghe.corp.example.com
|
||||
|
||||
# 3. Scan ALL orgs on a GHE instance (requires non-default --github-api-url)
|
||||
# 3. Scan ALL orgs on a GHE instance (requires non-default --api-url)
|
||||
KF_GITHUB_TOKEN="ghp_…" kingfisher scan github \
|
||||
--all-orgs \
|
||||
--github-api-url https://ghe.corp.example.com/api/v3/ \
|
||||
--api-url https://ghe.corp.example.com/api/v3/ \
|
||||
--endpoint github=https://ghe.corp.example.com
|
||||
|
||||
# 4. GHE on a private network — add --allow-internal-ips so the validator
|
||||
# can reach RFC1918 / loopback hosts (SSRF guard is on by default).
|
||||
KF_GITHUB_TOKEN="ghp_…" kingfisher scan github \
|
||||
--organization my-org \
|
||||
--github-api-url https://ghe.internal/api/v3/ \
|
||||
--api-url https://ghe.internal/api/v3/ \
|
||||
--endpoint github=https://ghe.internal \
|
||||
--allow-internal-ips
|
||||
|
||||
# 5. Validate a single PAT against GHE without scanning anything
|
||||
kingfisher validate --rule github \
|
||||
--endpoint github=https://ghe.corp.example.com \
|
||||
"ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||
"<your-github-pat>"
|
||||
|
||||
# 6. Revoke (delete) a confirmed-leaked PAT against GHE
|
||||
kingfisher revoke --rule github \
|
||||
--endpoint github=https://ghe.corp.example.com \
|
||||
"ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||
"<your-github-pat>"
|
||||
```
|
||||
|
||||
`--github-api-url` is the GHE *cloning* root that Kingfisher walks to
|
||||
enumerate orgs, repos, and contributors. `--endpoint github=…` is the
|
||||
*validator* root used to live-check discovered tokens. They are usually the
|
||||
same host, but they're separate flags because some deployments front-load
|
||||
auth (an SSO portal for repo access vs. a direct API endpoint for token
|
||||
`--api-url` is the GHE *cloning* root that Kingfisher walks to enumerate
|
||||
orgs, repos, and contributors. `--endpoint github=…` is the *validator*
|
||||
root used to live-check discovered tokens. They are usually the same host,
|
||||
but they're separate flags because some deployments front-load auth (an
|
||||
SSO portal for repo access vs. a direct API endpoint for token
|
||||
validation).
|
||||
|
||||
## GitLab
|
||||
|
|
@ -343,8 +344,9 @@ KF_GITLAB_TOKEN="glpat-…" kingfisher scan https://gitlab.com/group/private_pro
|
|||
For GitLab self-hosted (Omnibus, Helm, or Cloud Native), pair the
|
||||
enumeration flag with a matching validation endpoint:
|
||||
|
||||
- `--gitlab-api-url <URL>` — points the **enumeration / clone** flow at
|
||||
the custom GitLab root (typically `https://gitlab.example.com/`).
|
||||
- `--api-url <URL>` (on `kingfisher scan gitlab`) — points the
|
||||
**enumeration / clone** flow at the custom GitLab root (typically
|
||||
`https://gitlab.example.com/`).
|
||||
- `--endpoint gitlab=<URL>` — points the **token validation / revocation**
|
||||
flow at the same instance, so any GitLab PATs found in the scanned
|
||||
source are checked against your self-hosted GitLab rather than
|
||||
|
|
@ -355,36 +357,36 @@ enumeration flag with a matching validation endpoint:
|
|||
KF_GITLAB_TOKEN="glpat-…" kingfisher scan gitlab \
|
||||
--group my-group \
|
||||
--include-subgroups \
|
||||
--gitlab-api-url https://gitlab.corp.example.com/ \
|
||||
--api-url https://gitlab.corp.example.com/ \
|
||||
--endpoint gitlab=https://gitlab.corp.example.com
|
||||
|
||||
# 2. Scan a single self-hosted GitLab project by URL
|
||||
KF_GITLAB_TOKEN="glpat-…" kingfisher scan https://gitlab.corp.example.com/group/project.git \
|
||||
--endpoint gitlab=https://gitlab.corp.example.com
|
||||
|
||||
# 3. Scan ALL groups on a self-hosted GitLab (requires non-default --gitlab-api-url)
|
||||
# 3. Scan ALL groups on a self-hosted GitLab (requires non-default --api-url)
|
||||
KF_GITLAB_TOKEN="glpat-…" kingfisher scan gitlab \
|
||||
--all-groups \
|
||||
--gitlab-api-url https://gitlab.corp.example.com/ \
|
||||
--api-url https://gitlab.corp.example.com/ \
|
||||
--endpoint gitlab=https://gitlab.corp.example.com
|
||||
|
||||
# 4. Self-hosted GitLab on a private network — add --allow-internal-ips so
|
||||
# the validator can reach RFC1918 / loopback hosts.
|
||||
KF_GITLAB_TOKEN="glpat-…" kingfisher scan gitlab \
|
||||
--group my-group \
|
||||
--gitlab-api-url https://gitlab.internal/ \
|
||||
--api-url https://gitlab.internal/ \
|
||||
--endpoint gitlab=https://gitlab.internal \
|
||||
--allow-internal-ips
|
||||
|
||||
# 5. Validate a single PAT against self-hosted GitLab without scanning anything
|
||||
kingfisher validate --rule gitlab \
|
||||
--endpoint gitlab=https://gitlab.corp.example.com \
|
||||
"glpat-xxxxxxxxxxxxxxxxxxxx"
|
||||
"<your-gitlab-pat>"
|
||||
|
||||
# 6. Revoke (delete) a confirmed-leaked PAT against self-hosted GitLab
|
||||
kingfisher revoke --rule gitlab \
|
||||
--endpoint gitlab=https://gitlab.corp.example.com \
|
||||
"glpat-xxxxxxxxxxxxxxxxxxxx"
|
||||
"<your-gitlab-pat>"
|
||||
```
|
||||
|
||||
### Many endpoints at once: `--endpoint-config`
|
||||
|
|
@ -407,7 +409,7 @@ endpoints:
|
|||
```bash
|
||||
KF_GITHUB_TOKEN="ghp_…" KF_GITLAB_TOKEN="glpat-…" kingfisher scan github \
|
||||
--organization my-org \
|
||||
--github-api-url https://ghe.corp.example.com/api/v3/ \
|
||||
--api-url https://ghe.corp.example.com/api/v3/ \
|
||||
--endpoint-config ./kingfisher-endpoints.yml \
|
||||
--allow-internal-ips
|
||||
```
|
||||
|
|
@ -716,10 +718,10 @@ To use basic authentication instead, also set `KF_CONFLUENCE_USER` to your Confl
|
|||
### Scan Slack messages matching a search query
|
||||
|
||||
```bash
|
||||
KF_SLACK_TOKEN="xoxp-1234..." kingfisher scan slack "from:username has:link" \
|
||||
KF_SLACK_TOKEN="<your-slack-user-token>" kingfisher scan slack "from:username has:link" \
|
||||
--max-results 1000
|
||||
|
||||
KF_SLACK_TOKEN="xoxp-1234..." kingfisher scan slack "akia" \
|
||||
KF_SLACK_TOKEN="<your-slack-user-token>" kingfisher scan slack "akia" \
|
||||
--max-results 1000
|
||||
```
|
||||
|
||||
|
|
@ -805,7 +807,7 @@ The token is sent as the `X-Api-Key` header. Either `KF_POSTMAN_TOKEN` or `POSTM
|
|||
|
||||
> Top-level `kingfisher scan --postman-*` flags remain accepted as hidden aliases for backward compatibility, but new usage should prefer the `kingfisher scan postman` subcommand shown above.
|
||||
|
||||
**Out of scope:** Postman Vault secrets are client-side and not reachable via the API. The Postman API Network does not expose a search endpoint; supply specific public-workspace IDs via `--postman-workspace` to scan public surfaces.
|
||||
**Out of scope:** Postman Vault secrets are client-side and not reachable via the API. The Postman API Network does not expose a search endpoint; supply specific public-workspace IDs via `kingfisher scan postman --workspace` to scan public surfaces.
|
||||
|
||||
## Environment Variables
|
||||
|
||||
|
|
|
|||
|
|
@ -211,6 +211,61 @@ kingfisher scan https://github.com/org/repo.git --repo-artifacts
|
|||
KF_GITHUB_TOKEN="ghp_…" kingfisher scan https://github.com/org/private_repo.git --repo-artifacts
|
||||
```
|
||||
|
||||
### Scan a GitHub Enterprise / self-hosted GitHub instance
|
||||
|
||||
For GitHub Enterprise Server (GHES) or any self-hosted GitHub install, you
|
||||
need two flags:
|
||||
|
||||
- `--api-url <URL>` (on `kingfisher scan github`) — points the
|
||||
**enumeration / clone** flow at the custom API root (typically
|
||||
`https://ghe.example.com/api/v3/`).
|
||||
- `--endpoint github=<URL>` — points the **token validation / revocation**
|
||||
flow at the same instance, so any GitHub PATs Kingfisher discovers in the
|
||||
scanned source are checked against your GHE rather than `api.github.com`.
|
||||
|
||||
```bash
|
||||
# 1. Scan every org repo on GHE and validate discovered tokens against the same instance
|
||||
KF_GITHUB_TOKEN="ghp_…" kingfisher scan github \
|
||||
--organization my-org \
|
||||
--api-url https://ghe.corp.example.com/api/v3/ \
|
||||
--endpoint github=https://ghe.corp.example.com
|
||||
|
||||
# 2. Scan a single GHE repo by URL (positional target)
|
||||
KF_GITHUB_TOKEN="ghp_…" kingfisher scan https://ghe.corp.example.com/org/repo.git \
|
||||
--endpoint github=https://ghe.corp.example.com
|
||||
|
||||
# 3. Scan ALL orgs on a GHE instance (requires non-default --api-url)
|
||||
KF_GITHUB_TOKEN="ghp_…" kingfisher scan github \
|
||||
--all-orgs \
|
||||
--api-url https://ghe.corp.example.com/api/v3/ \
|
||||
--endpoint github=https://ghe.corp.example.com
|
||||
|
||||
# 4. GHE on a private network — add --allow-internal-ips so the validator
|
||||
# can reach RFC1918 / loopback hosts (SSRF guard is on by default).
|
||||
KF_GITHUB_TOKEN="ghp_…" kingfisher scan github \
|
||||
--organization my-org \
|
||||
--api-url https://ghe.internal/api/v3/ \
|
||||
--endpoint github=https://ghe.internal \
|
||||
--allow-internal-ips
|
||||
|
||||
# 5. Validate a single PAT against GHE without scanning anything
|
||||
kingfisher validate --rule github \
|
||||
--endpoint github=https://ghe.corp.example.com \
|
||||
"<your-github-pat>"
|
||||
|
||||
# 6. Revoke (delete) a confirmed-leaked PAT against GHE
|
||||
kingfisher revoke --rule github \
|
||||
--endpoint github=https://ghe.corp.example.com \
|
||||
"<your-github-pat>"
|
||||
```
|
||||
|
||||
`--api-url` is the GHE *cloning* root that Kingfisher walks to enumerate
|
||||
orgs, repos, and contributors. `--endpoint github=…` is the *validator*
|
||||
root used to live-check discovered tokens. They are usually the same host,
|
||||
but they're separate flags because some deployments front-load auth (an
|
||||
SSO portal for repo access vs. a direct API endpoint for token
|
||||
validation).
|
||||
|
||||
## GitLab
|
||||
|
||||
### Scan GitLab group (requires `KF_GITLAB_TOKEN`)
|
||||
|
|
@ -281,6 +336,100 @@ kingfisher scan https://gitlab.com/group/project.git --repo-artifacts
|
|||
KF_GITLAB_TOKEN="glpat-…" kingfisher scan https://gitlab.com/group/private_project.git --repo-artifacts
|
||||
```
|
||||
|
||||
### Scan a self-hosted (Omnibus / Cloud Native) GitLab instance
|
||||
|
||||
For GitLab self-hosted (Omnibus, Helm, or Cloud Native), pair the
|
||||
enumeration flag with a matching validation endpoint:
|
||||
|
||||
- `--api-url <URL>` (on `kingfisher scan gitlab`) — points the
|
||||
**enumeration / clone** flow at the custom GitLab root (typically
|
||||
`https://gitlab.example.com/`).
|
||||
- `--endpoint gitlab=<URL>` — points the **token validation / revocation**
|
||||
flow at the same instance, so any GitLab PATs found in the scanned
|
||||
source are checked against your self-hosted GitLab rather than
|
||||
`gitlab.com`.
|
||||
|
||||
```bash
|
||||
# 1. Scan a self-hosted group and validate discovered tokens against the same instance
|
||||
KF_GITLAB_TOKEN="glpat-…" kingfisher scan gitlab \
|
||||
--group my-group \
|
||||
--include-subgroups \
|
||||
--api-url https://gitlab.corp.example.com/ \
|
||||
--endpoint gitlab=https://gitlab.corp.example.com
|
||||
|
||||
# 2. Scan a single self-hosted GitLab project by URL
|
||||
KF_GITLAB_TOKEN="glpat-…" kingfisher scan https://gitlab.corp.example.com/group/project.git \
|
||||
--endpoint gitlab=https://gitlab.corp.example.com
|
||||
|
||||
# 3. Scan ALL groups on a self-hosted GitLab (requires non-default --api-url)
|
||||
KF_GITLAB_TOKEN="glpat-…" kingfisher scan gitlab \
|
||||
--all-groups \
|
||||
--api-url https://gitlab.corp.example.com/ \
|
||||
--endpoint gitlab=https://gitlab.corp.example.com
|
||||
|
||||
# 4. Self-hosted GitLab on a private network — add --allow-internal-ips so
|
||||
# the validator can reach RFC1918 / loopback hosts.
|
||||
KF_GITLAB_TOKEN="glpat-…" kingfisher scan gitlab \
|
||||
--group my-group \
|
||||
--api-url https://gitlab.internal/ \
|
||||
--endpoint gitlab=https://gitlab.internal \
|
||||
--allow-internal-ips
|
||||
|
||||
# 5. Validate a single PAT against self-hosted GitLab without scanning anything
|
||||
kingfisher validate --rule gitlab \
|
||||
--endpoint gitlab=https://gitlab.corp.example.com \
|
||||
"<your-gitlab-pat>"
|
||||
|
||||
# 6. Revoke (delete) a confirmed-leaked PAT against self-hosted GitLab
|
||||
kingfisher revoke --rule gitlab \
|
||||
--endpoint gitlab=https://gitlab.corp.example.com \
|
||||
"<your-gitlab-pat>"
|
||||
```
|
||||
|
||||
### Many endpoints at once: `--endpoint-config`
|
||||
|
||||
If you maintain a fleet of self-hosted instances (GHE, self-hosted GitLab,
|
||||
Gitea, Jira DC, Confluence, Artifactory), put them in a single YAML file
|
||||
and reference it instead of repeating `--endpoint` on every command:
|
||||
|
||||
```yaml
|
||||
# kingfisher-endpoints.yml
|
||||
endpoints:
|
||||
github: https://ghe.corp.example.com
|
||||
gitlab: https://gitlab.corp.example.com
|
||||
gitea: https://gitea.corp.example.com
|
||||
jira: https://jira.corp.example.com
|
||||
confluence: https://wiki.corp.example.com
|
||||
artifactory: http://artifactory.internal:8081
|
||||
```
|
||||
|
||||
```bash
|
||||
KF_GITHUB_TOKEN="ghp_…" KF_GITLAB_TOKEN="glpat-…" kingfisher scan github \
|
||||
--organization my-org \
|
||||
--api-url https://ghe.corp.example.com/api/v3/ \
|
||||
--endpoint-config ./kingfisher-endpoints.yml \
|
||||
--allow-internal-ips
|
||||
```
|
||||
|
||||
### Tip: bake the endpoints into `kingfisher.yaml`
|
||||
|
||||
Once you've worked out the right flags, capture them as project defaults
|
||||
so every scan uses the same config:
|
||||
|
||||
```bash
|
||||
kingfisher config init \
|
||||
--github-api-url https://ghe.corp.example.com/api/v3/ \
|
||||
--gitlab-api-url https://gitlab.corp.example.com/ \
|
||||
--endpoint github=https://ghe.corp.example.com \
|
||||
--endpoint gitlab=https://gitlab.corp.example.com \
|
||||
--allow-internal-ips \
|
||||
> kingfisher.yaml
|
||||
|
||||
# Then every scan inherits the same self-hosted defaults:
|
||||
KF_GITHUB_TOKEN="ghp_…" kingfisher scan github --organization my-org \
|
||||
--config ./kingfisher.yaml
|
||||
```
|
||||
|
||||
### List GitLab repositories
|
||||
|
||||
```bash
|
||||
|
|
@ -566,10 +715,10 @@ To use basic authentication instead, also set `KF_CONFLUENCE_USER` to your Confl
|
|||
### Scan Slack messages matching a search query
|
||||
|
||||
```bash
|
||||
KF_SLACK_TOKEN="xoxp-1234..." kingfisher scan slack "from:username has:link" \
|
||||
KF_SLACK_TOKEN="<your-slack-user-token>" kingfisher scan slack "from:username has:link" \
|
||||
--max-results 1000
|
||||
|
||||
KF_SLACK_TOKEN="xoxp-1234..." kingfisher scan slack "akia" \
|
||||
KF_SLACK_TOKEN="<your-slack-user-token>" kingfisher scan slack "akia" \
|
||||
--max-results 1000
|
||||
```
|
||||
|
||||
|
|
@ -655,7 +804,7 @@ The token is sent as the `X-Api-Key` header. Either `KF_POSTMAN_TOKEN` or `POSTM
|
|||
|
||||
> Top-level `kingfisher scan --postman-*` flags remain accepted as hidden aliases for backward compatibility, but new usage should prefer the `kingfisher scan postman` subcommand shown above.
|
||||
|
||||
**Out of scope:** Postman Vault secrets are client-side and not reachable via the API. The Postman API Network does not expose a search endpoint; supply specific public-workspace IDs via `--postman-workspace` to scan public surfaces.
|
||||
**Out of scope:** Postman Vault secrets are client-side and not reachable via the API. The Postman API Network does not expose a search endpoint; supply specific public-workspace IDs via `kingfisher scan postman --workspace` to scan public surfaces.
|
||||
|
||||
## Environment Variables
|
||||
|
||||
|
|
|
|||
120
src/main.rs
120
src/main.rs
|
|
@ -346,6 +346,24 @@ fn apply_config(
|
|||
}
|
||||
}
|
||||
|
||||
/// Like `config_wins`, but also inspects a nested provider subcommand's
|
||||
/// `--api-url` flag. The github/gitlab provider subcommands carry their
|
||||
/// own `api_url` arg (id `api_url`) that gets propagated to
|
||||
/// `scan_args.input_specifier_args.{github,gitlab}_api_url` in
|
||||
/// `into_operation()`. If that nested flag was user-supplied, the config
|
||||
/// must NOT clobber it.
|
||||
fn api_url_config_wins(
|
||||
matches: Option<&clap::ArgMatches>,
|
||||
outer_id: &str,
|
||||
subcommand: &str,
|
||||
) -> bool {
|
||||
if !config_wins(matches, outer_id) {
|
||||
return false;
|
||||
}
|
||||
let sub = matches.and_then(|m| m.subcommand_matches(subcommand));
|
||||
config_wins(sub, "api_url")
|
||||
}
|
||||
|
||||
// ---------- Filters: existing v1 list-typed merges ----------------------
|
||||
scan_args.skip_word.extend(cfg.filters.skip_words.iter().cloned());
|
||||
scan_args.skip_regex.extend(cfg.filters.skip_regex.iter().cloned());
|
||||
|
|
@ -631,14 +649,21 @@ fn apply_config(
|
|||
// field. parse_str() already validated this — `unwrap_or_default()`
|
||||
// would mask a real config bug, so we re-parse and *fail loud* if the
|
||||
// string somehow does not parse here.
|
||||
//
|
||||
// The provider subcommands (`scan github`, `scan gitlab`) expose their
|
||||
// own `--api-url` flag whose value is propagated into the same runtime
|
||||
// field by `into_operation()`. `api_url_config_wins` checks both the
|
||||
// outer hidden alias and the nested subcommand flag so an explicit
|
||||
// `kingfisher scan github --api-url ...` is never overridden by the
|
||||
// config file.
|
||||
if let Some(u) = &cfg.git.github_api_url
|
||||
&& config_wins(scan_matches, "github_api_url")
|
||||
&& api_url_config_wins(scan_matches, "github_api_url", "github")
|
||||
&& let Ok(parsed) = url::Url::parse(u)
|
||||
{
|
||||
scan_args.input_specifier_args.github_api_url = parsed;
|
||||
}
|
||||
if let Some(u) = &cfg.git.gitlab_api_url
|
||||
&& config_wins(scan_matches, "gitlab_api_url")
|
||||
&& api_url_config_wins(scan_matches, "gitlab_api_url", "gitlab")
|
||||
&& let Ok(parsed) = url::Url::parse(u)
|
||||
{
|
||||
scan_args.input_specifier_args.gitlab_api_url = parsed;
|
||||
|
|
@ -2268,4 +2293,95 @@ global:
|
|||
assert!(global_args.allow_internal_ips);
|
||||
assert_eq!(global_args.endpoint.len(), 1);
|
||||
}
|
||||
|
||||
/// Regression test: an explicit `--api-url` on the `scan github`
|
||||
/// subcommand must beat `git.github_api_url` from the config file. The
|
||||
/// flag lives on `GithubScanArgs` (id `api_url`), not on the outer scan
|
||||
/// command — checking only the outer matches misses it and the config
|
||||
/// silently overrode the CLI value.
|
||||
#[test]
|
||||
fn github_subcommand_api_url_beats_config() {
|
||||
let yaml = r#"
|
||||
git:
|
||||
github_api_url: https://ghe-from-config.example.com/api/v3/
|
||||
"#;
|
||||
let cfg = parse_str(yaml).unwrap();
|
||||
let (args, matches) = parse(&[
|
||||
"kingfisher",
|
||||
"scan",
|
||||
"github",
|
||||
"--organization",
|
||||
"my-org",
|
||||
"--api-url",
|
||||
"https://ghe-from-cli.example.com/api/v3/",
|
||||
]);
|
||||
let mut global_args = args.global_args.clone();
|
||||
let mut scan_args = into_scan(args);
|
||||
super::apply_config(
|
||||
&mut scan_args,
|
||||
&mut global_args,
|
||||
&cfg,
|
||||
matches.subcommand_matches("scan"),
|
||||
);
|
||||
assert_eq!(
|
||||
scan_args.input_specifier_args.github_api_url.as_str(),
|
||||
"https://ghe-from-cli.example.com/api/v3/",
|
||||
);
|
||||
}
|
||||
|
||||
/// And the inverse: when the user did NOT pass `--api-url` at all,
|
||||
/// `git.github_api_url` from the config should still win over the
|
||||
/// built-in default `https://api.github.com/`.
|
||||
#[test]
|
||||
fn github_config_wins_when_subcommand_api_url_default() {
|
||||
let yaml = r#"
|
||||
git:
|
||||
github_api_url: https://ghe-from-config.example.com/api/v3/
|
||||
"#;
|
||||
let cfg = parse_str(yaml).unwrap();
|
||||
let (args, matches) = parse(&["kingfisher", "scan", "github", "--organization", "my-org"]);
|
||||
let mut global_args = args.global_args.clone();
|
||||
let mut scan_args = into_scan(args);
|
||||
super::apply_config(
|
||||
&mut scan_args,
|
||||
&mut global_args,
|
||||
&cfg,
|
||||
matches.subcommand_matches("scan"),
|
||||
);
|
||||
assert_eq!(
|
||||
scan_args.input_specifier_args.github_api_url.as_str(),
|
||||
"https://ghe-from-config.example.com/api/v3/",
|
||||
);
|
||||
}
|
||||
|
||||
/// Same precedence story for `scan gitlab --api-url`.
|
||||
#[test]
|
||||
fn gitlab_subcommand_api_url_beats_config() {
|
||||
let yaml = r#"
|
||||
git:
|
||||
gitlab_api_url: https://gitlab-from-config.example.com/
|
||||
"#;
|
||||
let cfg = parse_str(yaml).unwrap();
|
||||
let (args, matches) = parse(&[
|
||||
"kingfisher",
|
||||
"scan",
|
||||
"gitlab",
|
||||
"--group",
|
||||
"my-group",
|
||||
"--api-url",
|
||||
"https://gitlab-from-cli.example.com/",
|
||||
]);
|
||||
let mut global_args = args.global_args.clone();
|
||||
let mut scan_args = into_scan(args);
|
||||
super::apply_config(
|
||||
&mut scan_args,
|
||||
&mut global_args,
|
||||
&cfg,
|
||||
matches.subcommand_matches("scan"),
|
||||
);
|
||||
assert_eq!(
|
||||
scan_args.input_specifier_args.gitlab_api_url.as_str(),
|
||||
"https://gitlab-from-cli.example.com/",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue