mirror of
https://github.com/tiennm99/ccs.git
synced 2026-10-06 08:13:49 +00:00
fix(cliproxy): mask control panel login key (#1617)
This commit is contained in:
1 parent
4283c4665c
commit
bb7c3a4037
3 files changed
+22
-16
No files matched your search
@@ -1,12 +1,12 @@
|
||||
/**
|
||||
* Tests for printControlPanelAccess: the Control Panel (API Management Center)
|
||||
* URL + login-key surface shown by `ccs cliproxy status` / `start`.
|
||||
* URL + masked login-key hint shown by `ccs cliproxy status` / `start`.
|
||||
*
|
||||
* Why this matters:
|
||||
* - The Control Panel login screen only asks for a "Management Key" with no
|
||||
* hint. Users who don't know the default (`ccs`) cannot get in. This surface
|
||||
* is the fix, so it must print the panel URL on the active port and the
|
||||
* EFFECTIVE key (default `ccs`, or the user's custom management_secret).
|
||||
* - Routine lifecycle output is commonly pasted into logs and support tickets,
|
||||
* so it must not disclose the raw management key. The helper should print
|
||||
* the panel URL, a masked key for orientation, and the explicit command users
|
||||
* can run when they intentionally need the full key.
|
||||
*/
|
||||
import * as fs from 'fs';
|
||||
import * as os from 'os';
|
||||
@@ -56,12 +56,14 @@ describe('printControlPanelAccess', () => {
|
||||
}
|
||||
});
|
||||
|
||||
it('prints the panel URL on the given port and the default key (ccs)', () => {
|
||||
it('prints the panel URL on the given port and masks the default key', () => {
|
||||
printControlPanelAccess(8317);
|
||||
const out = lines.join('\n');
|
||||
expect(out).toContain('http://127.0.0.1:8317/management.html');
|
||||
expect(out).toContain('Panel login key:');
|
||||
expect(out).toContain('ccs');
|
||||
expect(out).toContain('Panel login key: ****');
|
||||
expect(out).toContain('ccs tokens --show');
|
||||
expect(out).not.toContain('Panel login key: ccs');
|
||||
});
|
||||
|
||||
it('uses the active port in the URL', () => {
|
||||
@@ -69,7 +71,7 @@ describe('printControlPanelAccess', () => {
|
||||
expect(lines.join('\n')).toContain('http://127.0.0.1:9000/management.html');
|
||||
});
|
||||
|
||||
it('prints a custom management_secret when configured', () => {
|
||||
it('masks a custom management_secret when configured', () => {
|
||||
mutateConfig((config) => {
|
||||
if (!config.cliproxy) {
|
||||
config.cliproxy = {};
|
||||
@@ -84,6 +86,8 @@ describe('printControlPanelAccess', () => {
|
||||
printControlPanelAccess(8317);
|
||||
const out = lines.join('\n');
|
||||
expect(out).toContain('Panel login key:');
|
||||
expect(out).toContain('my-custom-key');
|
||||
expect(out).toContain('my-c...-key');
|
||||
expect(out).toContain('ccs tokens --show');
|
||||
expect(out).not.toContain('my-custom-key');
|
||||
});
|
||||
});
|
||||
@@ -91,7 +91,7 @@ export async function showHelp(): Promise<void> {
|
||||
['restart', 'Restart CLIProxy instance'],
|
||||
[
|
||||
'status [--verbose]',
|
||||
'Show CLIProxy status + Control Panel URL and login key (--verbose adds uptime)',
|
||||
'Show CLIProxy status + Control Panel URL and masked login key (--verbose adds uptime)',
|
||||
],
|
||||
['stop', 'Stop running CLIProxy instance'],
|
||||
['doctor | diag', 'Quota diagnostics and shared project detection'],
|
||||
|
||||
@@ -12,22 +12,24 @@ import { initUI, header, color, dim, ok, warn, info } from '../../utils/ui';
|
||||
import { getProxyStatus, startProxy, stopProxy } from '../../cliproxy/services';
|
||||
import { detectRunningProxy } from '../../cliproxy/proxy/proxy-detector';
|
||||
import { resolveLifecyclePort } from '../../cliproxy/config/port-manager';
|
||||
import { getEffectiveManagementSecret } from '../../cliproxy/auth/auth-token-manager';
|
||||
import { getEffectiveManagementSecret, maskToken } from '../../cliproxy/auth/auth-token-manager';
|
||||
|
||||
/**
|
||||
* Print how to reach the local CLIProxy Control Panel (a.k.a. API Management
|
||||
* Center) and the key needed to log in.
|
||||
* Center) without exposing the management secret in routine output.
|
||||
*
|
||||
* The panel is served by CLIProxy at `/management.html` on the proxy port and
|
||||
* its login is gated by the management secret (default `ccs`). The login screen
|
||||
* only asks for a "Management Key" with no hint, so users frequently cannot get
|
||||
* in. Surfacing the URL + resolved key here removes that guesswork.
|
||||
* its login is gated by the management secret (default `ccs`). Keep the resolved
|
||||
* key masked here because `start` and `status` output is commonly shared in
|
||||
* support tickets and logs. Users can explicitly reveal tokens with
|
||||
* `ccs tokens --show` when they need the raw value.
|
||||
*/
|
||||
export function printControlPanelAccess(port: number): void {
|
||||
const secret = getEffectiveManagementSecret();
|
||||
console.log('');
|
||||
console.log(` Control Panel: http://127.0.0.1:${port}/management.html`);
|
||||
console.log(` Panel login key: ${secret}`);
|
||||
console.log(` Panel login key: ${maskToken(secret)}`);
|
||||
console.log(dim(' To show the full key: ccs tokens --show'));
|
||||
}
|
||||
|
||||
export async function handleStart(verbose = false): Promise<void> {
|
||||
|
||||
Reference in new issue
Block a user