mirror of
https://github.com/tiennm99/ccs.git
synced 2026-10-13 14:15:56 +00:00
fix: disable docker legacy API key auth by default (#1355)
This commit is contained in:
1 parent
c21f589247
commit
ab379e9e13
2 files changed
+20
-5
No files matched your search
@@ -7,6 +7,7 @@ export const DOCKER_LEGACY_API_KEY = 'ccs-internal-managed';
|
|||||||
export const DEFAULT_DOCKER_LEGACY_KEY_GRACE_DAYS = 14;
|
export const DEFAULT_DOCKER_LEGACY_KEY_GRACE_DAYS = 14;
|
||||||
export const DOCKER_LEGACY_KEY_GRACE_ENV = 'CCS_DOCKER_LEGACY_KEY_GRACE_DAYS';
|
export const DOCKER_LEGACY_KEY_GRACE_ENV = 'CCS_DOCKER_LEGACY_KEY_GRACE_DAYS';
|
||||||
export const DOCKER_RESTORE_LEGACY_KEY_ENV = 'CCS_DOCKER_RESTORE_LEGACY_API_KEY';
|
export const DOCKER_RESTORE_LEGACY_KEY_ENV = 'CCS_DOCKER_RESTORE_LEGACY_API_KEY';
|
||||||
|
export const DOCKER_ENABLE_LEGACY_KEY_AUTH_ENV = 'CCS_DOCKER_ENABLE_LEGACY_KEY_AUTH';
|
||||||
|
|
||||||
const DAY_MS = 24 * 60 * 60 * 1000;
|
const DAY_MS = 24 * 60 * 60 * 1000;
|
||||||
const STATE_VERSION = 1;
|
const STATE_VERSION = 1;
|
||||||
@@ -67,6 +68,10 @@ export function shouldRestoreDockerLegacyApiKey(env = process.env): boolean {
|
|||||||
return env[DOCKER_RESTORE_LEGACY_KEY_ENV] === '1';
|
return env[DOCKER_RESTORE_LEGACY_KEY_ENV] === '1';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function shouldEnableDockerLegacyKeyAuth(env = process.env): boolean {
|
||||||
|
return env[DOCKER_ENABLE_LEGACY_KEY_AUTH_ENV] === '1';
|
||||||
|
}
|
||||||
|
|
||||||
export function readDockerBootstrapState(): DockerBootstrapStateReadResult {
|
export function readDockerBootstrapState(): DockerBootstrapStateReadResult {
|
||||||
const statePath = getDockerBootstrapStatePath();
|
const statePath = getDockerBootstrapStatePath();
|
||||||
if (!fs.existsSync(statePath)) {
|
if (!fs.existsSync(statePath)) {
|
||||||
@@ -135,6 +140,10 @@ export function isDockerLegacyKeyGraceActive(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function getActiveDockerLegacyApiKeys(now = new Date()): string[] {
|
export function getActiveDockerLegacyApiKeys(now = new Date()): string[] {
|
||||||
|
if (!shouldEnableDockerLegacyKeyAuth()) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
const { state } = readDockerBootstrapState();
|
const { state } = readDockerBootstrapState();
|
||||||
if (!isDockerLegacyKeyGraceActive(state, now)) {
|
if (!isDockerLegacyKeyGraceActive(state, now)) {
|
||||||
return [];
|
return [];
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import {
|
|||||||
const originalCcsHome = process.env.CCS_HOME;
|
const originalCcsHome = process.env.CCS_HOME;
|
||||||
const originalGraceDays = process.env.CCS_DOCKER_LEGACY_KEY_GRACE_DAYS;
|
const originalGraceDays = process.env.CCS_DOCKER_LEGACY_KEY_GRACE_DAYS;
|
||||||
const originalRestoreLegacyKey = process.env.CCS_DOCKER_RESTORE_LEGACY_API_KEY;
|
const originalRestoreLegacyKey = process.env.CCS_DOCKER_RESTORE_LEGACY_API_KEY;
|
||||||
|
const originalEnableLegacyKeyAuth = process.env.CCS_DOCKER_ENABLE_LEGACY_KEY_AUTH;
|
||||||
const tempDirs: string[] = [];
|
const tempDirs: string[] = [];
|
||||||
|
|
||||||
function useTempCcsHome(): string {
|
function useTempCcsHome(): string {
|
||||||
@@ -48,6 +49,11 @@ afterEach(() => {
|
|||||||
} else {
|
} else {
|
||||||
process.env.CCS_DOCKER_RESTORE_LEGACY_API_KEY = originalRestoreLegacyKey;
|
process.env.CCS_DOCKER_RESTORE_LEGACY_API_KEY = originalRestoreLegacyKey;
|
||||||
}
|
}
|
||||||
|
if (originalEnableLegacyKeyAuth === undefined) {
|
||||||
|
delete process.env.CCS_DOCKER_ENABLE_LEGACY_KEY_AUTH;
|
||||||
|
} else {
|
||||||
|
process.env.CCS_DOCKER_ENABLE_LEGACY_KEY_AUTH = originalEnableLegacyKeyAuth;
|
||||||
|
}
|
||||||
|
|
||||||
for (const dir of tempDirs.splice(0)) {
|
for (const dir of tempDirs.splice(0)) {
|
||||||
rmSync(dir, { recursive: true, force: true });
|
rmSync(dir, { recursive: true, force: true });
|
||||||
@@ -98,7 +104,7 @@ describe('docker bootstrap auth', () => {
|
|||||||
expect(readDockerBootstrapState().state?.legacyKeyGrace).toBeUndefined();
|
expect(readDockerBootstrapState().state?.legacyKeyGrace).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('preserves the legacy key during the default upgrade grace window', () => {
|
it('tracks legacy key grace but does not enable it in config by default', () => {
|
||||||
useTempCcsHome();
|
useTempCcsHome();
|
||||||
mutateConfig((config) => {
|
mutateConfig((config) => {
|
||||||
config.cliproxy.auth = {
|
config.cliproxy.auth = {
|
||||||
@@ -118,7 +124,7 @@ describe('docker bootstrap auth', () => {
|
|||||||
expect(state?.legacyKeyGrace?.legacyKey).toBe(CCS_INTERNAL_API_KEY);
|
expect(state?.legacyKeyGrace?.legacyKey).toBe(CCS_INTERNAL_API_KEY);
|
||||||
expect(state?.legacyKeyGrace?.replacementKey).toBe(config.cliproxy.auth?.api_key);
|
expect(state?.legacyKeyGrace?.replacementKey).toBe(config.cliproxy.auth?.api_key);
|
||||||
expect(content).toContain(`"${config.cliproxy.auth?.api_key}"`);
|
expect(content).toContain(`"${config.cliproxy.auth?.api_key}"`);
|
||||||
expect(content).toContain(`"${CCS_INTERNAL_API_KEY}"`);
|
expect(content).not.toContain(`"${CCS_INTERNAL_API_KEY}"`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('honors CCS_DOCKER_LEGACY_KEY_GRACE_DAYS for upgrade expiry', () => {
|
it('honors CCS_DOCKER_LEGACY_KEY_GRACE_DAYS for upgrade expiry', () => {
|
||||||
@@ -188,7 +194,7 @@ describe('docker bootstrap auth', () => {
|
|||||||
|
|
||||||
expect(changed).toBe(true);
|
expect(changed).toBe(true);
|
||||||
expect(content).toContain(`"${generatedKey}"`);
|
expect(content).toContain(`"${generatedKey}"`);
|
||||||
expect(content).toContain(`"${CCS_INTERNAL_API_KEY}"`);
|
expect(content).not.toContain(`"${CCS_INTERNAL_API_KEY}"`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('restores the legacy key after an earlier run wrote a no-grace marker', () => {
|
it('restores the legacy key after an earlier run wrote a no-grace marker', () => {
|
||||||
@@ -212,7 +218,7 @@ describe('docker bootstrap auth', () => {
|
|||||||
|
|
||||||
expect(changed).toBe(true);
|
expect(changed).toBe(true);
|
||||||
expect(content).toContain(`"${generatedKey}"`);
|
expect(content).toContain(`"${generatedKey}"`);
|
||||||
expect(content).toContain(`"${CCS_INTERNAL_API_KEY}"`);
|
expect(content).not.toContain(`"${CCS_INTERNAL_API_KEY}"`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('recovers safely from a corrupted marker file during broken-install recovery', () => {
|
it('recovers safely from a corrupted marker file during broken-install recovery', () => {
|
||||||
@@ -232,7 +238,7 @@ describe('docker bootstrap auth', () => {
|
|||||||
|
|
||||||
expect(getDockerBootstrapStatePath()).toContain(DOCKER_BOOTSTRAP_STATE_FILENAME);
|
expect(getDockerBootstrapStatePath()).toContain(DOCKER_BOOTSTRAP_STATE_FILENAME);
|
||||||
expect(readDockerBootstrapState().corrupted).toBe(false);
|
expect(readDockerBootstrapState().corrupted).toBe(false);
|
||||||
expect(content).toContain(`"${CCS_INTERNAL_API_KEY}"`);
|
expect(content).not.toContain(`"${CCS_INTERNAL_API_KEY}"`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('does not treat human custom keys as broken Docker-generated keys', () => {
|
it('does not treat human custom keys as broken Docker-generated keys', () => {
|
||||||
|
|||||||
Reference in new issue
Block a user