mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-08-10 02:41:14 +00:00
fix(compose-doctor): recognize Docker socket proxy topologies (#1791)
* fix(compose-doctor): recognize Docker socket proxy topologies Classify dedicated socket proxies separately from direct docker.sock mounts so Doctor no longer recommends adopting a proxy the stack already uses. Closes #1790. * fix(compose-doctor): widen socket proxy detection and flag writable proxy sockets Close the remaining gaps in socket proxy topology handling: a service that points at a proxy through a tcp:// endpoint on its command line (how Traefik and friends do it) now gets the client note, proxy API group flags are read for any truthy value rather than a literal 1, and underscore or dot separated proxy names are recognized. Two cases that previously slipped through now surface: a service classified as a proxy purely by name or image but mounting docker.sock read-write is reported as high, and a proxy on the implicit default network or on a network the rendered model does not describe counts as non-internal. A direct socket mount alongside an existing proxy now names that proxy in its fix. * fix(compose-doctor): require corroboration before a service name classifies a socket proxy A service name is free text the author controls, so on its own it could move a writable docker.sock mount out of the high direct-mount finding. A known proxy image is an artifact identity and still stands alone; a proxy-shaped name now counts only alongside an observable fact, a read-only socket or a scoped API group key. * fix(compose-doctor): tighten socket-proxy detection against live upstream behavior Require proxy API flags to be exactly 1 (matching tecnativa and linuxserver images), count only those enabled flags when classifying a proxy, extract tcp hosts from DOCKER_HOST instead of treating key presence as a proxy client, and correlate each client note to one proxy instance by both name and shared network. Soften the published-port finding so it claims reachability rather than Docker API exposure for unrelated ports.
This commit is contained in:
@@ -163,6 +163,28 @@ describe('PreflightPanel', () => {
|
||||
expect(screen.queryByTestId('preflight-ack-btn-healthcheck-inherited-web')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders socket-proxy client findings as Notes without acknowledgement', async () => {
|
||||
vi.mocked(apiFetch).mockResolvedValue(jsonRes(report({
|
||||
status: 'pass',
|
||||
activeStatus: 'pass',
|
||||
activeCount: 0,
|
||||
findings: [{
|
||||
ruleId: 'docker-socket-proxy-client',
|
||||
severity: 'info',
|
||||
title: 'Docker API access routed through socket proxy',
|
||||
message: 'Service "app" does not mount docker.sock directly and appears to use a Docker socket proxy instead.',
|
||||
service: 'app',
|
||||
}],
|
||||
})));
|
||||
render(<PreflightPanel stackName="web" canEdit />);
|
||||
const status = await screen.findByTestId('preflight-status');
|
||||
expect(status).toHaveAttribute('data-status', 'pass');
|
||||
expect(status).toHaveTextContent(/all clear/i);
|
||||
expect(screen.getByTestId('preflight-notes-section')).toHaveTextContent(/Docker API access routed through socket proxy/i);
|
||||
expect(screen.queryByTestId('preflight-ack-btn-docker-socket-proxy-client-app')).not.toBeInTheDocument();
|
||||
expect(status).not.toHaveTextContent(/info/i);
|
||||
});
|
||||
|
||||
it('excludes notes from the graded summary line when issue findings remain', async () => {
|
||||
vi.mocked(apiFetch).mockResolvedValue(jsonRes(report({
|
||||
status: 'warning',
|
||||
|
||||
@@ -2,7 +2,10 @@
|
||||
* Informational Compose Doctor notes (excluded from All Clear, severity
|
||||
* summary, and dismiss fingerprint). Keep in sync with backend PREFLIGHT_NOTE_RULE_IDS.
|
||||
*/
|
||||
const PREFLIGHT_NOTE_RULE_IDS = new Set(['healthcheck-inherited']);
|
||||
const PREFLIGHT_NOTE_RULE_IDS = new Set([
|
||||
'healthcheck-inherited',
|
||||
'docker-socket-proxy-client',
|
||||
]);
|
||||
|
||||
export function isPreflightNoteFinding(ruleId: string | undefined): boolean {
|
||||
return !!ruleId && PREFLIGHT_NOTE_RULE_IDS.has(ruleId);
|
||||
|
||||
Reference in New Issue
Block a user