mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-07-15 12:30:32 -07:00
Move keychain fallback to keychain service (#22332)
This commit is contained in:
@@ -14,6 +14,9 @@ import {
|
||||
KEYCHAIN_TEST_PREFIX,
|
||||
} from './keychainTypes.js';
|
||||
import { isRecord } from '../utils/markdownUtils.js';
|
||||
import { FileKeychain } from './fileKeychain.js';
|
||||
|
||||
export const FORCE_FILE_STORAGE_ENV_VAR = 'GEMINI_FORCE_FILE_STORAGE';
|
||||
|
||||
/**
|
||||
* Service for interacting with OS-level secure storage (e.g. keytar).
|
||||
@@ -31,6 +34,14 @@ export class KeychainService {
|
||||
return (await this.getKeychain()) !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the service is using the encrypted file fallback backend.
|
||||
*/
|
||||
async isUsingFileFallback(): Promise<boolean> {
|
||||
const keychain = await this.getKeychain();
|
||||
return keychain instanceof FileKeychain;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a secret for the given account.
|
||||
* @throws Error if the keychain is unavailable.
|
||||
@@ -85,26 +96,40 @@ export class KeychainService {
|
||||
// High-level orchestration of the loading and testing cycle.
|
||||
private async initializeKeychain(): Promise<Keychain | null> {
|
||||
let resultKeychain: Keychain | null = null;
|
||||
const forceFileStorage = process.env[FORCE_FILE_STORAGE_ENV_VAR] === 'true';
|
||||
|
||||
try {
|
||||
const keychainModule = await this.loadKeychainModule();
|
||||
if (keychainModule) {
|
||||
if (await this.isKeychainFunctional(keychainModule)) {
|
||||
resultKeychain = keychainModule;
|
||||
} else {
|
||||
debugLogger.log('Keychain functional verification failed');
|
||||
if (!forceFileStorage) {
|
||||
try {
|
||||
const keychainModule = await this.loadKeychainModule();
|
||||
if (keychainModule) {
|
||||
if (await this.isKeychainFunctional(keychainModule)) {
|
||||
resultKeychain = keychainModule;
|
||||
} else {
|
||||
debugLogger.log('Keychain functional verification failed');
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
// Avoid logging full error objects to prevent PII exposure.
|
||||
const message = error instanceof Error ? error.message : String(error);
|
||||
debugLogger.log(
|
||||
'Keychain initialization encountered an error:',
|
||||
message,
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
// Avoid logging full error objects to prevent PII exposure.
|
||||
const message = error instanceof Error ? error.message : String(error);
|
||||
debugLogger.log('Keychain initialization encountered an error:', message);
|
||||
}
|
||||
|
||||
coreEvents.emitTelemetryKeychainAvailability(
|
||||
new KeychainAvailabilityEvent(resultKeychain !== null),
|
||||
new KeychainAvailabilityEvent(
|
||||
resultKeychain !== null && !forceFileStorage,
|
||||
),
|
||||
);
|
||||
|
||||
// Fallback to FileKeychain if native keychain is unavailable or file storage is forced
|
||||
if (!resultKeychain) {
|
||||
resultKeychain = new FileKeychain();
|
||||
debugLogger.log('Using FileKeychain fallback for secure storage.');
|
||||
}
|
||||
|
||||
return resultKeychain;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user