## Summary
Currently when we refresh sessions we always use the global IdP
credentials. This PR updates the identity manager to use route settings
when defined.
To do this a new `idp_id` field is added to the session stored in the
databroker.
## Related issues
-
[ENG-2595](https://linear.app/pomerium/issue/ENG-2595/refresh-using-custom-idp-uses-wrong-credentials)
- https://github.com/pomerium/pomerium/issues/4759
## Checklist
- [x] reference any related issues
- [x] updated unit tests
- [x] add appropriate label (`enhancement`, `bug`, `breaking`,
`dependencies`, `ci`)
- [x] ready for review
## Summary
Explicitly set the `concurrency` option for envoy to match `GOMAXPROCS`.
In v1.25 the default behavior of `GOMAXPROCS` will change:
> On Linux, the runtime considers the CPU bandwidth limit of the cgroup
containing the process, if any. If the CPU bandwidth limit is lower than
the number of logical CPUs available, GOMAXPROCS will default to the
lower limit. In container runtime systems like Kubernetes, cgroup CPU
bandwidth limits generally correspond to the “CPU limit” option.
However we use
[github.com/uber-go/automaxprocs](https://github.com/uber-go/automaxprocs)
so we already have this behavior.
This behavior is enabled by default but can be disabled by setting the
runtime flag `set_envoy_concurrency_to_go_max_procs` to false.
This change will be backported to v0.30 and v0.29, though with v0.29 the
default will be off so as not to change the current behavior.
I also looked into the `--cpuset-threads` option, but it only applies
when cpusets are used explicitly and most containers use
`cpu.cfs_quota_us` or `cpu.max` instead.
## Related issues
-
[ENG-2549](https://linear.app/pomerium/issue/ENG-2549/core-set-cpuset-threads-envoy-option-to-detected-cpu-quota)
## User Explanation
<!-- How would you explain this change to the user? If this
change doesn't create any user-facing changes, you can leave
this blank. If filled out, add the `docs` label -->
## Checklist
- [x] reference any related issues
- [ ] updated unit tests
- [ ] add appropriate label (`enhancement`, `bug`, `breaking`,
`dependencies`, `ci`)
- [x] ready for review
## Summary
Remove Authorization header for the MCP server upstream.
## Related issues
Fix https://github.com/pomerium/pomerium/issues/5718
## User Explanation
<!-- How would you explain this change to the user? If this
change doesn't create any user-facing changes, you can leave
this blank. If filled out, add the `docs` label -->
## Checklist
- [x] reference any related issues
- [x] updated unit tests
- [x] add appropriate label (`enhancement`, `bug`, `breaking`,
`dependencies`, `ci`)
- [x] ready for review
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
<details>
<summary>Dependabot commands and options</summary>
<br />
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions
</details>
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Denis Mishin <dmishin@pomerium.com>
## Summary
There are 3 indices in the postgres storage driver that are redundant.
This PR drops them.
## Related issues
-
[ENG-2560](https://linear.app/pomerium/issue/ENG-2560/request-remove-redundant-database-indexes)
## Checklist
- [x] reference any related issues
- [ ] updated unit tests
- [x] add appropriate label (`enhancement`, `bug`, `breaking`,
`dependencies`, `ci`)
- [x] ready for review
OpenSSH requires a trailing newline for private keys, which is easy to
accidentally omit when configuring private keys as strings inline via
copy/paste. This adds the missing newline if it is not present. Private
keys read from files still require the trailing newline.
## Summary
Adds headers evaluator tests for MCP routes.
## Related issues
<!-- For example...
- #159
-->
## User Explanation
<!-- How would you explain this change to the user? If this
change doesn't create any user-facing changes, you can leave
this blank. If filled out, add the `docs` label -->
## Checklist
- [ ] reference any related issues
- [ ] updated unit tests
- [ ] add appropriate label (`enhancement`, `bug`, `breaking`,
`dependencies`, `ci`)
- [ ] ready for review
## Summary
Adds `POST /.pomerium/mcp/routes/disconnect` that allows an MCP client
application to request upstream OAuth2 tokens to be purged, so that a
user may get a new ones with possibly different scopes.
## Related issues
Fix
https://linear.app/pomerium/issue/ENG-2545/mcp-user-should-be-able-to-purge-their-upstream-oauth2-token
## User Explanation
<!-- How would you explain this change to the user? If this
change doesn't create any user-facing changes, you can leave
this blank. If filled out, add the `docs` label -->
## Checklist
- [x] reference any related issues
- [x] updated unit tests
- [x] add appropriate label (`enhancement`, `bug`, `breaking`,
`dependencies`, `ci`)
- [x] ready for review
## Summary
Individual MCP method calls may be denied (i.e. via `mcp_tool`
criterion) and Pomerium has to respond with MCP protocol error, which is
JSON-RPC error message, rather then with HTTP level error which seems to
break some MCP clients.
## Related issues
Fix
https://linear.app/pomerium/issue/ENG-2521/pomerium-does-not-return-an-mcp-error-when-a-tool-call-is-unauthorized
## User Explanation
<!-- How would you explain this change to the user? If this
change doesn't create any user-facing changes, you can leave
this blank. If filled out, add the `docs` label -->
## Checklist
- [x] reference any related issues
- [x] updated unit tests
- [x] add appropriate label (`enhancement`, `bug`, `breaking`,
`dependencies`, `ci`)
- [x] ready for review
## Summary
Change MCP PPL reasons to be more human-readable when used in the denial
matches.
## Related issues
See
https://github.com/pomerium/pomerium/issues/5673#issuecomment-3036879247
## User Explanation
<!-- How would you explain this change to the user? If this
change doesn't create any user-facing changes, you can leave
this blank. If filled out, add the `docs` label -->
## Checklist
- [x] reference any related issues
- [x] updated unit tests
- [x] add appropriate label (`enhancement`, `bug`, `breaking`,
`dependencies`, `ci`)
- [x] ready for review
## Summary
## Related issues
Fix
https://linear.app/pomerium/issue/ENG-2543/mcp-tool-ignore-non-jsonrpc-calls
## User Explanation
<!-- How would you explain this change to the user? If this
change doesn't create any user-facing changes, you can leave
this blank. If filled out, add the `docs` label -->
## Checklist
- [x] reference any related issues
- [x] updated unit tests
- [x] add appropriate label (`enhancement`, `bug`, `breaking`,
`dependencies`, `ci`)
- [x] ready for review
Adds a new runtime flag `ssh_allow_direct_tcpip` (default false) which
enables the "jump-host mode". This is disabled by default since we are
missing related config options/policy criteria.
## Summary
Adds an option to log request body for protocols that perform request
inspection, such as MCP.
## Related issues
Fix
https://linear.app/pomerium/issue/ENG-2544/authorize-request-body-logging
## User Explanation
<!-- How would you explain this change to the user? If this
change doesn't create any user-facing changes, you can leave
this blank. If filled out, add the `docs` label -->
## Checklist
- [ ] reference any related issues
- [ ] updated unit tests
- [ ] add appropriate label (`enhancement`, `bug`, `breaking`,
`dependencies`, `ci`)
- [ ] ready for review
Use RawStdEncoding to compute the base64 fingerprint as part of SSH
session IDs. This is mostly just so that we can use the go
`ssh.FingerprintSHA256` function in tests (which uses RawStdEncoding) to
assert on session ID strings
Set 'fail-fast: false' so that if one of these jobs fails it will not
cancel the other. These have have unfortunately become very flaky, and
the current behavior is not helpful.
Remove 'go-version' from the matrix as it is currently unused and it
does not match the actual Go version in use.
Add a bare-bones integration test using the testenv framework to verify
the basics of SSH proxying: configure an upstream ssh server and connect
to it through Pomerium.
Add an additional method to the ssh.Evaluator interface for invalidating
cached databroker records. Invalidating the global cache is not
sufficient, because there may be sync queriers as well.
Make sure to invalidate the User record (in addition to the Session
record) during the login flow.
Re-evaluate ssh authorization decision on a fixed interval, or whenever
the config changes. If access is no longer allowed, log a new 'authorize
check' message and disconnect.
Refactor the ssh.StreamManager initialization so that its lifecycle
matches the Authorize lifecycle.
Implement the pkg/ssh.AuthInterface. Add logic for converting from the
ssh stream state to an evaluator request, and for interpreting the
results of policy evaluation. Refactor some of the existing authorize
logic to make it easier to reuse.
## Summary
This should fix some test flakes. If (*Pomerium).Start() fails, we
should not attempt to call (*Pomerium).Shutdown().
## Related issues
<!-- For example...
- #159
-->
## User Explanation
<!-- How would you explain this change to the user? If this
change doesn't create any user-facing changes, you can leave
this blank. If filled out, add the `docs` label -->
## Checklist
- [ ] reference any related issues
- [ ] updated unit tests
- [ ] add appropriate label (`enhancement`, `bug`, `breaking`,
`dependencies`, `ci`)
- [ ] ready for review
## Summary
This implements the StreamManagement API defined at
https://github.com/pomerium/envoy-custom/blob/main/api/extensions/filters/network/ssh/ssh.proto#L46-L60.
Policy evaluation and authorization logic is stubbed out here, and
implemented in https://github.com/pomerium/pomerium/pull/5665.
## Related issues
<!-- For example...
- #159
-->
## User Explanation
<!-- How would you explain this change to the user? If this
change doesn't create any user-facing changes, you can leave
this blank. If filled out, add the `docs` label -->
## Checklist
- [ ] reference any related issues
- [ ] updated unit tests
- [ ] add appropriate label (`enhancement`, `bug`, `breaking`,
`dependencies`, `ci`)
- [ ] ready for review
This adds a build tag and debug variable that can be used to launch an
external envoy binary and skip embedding one, for debugging purposes.
Example usage:
```
go build -tags=debug_local_envoy -ldflags -X github.com/pomerium/pomerium/pkg/envoy.DebugLocalEnvoyPath=/path/to/envoy
```
or in launch.json
```jsonc
{
"version": "0.2.0",
"configurations": [
{
"name": "debug pomerium (external envoy)",
"type": "go",
"request": "launch",
"mode": "debug",
"program": "${workspaceRoot}/cmd/pomerium",
// ...
"buildFlags": [
"-tags=debug_local_envoy",
"-ldflags",
"-X github.com/pomerium/pomerium/pkg/envoy.DebugLocalEnvoyPath=/path/to/envoy"
],
}
]
}
```
## Summary
Adds the envoy listener config logic for ssh.
## Related issues
<!-- For example...
- #159
-->
## User Explanation
<!-- How would you explain this change to the user? If this
change doesn't create any user-facing changes, you can leave
this blank. If filled out, add the `docs` label -->
## Checklist
- [ ] reference any related issues
- [ ] updated unit tests
- [ ] add appropriate label (`enhancement`, `bug`, `breaking`,
`dependencies`, `ci`)
- [ ] ready for review
Refactor the testenv mock IdP implementation to split off the core
functionality from the testenv environment setup. Add a Start() method
to run the mock IdP as an httptest server, tied to a test lifecycle.
This allows the mock IdP to be used also in tests that do not start a
full Pomerium instance.
Add the new types scenarios.SSH for configuring Pomerium with the global
SSH config options, and upstreams.SSHUpstream for configuring an
individual SSH upstream/route.
Add barebones device auth flow support to the testenv mock IdP, for use
with the SSH auth flow.
---------
Co-authored-by: Joe Kralicky <joekralicky@gmail.com>
## Summary
The `pomerium_pgxpool_constructing_connections` had a `_milliseconds`
suffix due to a bug in the upstream package.
## Related issues
Ref: https://github.com/exaring/otelpgx/issues/61
## User Explanation
<!-- How would you explain this change to the user? If this
change doesn't create any user-facing changes, you can leave
this blank. If filled out, add the `docs` label -->
## Checklist
- [ ] reference any related issues
- [ ] updated unit tests
- [ ] add appropriate label (`enhancement`, `bug`, `breaking`,
`dependencies`, `ci`)
- [ ] ready for review
Add five new PPL criteria for use with SSH, matching username and public
key. Username can be matched against a String Matcher, user's email
address, or a custom claim from the IdP claims. Public key can be
matched against a list of keys or a trusted CA.
## Summary
Adds support for extending authorization log with Model Context Protocol
details.
i.e.
```json
{
"level": "info",
"server-name": "all",
"service": "authorize",
"mcp-method": "tools/call",
"mcp-tool": "describe_table",
"mcp-tool-parameters": { "table_name": "Categories" },
"allow": true,
"allow-why-true": ["email-ok", "mcp-tool-ok"],
"deny": false,
"deny-why-false": [],
"time": "2025-06-24T17:40:41-04:00",
"message": "authorize check"
}
```
## Related issues
Fixes
https://linear.app/pomerium/issue/ENG-2393/mcp-authorize-each-incoming-request-to-an-mcp-route
## User Explanation
<!-- How would you explain this change to the user? If this
change doesn't create any user-facing changes, you can leave
this blank. If filled out, add the `docs` label -->
## Checklist
- [x] reference any related issues
- [x] updated unit tests
- [x] add appropriate label (`enhancement`, `bug`, `breaking`,
`dependencies`, `ci`)
- [x] ready for review
## Summary
This adds the necessary logic needed for device auth flow in ssh. The
code is not used currently; will follow up with testenv updates that can
let us test this with the mock idp.
## Related issues
<!-- For example...
- #159
-->
## User Explanation
<!-- How would you explain this change to the user? If this
change doesn't create any user-facing changes, you can leave
this blank. If filled out, add the `docs` label -->
## Checklist
- [ ] reference any related issues
- [ ] updated unit tests
- [ ] add appropriate label (`enhancement`, `bug`, `breaking`,
`dependencies`, `ci`)
- [ ] ready for review
## Summary
Adds `mcp_tool` PPL criterion, that matches MCP tool names like
```yaml
- from: https://db.localhost.pomerium.io
to: http://localhost:3000/mcp
policy:
allow:
and:
- email:
in: ["user@pomerium.com"]
- mcp_tool:
in: ["list_tables", "read_table", "search_records"]
mcp: {}
```
## Related issues
Fix
https://linear.app/pomerium/issue/ENG-2393/mcp-authorize-each-incoming-request-to-an-mcp-route
## User Explanation
<!-- How would you explain this change to the user? If this
change doesn't create any user-facing changes, you can leave
this blank. If filled out, add the `docs` label -->
## Checklist
- [x] reference any related issues
- [x] updated unit tests
- [x] add appropriate label (`enhancement`, `bug`, `breaking`,
`dependencies`, `ci`)
- [x] ready for review