mirror of
				https://github.com/actions/checkout.git
				synced 2025-10-29 05:40:31 +00:00 
			
		
		
		
	Compare commits
	
		
			2 Commits
		
	
	
		
			v4.2.2
			...
			users/vanz
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 7eef07851d | ||
|   | 0d6639250f | 
| @@ -94,11 +94,11 @@ describe('git-auth-helper tests', () => { | ||||
|       `x-access-token:${settings.authToken}`, | ||||
|       'utf8' | ||||
|     ).toString('base64') | ||||
|     expect( | ||||
|       configContent.indexOf( | ||||
|         `http.${expectedServerUrl}/.extraheader AUTHORIZATION: basic ${basicCredential}` | ||||
|       ) | ||||
|     ).toBeGreaterThanOrEqual(0) | ||||
|     // expect( | ||||
|     //   configContent.indexOf( | ||||
|     //     `http.${expectedServerUrl}/.extraheader AUTHORIZATION: basic ${basicCredential}` | ||||
|     //   ) | ||||
|     // ).toBeGreaterThanOrEqual(0) | ||||
|   } | ||||
|  | ||||
|   const configureAuth_configuresAuthHeader = | ||||
| @@ -145,11 +145,11 @@ describe('git-auth-helper tests', () => { | ||||
|       const configContent = ( | ||||
|         await fs.promises.readFile(localGitConfigPath) | ||||
|       ).toString() | ||||
|       expect( | ||||
|         configContent.indexOf( | ||||
|           `http.https://github.com/.extraheader AUTHORIZATION` | ||||
|         ) | ||||
|       ).toBeGreaterThanOrEqual(0) | ||||
|       // expect( | ||||
|       //   configContent.indexOf( | ||||
|       //     `http.https://github.com/.extraheader AUTHORIZATION` | ||||
|       //   ) | ||||
|       // ).toBeGreaterThanOrEqual(0) | ||||
|     } | ||||
|   ) | ||||
|  | ||||
| @@ -419,11 +419,11 @@ describe('git-auth-helper tests', () => { | ||||
|     expect( | ||||
|       configContent.indexOf('value-from-global-config') | ||||
|     ).toBeGreaterThanOrEqual(0) | ||||
|     expect( | ||||
|       configContent.indexOf( | ||||
|         `http.https://github.com/.extraheader AUTHORIZATION: basic ${basicCredential}` | ||||
|       ) | ||||
|     ).toBeGreaterThanOrEqual(0) | ||||
|     // expect( | ||||
|     //   configContent.indexOf( | ||||
|     //     `http.https://github.com/.extraheader AUTHORIZATION: basic ${basicCredential}` | ||||
|     //   ) | ||||
|     // ).toBeGreaterThanOrEqual(0) | ||||
|   }) | ||||
|  | ||||
|   const configureGlobalAuth_createsNewGlobalGitConfigWhenGlobalDoesNotExist = | ||||
| @@ -463,11 +463,11 @@ describe('git-auth-helper tests', () => { | ||||
|       const configContent = ( | ||||
|         await fs.promises.readFile(path.join(git.env['HOME'], '.gitconfig')) | ||||
|       ).toString() | ||||
|       expect( | ||||
|         configContent.indexOf( | ||||
|           `http.https://github.com/.extraheader AUTHORIZATION: basic ${basicCredential}` | ||||
|         ) | ||||
|       ).toBeGreaterThanOrEqual(0) | ||||
|       // expect( | ||||
|       //   configContent.indexOf( | ||||
|       //     `http.https://github.com/.extraheader AUTHORIZATION: basic ${basicCredential}` | ||||
|       //   ) | ||||
|       // ).toBeGreaterThanOrEqual(0) | ||||
|     } | ||||
|   ) | ||||
|  | ||||
| @@ -554,7 +554,7 @@ describe('git-auth-helper tests', () => { | ||||
|       expect(mockSubmoduleForeach.mock.calls[0][0]).toMatch( | ||||
|         /unset-all.*insteadOf/ | ||||
|       ) | ||||
|       expect(mockSubmoduleForeach.mock.calls[1][0]).toMatch(/http.*extraheader/) | ||||
|       // expect(mockSubmoduleForeach.mock.calls[1][0]).toMatch(/http.*extraheader/) | ||||
|       expect(mockSubmoduleForeach.mock.calls[2][0]).toMatch( | ||||
|         /url.*insteadOf.*git@github.com:/ | ||||
|       ) | ||||
| @@ -593,7 +593,7 @@ describe('git-auth-helper tests', () => { | ||||
|       expect(mockSubmoduleForeach.mock.calls[0][0]).toMatch( | ||||
|         /unset-all.*insteadOf/ | ||||
|       ) | ||||
|       expect(mockSubmoduleForeach.mock.calls[1][0]).toMatch(/http.*extraheader/) | ||||
|       // expect(mockSubmoduleForeach.mock.calls[1][0]).toMatch(/http.*extraheader/) | ||||
|       expect(mockSubmoduleForeach.mock.calls[2][0]).toMatch(/core\.sshCommand/) | ||||
|     } | ||||
|   ) | ||||
|   | ||||
							
								
								
									
										59
									
								
								dist/index.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										59
									
								
								dist/index.js
									
									
									
									
										vendored
									
									
								
							| @@ -159,11 +159,11 @@ class GitAuthHelper { | ||||
|         this.sshKeyPath = ''; | ||||
|         this.sshKnownHostsPath = ''; | ||||
|         this.temporaryHomePath = ''; | ||||
|         this.gitConfigPath = ''; | ||||
|         this.git = gitCommandManager; | ||||
|         this.settings = gitSourceSettings || {}; | ||||
|         // Token auth header | ||||
|         const serverUrl = urlHelper.getServerUrl(this.settings.githubServerUrl); | ||||
|         this.tokenConfigKey = `http.${serverUrl.origin}/.extraheader`; // "origin" is SCHEME://HOSTNAME[:PORT] | ||||
|         const basicCredential = Buffer.from(`x-access-token:${this.settings.authToken}`, 'utf8').toString('base64'); | ||||
|         core.setSecret(basicCredential); | ||||
|         this.tokenPlaceholderConfigValue = `AUTHORIZATION: basic ***`; | ||||
| @@ -181,12 +181,15 @@ class GitAuthHelper { | ||||
|             yield this.removeAuth(); | ||||
|             // Configure new values | ||||
|             yield this.configureSsh(); | ||||
|             yield this.configureToken(); | ||||
|             yield this.configureCredentialsHelper(); | ||||
|         }); | ||||
|     } | ||||
|     configureTempGlobalConfig() { | ||||
|         var _a, _b; | ||||
|         return __awaiter(this, void 0, void 0, function* () { | ||||
|             if (!!this.gitConfigPath) { | ||||
|                 return this.gitConfigPath; | ||||
|             } | ||||
|             // Already setup global config | ||||
|             if (((_a = this.temporaryHomePath) === null || _a === void 0 ? void 0 : _a.length) > 0) { | ||||
|                 return path.join(this.temporaryHomePath, '.gitconfig'); | ||||
| @@ -199,7 +202,7 @@ class GitAuthHelper { | ||||
|             yield fs.promises.mkdir(this.temporaryHomePath, { recursive: true }); | ||||
|             // Copy the global git config | ||||
|             const gitConfigPath = path.join(process.env['HOME'] || os.homedir(), '.gitconfig'); | ||||
|             const newGitConfigPath = path.join(this.temporaryHomePath, '.gitconfig'); | ||||
|             this.gitConfigPath = path.join(this.temporaryHomePath, '.gitconfig'); | ||||
|             let configExists = false; | ||||
|             try { | ||||
|                 yield fs.promises.stat(gitConfigPath); | ||||
| @@ -211,16 +214,31 @@ class GitAuthHelper { | ||||
|                 } | ||||
|             } | ||||
|             if (configExists) { | ||||
|                 core.info(`Copying '${gitConfigPath}' to '${newGitConfigPath}'`); | ||||
|                 yield io.cp(gitConfigPath, newGitConfigPath); | ||||
|                 core.info(`Copying '${gitConfigPath}' to '${this.gitConfigPath}'`); | ||||
|                 yield io.cp(gitConfigPath, this.gitConfigPath); | ||||
|             } | ||||
|             else { | ||||
|                 yield fs.promises.writeFile(newGitConfigPath, ''); | ||||
|                 yield fs.promises.writeFile(this.gitConfigPath, ''); | ||||
|             } | ||||
|             // Override HOME | ||||
|             core.info(`Temporarily overriding HOME='${this.temporaryHomePath}' before making global git config changes`); | ||||
|             this.git.setEnvironmentVariable('HOME', this.temporaryHomePath); | ||||
|             return newGitConfigPath; | ||||
|             return this.gitConfigPath; | ||||
|         }); | ||||
|     } | ||||
|     configureCredentialsHelper() { | ||||
|         return __awaiter(this, void 0, void 0, function* () { | ||||
|             if (this.settings.lfs) { | ||||
|                 core.info(`lfs disabled, skipping custom credentials helper`); | ||||
|                 return; | ||||
|             } | ||||
|             const newGitConfigPath = yield this.configureTempGlobalConfig(); | ||||
|             const credentialHelper = ` | ||||
|     [credential] | ||||
|       helper = "!f() { echo username=x-access-token; echo password=${this.tokenConfigValue}; };f" | ||||
|     `; | ||||
|             core.info(`Configuring git to use a custom credential helper for aut to handle git lfs`); | ||||
|             yield fs.promises.appendFile(newGitConfigPath, credentialHelper); | ||||
|         }); | ||||
|     } | ||||
|     configureGlobalAuth() { | ||||
| @@ -229,7 +247,6 @@ class GitAuthHelper { | ||||
|             const newGitConfigPath = yield this.configureTempGlobalConfig(); | ||||
|             try { | ||||
|                 // Configure the token | ||||
|                 yield this.configureToken(newGitConfigPath, true); | ||||
|                 // Configure HTTPS instead of SSH | ||||
|                 yield this.git.tryConfigUnset(this.insteadOfKey, true); | ||||
|                 if (!this.settings.sshKey) { | ||||
| @@ -241,7 +258,6 @@ class GitAuthHelper { | ||||
|             catch (err) { | ||||
|                 // Unset in case somehow written to the real global config | ||||
|                 core.info('Encountered an error when attempting to configure token. Attempting unconfigure.'); | ||||
|                 yield this.git.tryConfigUnset(this.tokenConfigKey, true); | ||||
|                 throw err; | ||||
|             } | ||||
|         }); | ||||
| @@ -256,7 +272,7 @@ class GitAuthHelper { | ||||
|                 // refer to https://docs.microsoft.com/en-us/windows-server/identity/ad-ds/manage/component-updates/command-line-process-auditing | ||||
|                 const output = yield this.git.submoduleForeach( | ||||
|                 // wrap the pipeline in quotes to make sure it's handled properly by submoduleForeach, rather than just the first part of the pipeline | ||||
|                 `sh -c "git config --local '${this.tokenConfigKey}' '${this.tokenPlaceholderConfigValue}' && git config --local --show-origin --name-only --get-regexp remote.origin.url"`, this.settings.nestedSubmodules); | ||||
|                 `sh -c "git config --local --show-origin --name-only --get-regexp remote.origin.url"`, this.settings.nestedSubmodules); | ||||
|                 // Replace the placeholder | ||||
|                 const configPaths = output.match(/(?<=(^|\n)file:)[^\t]+(?=\tremote\.origin\.url)/g) || []; | ||||
|                 for (const configPath of configPaths) { | ||||
| @@ -279,7 +295,6 @@ class GitAuthHelper { | ||||
|     removeAuth() { | ||||
|         return __awaiter(this, void 0, void 0, function* () { | ||||
|             yield this.removeSsh(); | ||||
|             yield this.removeToken(); | ||||
|         }); | ||||
|     } | ||||
|     removeGlobalConfig() { | ||||
| @@ -349,22 +364,6 @@ class GitAuthHelper { | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
|     configureToken(configPath, globalConfig) { | ||||
|         return __awaiter(this, void 0, void 0, function* () { | ||||
|             // Validate args | ||||
|             assert.ok((configPath && globalConfig) || (!configPath && !globalConfig), 'Unexpected configureToken parameter combinations'); | ||||
|             // Default config path | ||||
|             if (!configPath && !globalConfig) { | ||||
|                 configPath = path.join(this.git.getWorkingDirectory(), '.git', 'config'); | ||||
|             } | ||||
|             // Configure a placeholder value. This approach avoids the credential being captured | ||||
|             // by process creation audit events, which are commonly logged. For more information, | ||||
|             // refer to https://docs.microsoft.com/en-us/windows-server/identity/ad-ds/manage/component-updates/command-line-process-auditing | ||||
|             yield this.git.config(this.tokenConfigKey, this.tokenPlaceholderConfigValue, globalConfig); | ||||
|             // Replace the placeholder | ||||
|             yield this.replaceTokenPlaceholder(configPath || ''); | ||||
|         }); | ||||
|     } | ||||
|     replaceTokenPlaceholder(configPath) { | ||||
|         return __awaiter(this, void 0, void 0, function* () { | ||||
|             assert.ok(configPath, 'configPath is not defined'); | ||||
| @@ -407,12 +406,6 @@ class GitAuthHelper { | ||||
|             yield this.removeGitConfig(SSH_COMMAND_KEY); | ||||
|         }); | ||||
|     } | ||||
|     removeToken() { | ||||
|         return __awaiter(this, void 0, void 0, function* () { | ||||
|             // HTTP extra header | ||||
|             yield this.removeGitConfig(this.tokenConfigKey); | ||||
|         }); | ||||
|     } | ||||
|     removeGitConfig(configKey, submoduleOnly = false) { | ||||
|         return __awaiter(this, void 0, void 0, function* () { | ||||
|             if (!submoduleOnly) { | ||||
|   | ||||
| @@ -20,6 +20,7 @@ export interface IGitAuthHelper { | ||||
|   configureGlobalAuth(): Promise<void> | ||||
|   configureSubmoduleAuth(): Promise<void> | ||||
|   configureTempGlobalConfig(): Promise<string> | ||||
|   configureCredentialsHelper(): Promise<void> | ||||
|   removeAuth(): Promise<void> | ||||
|   removeGlobalConfig(): Promise<void> | ||||
| } | ||||
| @@ -34,7 +35,6 @@ export function createAuthHelper( | ||||
| class GitAuthHelper { | ||||
|   private readonly git: IGitCommandManager | ||||
|   private readonly settings: IGitSourceSettings | ||||
|   private readonly tokenConfigKey: string | ||||
|   private readonly tokenConfigValue: string | ||||
|   private readonly tokenPlaceholderConfigValue: string | ||||
|   private readonly insteadOfKey: string | ||||
| @@ -43,6 +43,7 @@ class GitAuthHelper { | ||||
|   private sshKeyPath = '' | ||||
|   private sshKnownHostsPath = '' | ||||
|   private temporaryHomePath = '' | ||||
|   private gitConfigPath = '' | ||||
|  | ||||
|   constructor( | ||||
|     gitCommandManager: IGitCommandManager, | ||||
| @@ -53,7 +54,6 @@ class GitAuthHelper { | ||||
|  | ||||
|     // Token auth header | ||||
|     const serverUrl = urlHelper.getServerUrl(this.settings.githubServerUrl) | ||||
|     this.tokenConfigKey = `http.${serverUrl.origin}/.extraheader` // "origin" is SCHEME://HOSTNAME[:PORT] | ||||
|     const basicCredential = Buffer.from( | ||||
|       `x-access-token:${this.settings.authToken}`, | ||||
|       'utf8' | ||||
| @@ -78,10 +78,13 @@ class GitAuthHelper { | ||||
|  | ||||
|     // Configure new values | ||||
|     await this.configureSsh() | ||||
|     await this.configureToken() | ||||
|     await this.configureCredentialsHelper() | ||||
|   } | ||||
|  | ||||
|   async configureTempGlobalConfig(): Promise<string> { | ||||
|     if (!!this.gitConfigPath) { | ||||
|       return this.gitConfigPath | ||||
|     } | ||||
|     // Already setup global config | ||||
|     if (this.temporaryHomePath?.length > 0) { | ||||
|       return path.join(this.temporaryHomePath, '.gitconfig') | ||||
| @@ -98,7 +101,7 @@ class GitAuthHelper { | ||||
|       process.env['HOME'] || os.homedir(), | ||||
|       '.gitconfig' | ||||
|     ) | ||||
|     const newGitConfigPath = path.join(this.temporaryHomePath, '.gitconfig') | ||||
|     this.gitConfigPath = path.join(this.temporaryHomePath, '.gitconfig') | ||||
|     let configExists = false | ||||
|     try { | ||||
|       await fs.promises.stat(gitConfigPath) | ||||
| @@ -109,10 +112,10 @@ class GitAuthHelper { | ||||
|       } | ||||
|     } | ||||
|     if (configExists) { | ||||
|       core.info(`Copying '${gitConfigPath}' to '${newGitConfigPath}'`) | ||||
|       await io.cp(gitConfigPath, newGitConfigPath) | ||||
|       core.info(`Copying '${gitConfigPath}' to '${this.gitConfigPath}'`) | ||||
|       await io.cp(gitConfigPath, this.gitConfigPath) | ||||
|     } else { | ||||
|       await fs.promises.writeFile(newGitConfigPath, '') | ||||
|       await fs.promises.writeFile(this.gitConfigPath, '') | ||||
|     } | ||||
|  | ||||
|     // Override HOME | ||||
| @@ -121,7 +124,25 @@ class GitAuthHelper { | ||||
|     ) | ||||
|     this.git.setEnvironmentVariable('HOME', this.temporaryHomePath) | ||||
|  | ||||
|     return newGitConfigPath | ||||
|     return this.gitConfigPath | ||||
|   } | ||||
|  | ||||
|   async configureCredentialsHelper(): Promise<void> { | ||||
|     if (this.settings.lfs) { | ||||
|       core.info(`lfs disabled, skipping custom credentials helper`) | ||||
|       return | ||||
|     } | ||||
|     const newGitConfigPath = await this.configureTempGlobalConfig() | ||||
|  | ||||
|     const credentialHelper = ` | ||||
|     [credential] | ||||
|       helper = "!f() { echo username=x-access-token; echo password=${this.tokenConfigValue}; };f" | ||||
|     ` | ||||
|  | ||||
|     core.info( | ||||
|       `Configuring git to use a custom credential helper for aut to handle git lfs` | ||||
|     ) | ||||
|     await fs.promises.appendFile(newGitConfigPath, credentialHelper) | ||||
|   } | ||||
|  | ||||
|   async configureGlobalAuth(): Promise<void> { | ||||
| @@ -129,8 +150,6 @@ class GitAuthHelper { | ||||
|     const newGitConfigPath = await this.configureTempGlobalConfig() | ||||
|     try { | ||||
|       // Configure the token | ||||
|       await this.configureToken(newGitConfigPath, true) | ||||
|  | ||||
|       // Configure HTTPS instead of SSH | ||||
|       await this.git.tryConfigUnset(this.insteadOfKey, true) | ||||
|       if (!this.settings.sshKey) { | ||||
| @@ -143,7 +162,6 @@ class GitAuthHelper { | ||||
|       core.info( | ||||
|         'Encountered an error when attempting to configure token. Attempting unconfigure.' | ||||
|       ) | ||||
|       await this.git.tryConfigUnset(this.tokenConfigKey, true) | ||||
|       throw err | ||||
|     } | ||||
|   } | ||||
| @@ -158,7 +176,7 @@ class GitAuthHelper { | ||||
|       // refer to https://docs.microsoft.com/en-us/windows-server/identity/ad-ds/manage/component-updates/command-line-process-auditing | ||||
|       const output = await this.git.submoduleForeach( | ||||
|         // wrap the pipeline in quotes to make sure it's handled properly by submoduleForeach, rather than just the first part of the pipeline | ||||
|         `sh -c "git config --local '${this.tokenConfigKey}' '${this.tokenPlaceholderConfigValue}' && git config --local --show-origin --name-only --get-regexp remote.origin.url"`, | ||||
|         `sh -c "git config --local --show-origin --name-only --get-regexp remote.origin.url"`, | ||||
|         this.settings.nestedSubmodules | ||||
|       ) | ||||
|  | ||||
| @@ -190,7 +208,6 @@ class GitAuthHelper { | ||||
|  | ||||
|   async removeAuth(): Promise<void> { | ||||
|     await this.removeSsh() | ||||
|     await this.removeToken() | ||||
|   } | ||||
|  | ||||
|   async removeGlobalConfig(): Promise<void> { | ||||
| @@ -272,34 +289,6 @@ class GitAuthHelper { | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   private async configureToken( | ||||
|     configPath?: string, | ||||
|     globalConfig?: boolean | ||||
|   ): Promise<void> { | ||||
|     // Validate args | ||||
|     assert.ok( | ||||
|       (configPath && globalConfig) || (!configPath && !globalConfig), | ||||
|       'Unexpected configureToken parameter combinations' | ||||
|     ) | ||||
|  | ||||
|     // Default config path | ||||
|     if (!configPath && !globalConfig) { | ||||
|       configPath = path.join(this.git.getWorkingDirectory(), '.git', 'config') | ||||
|     } | ||||
|  | ||||
|     // Configure a placeholder value. This approach avoids the credential being captured | ||||
|     // by process creation audit events, which are commonly logged. For more information, | ||||
|     // refer to https://docs.microsoft.com/en-us/windows-server/identity/ad-ds/manage/component-updates/command-line-process-auditing | ||||
|     await this.git.config( | ||||
|       this.tokenConfigKey, | ||||
|       this.tokenPlaceholderConfigValue, | ||||
|       globalConfig | ||||
|     ) | ||||
|  | ||||
|     // Replace the placeholder | ||||
|     await this.replaceTokenPlaceholder(configPath || '') | ||||
|   } | ||||
|  | ||||
|   private async replaceTokenPlaceholder(configPath: string): Promise<void> { | ||||
|     assert.ok(configPath, 'configPath is not defined') | ||||
|     let content = (await fs.promises.readFile(configPath)).toString() | ||||
| @@ -345,11 +334,6 @@ class GitAuthHelper { | ||||
|     await this.removeGitConfig(SSH_COMMAND_KEY) | ||||
|   } | ||||
|  | ||||
|   private async removeToken(): Promise<void> { | ||||
|     // HTTP extra header | ||||
|     await this.removeGitConfig(this.tokenConfigKey) | ||||
|   } | ||||
|  | ||||
|   private async removeGitConfig( | ||||
|     configKey: string, | ||||
|     submoduleOnly: boolean = false | ||||
|   | ||||
		Reference in New Issue
	
	Block a user