mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-18 01:00:39 -07:00
feat(auth): Add option for metadata server application default credentials without project override (#12948)
This commit is contained in:
@@ -68,18 +68,18 @@ describe('codeAssist', () => {
|
||||
expect(generator).toBeInstanceOf(MockedCodeAssistServer);
|
||||
});
|
||||
|
||||
it('should create a server for CLOUD_SHELL', async () => {
|
||||
it('should create a server for COMPUTE_ADC', async () => {
|
||||
mockedGetOauthClient.mockResolvedValue(mockAuthClient as never);
|
||||
mockedSetupUser.mockResolvedValue(mockUserData);
|
||||
|
||||
const generator = await createCodeAssistContentGenerator(
|
||||
httpOptions,
|
||||
AuthType.CLOUD_SHELL,
|
||||
AuthType.COMPUTE_ADC,
|
||||
mockConfig,
|
||||
);
|
||||
|
||||
expect(getOauthClient).toHaveBeenCalledWith(
|
||||
AuthType.CLOUD_SHELL,
|
||||
AuthType.COMPUTE_ADC,
|
||||
mockConfig,
|
||||
);
|
||||
expect(setupUser).toHaveBeenCalledWith(mockAuthClient);
|
||||
|
||||
@@ -21,7 +21,7 @@ export async function createCodeAssistContentGenerator(
|
||||
): Promise<ContentGenerator> {
|
||||
if (
|
||||
authType === AuthType.LOGIN_WITH_GOOGLE ||
|
||||
authType === AuthType.CLOUD_SHELL
|
||||
authType === AuthType.COMPUTE_ADC
|
||||
) {
|
||||
const authClient = await getOauthClient(authType, config);
|
||||
const userData = await setupUser(authClient);
|
||||
|
||||
@@ -318,7 +318,7 @@ describe('oauth2', () => {
|
||||
});
|
||||
|
||||
it('should use Compute to get a client if no cached credentials exist', async () => {
|
||||
await getOauthClient(AuthType.CLOUD_SHELL, mockConfig);
|
||||
await getOauthClient(AuthType.COMPUTE_ADC, mockConfig);
|
||||
|
||||
expect(Compute).toHaveBeenCalledWith({});
|
||||
expect(mockGetAccessToken).toHaveBeenCalled();
|
||||
@@ -329,7 +329,7 @@ describe('oauth2', () => {
|
||||
mockComputeClient.credentials = newCredentials;
|
||||
mockGetAccessToken.mockResolvedValue({ token: 'new-adc-token' });
|
||||
|
||||
await getOauthClient(AuthType.CLOUD_SHELL, mockConfig);
|
||||
await getOauthClient(AuthType.COMPUTE_ADC, mockConfig);
|
||||
|
||||
const credsPath = path.join(
|
||||
tempHomeDir,
|
||||
@@ -340,7 +340,7 @@ describe('oauth2', () => {
|
||||
});
|
||||
|
||||
it('should return the Compute client on successful ADC authentication', async () => {
|
||||
const client = await getOauthClient(AuthType.CLOUD_SHELL, mockConfig);
|
||||
const client = await getOauthClient(AuthType.COMPUTE_ADC, mockConfig);
|
||||
expect(client).toBe(mockComputeClient);
|
||||
});
|
||||
|
||||
@@ -349,9 +349,9 @@ describe('oauth2', () => {
|
||||
mockGetAccessToken.mockRejectedValue(testError);
|
||||
|
||||
await expect(
|
||||
getOauthClient(AuthType.CLOUD_SHELL, mockConfig),
|
||||
getOauthClient(AuthType.COMPUTE_ADC, mockConfig),
|
||||
).rejects.toThrow(
|
||||
'Could not authenticate using Cloud Shell credentials. Please select a different authentication method or ensure you are in a properly configured environment. Error: ADC Failed',
|
||||
'Could not authenticate using metadata server application default credentials. Please select a different authentication method or ensure you are in a properly configured environment. Error: ADC Failed',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -155,12 +155,15 @@ async function initOauthClient(
|
||||
}
|
||||
}
|
||||
|
||||
// In Google Cloud Shell, we can use Application Default Credentials (ADC)
|
||||
// provided via its metadata server to authenticate non-interactively using
|
||||
// the identity of the user logged into Cloud Shell.
|
||||
if (authType === AuthType.CLOUD_SHELL) {
|
||||
// In Google Compute Engine based environments (including Cloud Shell), we can
|
||||
// use Application Default Credentials (ADC) provided via its metadata server
|
||||
// to authenticate non-interactively using the identity of the logged-in user.
|
||||
if (authType === AuthType.COMPUTE_ADC) {
|
||||
try {
|
||||
debugLogger.log("Attempting to authenticate via Cloud Shell VM's ADC.");
|
||||
debugLogger.log(
|
||||
'Attempting to authenticate via metadata server application default credentials.',
|
||||
);
|
||||
|
||||
const computeClient = new Compute({
|
||||
// We can leave this empty, since the metadata server will provide
|
||||
// the service account email.
|
||||
@@ -172,7 +175,7 @@ async function initOauthClient(
|
||||
return computeClient;
|
||||
} catch (e) {
|
||||
throw new Error(
|
||||
`Could not authenticate using Cloud Shell credentials. Please select a different authentication method or ensure you are in a properly configured environment. Error: ${getErrorMessage(
|
||||
`Could not authenticate using metadata server application default credentials. Please select a different authentication method or ensure you are in a properly configured environment. Error: ${getErrorMessage(
|
||||
e,
|
||||
)}`,
|
||||
);
|
||||
|
||||
@@ -67,7 +67,7 @@ describe('createContentGenerator', () => {
|
||||
expect(generator).toBeInstanceOf(RecordingContentGenerator);
|
||||
});
|
||||
|
||||
it('should create a CodeAssistContentGenerator', async () => {
|
||||
it('should create a CodeAssistContentGenerator when AuthType is LOGIN_WITH_GOOGLE', async () => {
|
||||
const mockGenerator = {} as unknown as ContentGenerator;
|
||||
vi.mocked(createCodeAssistContentGenerator).mockResolvedValue(
|
||||
mockGenerator as never,
|
||||
@@ -84,6 +84,23 @@ describe('createContentGenerator', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('should create a CodeAssistContentGenerator when AuthType is COMPUTE_ADC', async () => {
|
||||
const mockGenerator = {} as unknown as ContentGenerator;
|
||||
vi.mocked(createCodeAssistContentGenerator).mockResolvedValue(
|
||||
mockGenerator as never,
|
||||
);
|
||||
const generator = await createContentGenerator(
|
||||
{
|
||||
authType: AuthType.COMPUTE_ADC,
|
||||
},
|
||||
mockConfig,
|
||||
);
|
||||
expect(createCodeAssistContentGenerator).toHaveBeenCalled();
|
||||
expect(generator).toEqual(
|
||||
new LoggingContentGenerator(mockGenerator, mockConfig),
|
||||
);
|
||||
});
|
||||
|
||||
it('should create a GoogleGenAI content generator', async () => {
|
||||
const mockConfig = {
|
||||
getUsageStatisticsEnabled: () => true,
|
||||
|
||||
@@ -48,7 +48,8 @@ export enum AuthType {
|
||||
LOGIN_WITH_GOOGLE = 'oauth-personal',
|
||||
USE_GEMINI = 'gemini-api-key',
|
||||
USE_VERTEX_AI = 'vertex-ai',
|
||||
CLOUD_SHELL = 'cloud-shell',
|
||||
LEGACY_CLOUD_SHELL = 'cloud-shell',
|
||||
COMPUTE_ADC = 'compute-default-credentials',
|
||||
}
|
||||
|
||||
export type ContentGeneratorConfig = {
|
||||
@@ -79,7 +80,7 @@ export async function createContentGeneratorConfig(
|
||||
// If we are using Google auth or we are in Cloud Shell, there is nothing else to validate for now
|
||||
if (
|
||||
authType === AuthType.LOGIN_WITH_GOOGLE ||
|
||||
authType === AuthType.CLOUD_SHELL
|
||||
authType === AuthType.COMPUTE_ADC
|
||||
) {
|
||||
return contentGeneratorConfig;
|
||||
}
|
||||
@@ -120,7 +121,7 @@ export async function createContentGenerator(
|
||||
};
|
||||
if (
|
||||
config.authType === AuthType.LOGIN_WITH_GOOGLE ||
|
||||
config.authType === AuthType.CLOUD_SHELL
|
||||
config.authType === AuthType.COMPUTE_ADC
|
||||
) {
|
||||
const httpOptions = { headers: baseHeaders };
|
||||
return new LoggingContentGenerator(
|
||||
|
||||
@@ -298,7 +298,7 @@ describe('loggers', () => {
|
||||
const event = new UserPromptEvent(
|
||||
11,
|
||||
'prompt-id-9',
|
||||
AuthType.CLOUD_SHELL,
|
||||
AuthType.COMPUTE_ADC,
|
||||
'test-prompt',
|
||||
);
|
||||
|
||||
@@ -315,7 +315,7 @@ describe('loggers', () => {
|
||||
interactive: false,
|
||||
prompt_length: 11,
|
||||
prompt_id: 'prompt-id-9',
|
||||
auth_type: 'cloud-shell',
|
||||
auth_type: 'compute-default-credentials',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
@@ -886,7 +886,7 @@ export function getConventionAttributes(event: {
|
||||
function getGenAiProvider(authType?: string): GenAiProviderName {
|
||||
switch (authType) {
|
||||
case AuthType.USE_VERTEX_AI:
|
||||
case AuthType.CLOUD_SHELL:
|
||||
case AuthType.COMPUTE_ADC:
|
||||
case AuthType.LOGIN_WITH_GOOGLE:
|
||||
return GenAiProviderName.GCP_VERTEX_AI;
|
||||
case AuthType.USE_GEMINI:
|
||||
|
||||
Reference in New Issue
Block a user