mirror of
				https://github.com/actions/checkout.git
				synced 2025-11-03 23:38:09 +08:00 
			
		
		
		
	Compare commits
	
		
			2 Commits
		
	
	
		
			v4.0.0
			...
			users/vanz
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					7eef07851d | ||
| 
						 | 
					0d6639250f | 
@@ -94,11 +94,11 @@ describe('git-auth-helper tests', () => {
 | 
				
			|||||||
      `x-access-token:${settings.authToken}`,
 | 
					      `x-access-token:${settings.authToken}`,
 | 
				
			||||||
      'utf8'
 | 
					      'utf8'
 | 
				
			||||||
    ).toString('base64')
 | 
					    ).toString('base64')
 | 
				
			||||||
    expect(
 | 
					    // expect(
 | 
				
			||||||
      configContent.indexOf(
 | 
					    //   configContent.indexOf(
 | 
				
			||||||
        `http.${expectedServerUrl}/.extraheader AUTHORIZATION: basic ${basicCredential}`
 | 
					    //     `http.${expectedServerUrl}/.extraheader AUTHORIZATION: basic ${basicCredential}`
 | 
				
			||||||
      )
 | 
					    //   )
 | 
				
			||||||
    ).toBeGreaterThanOrEqual(0)
 | 
					    // ).toBeGreaterThanOrEqual(0)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const configureAuth_configuresAuthHeader =
 | 
					  const configureAuth_configuresAuthHeader =
 | 
				
			||||||
@@ -145,11 +145,11 @@ describe('git-auth-helper tests', () => {
 | 
				
			|||||||
      const configContent = (
 | 
					      const configContent = (
 | 
				
			||||||
        await fs.promises.readFile(localGitConfigPath)
 | 
					        await fs.promises.readFile(localGitConfigPath)
 | 
				
			||||||
      ).toString()
 | 
					      ).toString()
 | 
				
			||||||
      expect(
 | 
					      // expect(
 | 
				
			||||||
        configContent.indexOf(
 | 
					      //   configContent.indexOf(
 | 
				
			||||||
          `http.https://github.com/.extraheader AUTHORIZATION`
 | 
					      //     `http.https://github.com/.extraheader AUTHORIZATION`
 | 
				
			||||||
        )
 | 
					      //   )
 | 
				
			||||||
      ).toBeGreaterThanOrEqual(0)
 | 
					      // ).toBeGreaterThanOrEqual(0)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  )
 | 
					  )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -419,11 +419,11 @@ describe('git-auth-helper tests', () => {
 | 
				
			|||||||
    expect(
 | 
					    expect(
 | 
				
			||||||
      configContent.indexOf('value-from-global-config')
 | 
					      configContent.indexOf('value-from-global-config')
 | 
				
			||||||
    ).toBeGreaterThanOrEqual(0)
 | 
					    ).toBeGreaterThanOrEqual(0)
 | 
				
			||||||
    expect(
 | 
					    // expect(
 | 
				
			||||||
      configContent.indexOf(
 | 
					    //   configContent.indexOf(
 | 
				
			||||||
        `http.https://github.com/.extraheader AUTHORIZATION: basic ${basicCredential}`
 | 
					    //     `http.https://github.com/.extraheader AUTHORIZATION: basic ${basicCredential}`
 | 
				
			||||||
      )
 | 
					    //   )
 | 
				
			||||||
    ).toBeGreaterThanOrEqual(0)
 | 
					    // ).toBeGreaterThanOrEqual(0)
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const configureGlobalAuth_createsNewGlobalGitConfigWhenGlobalDoesNotExist =
 | 
					  const configureGlobalAuth_createsNewGlobalGitConfigWhenGlobalDoesNotExist =
 | 
				
			||||||
@@ -463,11 +463,11 @@ describe('git-auth-helper tests', () => {
 | 
				
			|||||||
      const configContent = (
 | 
					      const configContent = (
 | 
				
			||||||
        await fs.promises.readFile(path.join(git.env['HOME'], '.gitconfig'))
 | 
					        await fs.promises.readFile(path.join(git.env['HOME'], '.gitconfig'))
 | 
				
			||||||
      ).toString()
 | 
					      ).toString()
 | 
				
			||||||
      expect(
 | 
					      // expect(
 | 
				
			||||||
        configContent.indexOf(
 | 
					      //   configContent.indexOf(
 | 
				
			||||||
          `http.https://github.com/.extraheader AUTHORIZATION: basic ${basicCredential}`
 | 
					      //     `http.https://github.com/.extraheader AUTHORIZATION: basic ${basicCredential}`
 | 
				
			||||||
        )
 | 
					      //   )
 | 
				
			||||||
      ).toBeGreaterThanOrEqual(0)
 | 
					      // ).toBeGreaterThanOrEqual(0)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  )
 | 
					  )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -554,7 +554,7 @@ describe('git-auth-helper tests', () => {
 | 
				
			|||||||
      expect(mockSubmoduleForeach.mock.calls[0][0]).toMatch(
 | 
					      expect(mockSubmoduleForeach.mock.calls[0][0]).toMatch(
 | 
				
			||||||
        /unset-all.*insteadOf/
 | 
					        /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(
 | 
					      expect(mockSubmoduleForeach.mock.calls[2][0]).toMatch(
 | 
				
			||||||
        /url.*insteadOf.*git@github.com:/
 | 
					        /url.*insteadOf.*git@github.com:/
 | 
				
			||||||
      )
 | 
					      )
 | 
				
			||||||
@@ -593,7 +593,7 @@ describe('git-auth-helper tests', () => {
 | 
				
			|||||||
      expect(mockSubmoduleForeach.mock.calls[0][0]).toMatch(
 | 
					      expect(mockSubmoduleForeach.mock.calls[0][0]).toMatch(
 | 
				
			||||||
        /unset-all.*insteadOf/
 | 
					        /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/)
 | 
					      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.sshKeyPath = '';
 | 
				
			||||||
        this.sshKnownHostsPath = '';
 | 
					        this.sshKnownHostsPath = '';
 | 
				
			||||||
        this.temporaryHomePath = '';
 | 
					        this.temporaryHomePath = '';
 | 
				
			||||||
 | 
					        this.gitConfigPath = '';
 | 
				
			||||||
        this.git = gitCommandManager;
 | 
					        this.git = gitCommandManager;
 | 
				
			||||||
        this.settings = gitSourceSettings || {};
 | 
					        this.settings = gitSourceSettings || {};
 | 
				
			||||||
        // Token auth header
 | 
					        // Token auth header
 | 
				
			||||||
        const serverUrl = urlHelper.getServerUrl(this.settings.githubServerUrl);
 | 
					        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');
 | 
					        const basicCredential = Buffer.from(`x-access-token:${this.settings.authToken}`, 'utf8').toString('base64');
 | 
				
			||||||
        core.setSecret(basicCredential);
 | 
					        core.setSecret(basicCredential);
 | 
				
			||||||
        this.tokenPlaceholderConfigValue = `AUTHORIZATION: basic ***`;
 | 
					        this.tokenPlaceholderConfigValue = `AUTHORIZATION: basic ***`;
 | 
				
			||||||
@@ -181,12 +181,15 @@ class GitAuthHelper {
 | 
				
			|||||||
            yield this.removeAuth();
 | 
					            yield this.removeAuth();
 | 
				
			||||||
            // Configure new values
 | 
					            // Configure new values
 | 
				
			||||||
            yield this.configureSsh();
 | 
					            yield this.configureSsh();
 | 
				
			||||||
            yield this.configureToken();
 | 
					            yield this.configureCredentialsHelper();
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    configureTempGlobalConfig() {
 | 
					    configureTempGlobalConfig() {
 | 
				
			||||||
        var _a, _b;
 | 
					        var _a, _b;
 | 
				
			||||||
        return __awaiter(this, void 0, void 0, function* () {
 | 
					        return __awaiter(this, void 0, void 0, function* () {
 | 
				
			||||||
 | 
					            if (!!this.gitConfigPath) {
 | 
				
			||||||
 | 
					                return this.gitConfigPath;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            // Already setup global config
 | 
					            // Already setup global config
 | 
				
			||||||
            if (((_a = this.temporaryHomePath) === null || _a === void 0 ? void 0 : _a.length) > 0) {
 | 
					            if (((_a = this.temporaryHomePath) === null || _a === void 0 ? void 0 : _a.length) > 0) {
 | 
				
			||||||
                return path.join(this.temporaryHomePath, '.gitconfig');
 | 
					                return path.join(this.temporaryHomePath, '.gitconfig');
 | 
				
			||||||
@@ -199,7 +202,7 @@ class GitAuthHelper {
 | 
				
			|||||||
            yield fs.promises.mkdir(this.temporaryHomePath, { recursive: true });
 | 
					            yield fs.promises.mkdir(this.temporaryHomePath, { recursive: true });
 | 
				
			||||||
            // Copy the global git config
 | 
					            // Copy the global git config
 | 
				
			||||||
            const gitConfigPath = path.join(process.env['HOME'] || os.homedir(), '.gitconfig');
 | 
					            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;
 | 
					            let configExists = false;
 | 
				
			||||||
            try {
 | 
					            try {
 | 
				
			||||||
                yield fs.promises.stat(gitConfigPath);
 | 
					                yield fs.promises.stat(gitConfigPath);
 | 
				
			||||||
@@ -211,16 +214,31 @@ class GitAuthHelper {
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            if (configExists) {
 | 
					            if (configExists) {
 | 
				
			||||||
                core.info(`Copying '${gitConfigPath}' to '${newGitConfigPath}'`);
 | 
					                core.info(`Copying '${gitConfigPath}' to '${this.gitConfigPath}'`);
 | 
				
			||||||
                yield io.cp(gitConfigPath, newGitConfigPath);
 | 
					                yield io.cp(gitConfigPath, this.gitConfigPath);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            else {
 | 
					            else {
 | 
				
			||||||
                yield fs.promises.writeFile(newGitConfigPath, '');
 | 
					                yield fs.promises.writeFile(this.gitConfigPath, '');
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            // Override HOME
 | 
					            // Override HOME
 | 
				
			||||||
            core.info(`Temporarily overriding HOME='${this.temporaryHomePath}' before making global git config changes`);
 | 
					            core.info(`Temporarily overriding HOME='${this.temporaryHomePath}' before making global git config changes`);
 | 
				
			||||||
            this.git.setEnvironmentVariable('HOME', this.temporaryHomePath);
 | 
					            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() {
 | 
					    configureGlobalAuth() {
 | 
				
			||||||
@@ -229,7 +247,6 @@ class GitAuthHelper {
 | 
				
			|||||||
            const newGitConfigPath = yield this.configureTempGlobalConfig();
 | 
					            const newGitConfigPath = yield this.configureTempGlobalConfig();
 | 
				
			||||||
            try {
 | 
					            try {
 | 
				
			||||||
                // Configure the token
 | 
					                // Configure the token
 | 
				
			||||||
                yield this.configureToken(newGitConfigPath, true);
 | 
					 | 
				
			||||||
                // Configure HTTPS instead of SSH
 | 
					                // Configure HTTPS instead of SSH
 | 
				
			||||||
                yield this.git.tryConfigUnset(this.insteadOfKey, true);
 | 
					                yield this.git.tryConfigUnset(this.insteadOfKey, true);
 | 
				
			||||||
                if (!this.settings.sshKey) {
 | 
					                if (!this.settings.sshKey) {
 | 
				
			||||||
@@ -241,7 +258,6 @@ class GitAuthHelper {
 | 
				
			|||||||
            catch (err) {
 | 
					            catch (err) {
 | 
				
			||||||
                // Unset in case somehow written to the real global config
 | 
					                // Unset in case somehow written to the real global config
 | 
				
			||||||
                core.info('Encountered an error when attempting to configure token. Attempting unconfigure.');
 | 
					                core.info('Encountered an error when attempting to configure token. Attempting unconfigure.');
 | 
				
			||||||
                yield this.git.tryConfigUnset(this.tokenConfigKey, true);
 | 
					 | 
				
			||||||
                throw err;
 | 
					                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
 | 
					                // 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(
 | 
					                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
 | 
					                // 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
 | 
					                // Replace the placeholder
 | 
				
			||||||
                const configPaths = output.match(/(?<=(^|\n)file:)[^\t]+(?=\tremote\.origin\.url)/g) || [];
 | 
					                const configPaths = output.match(/(?<=(^|\n)file:)[^\t]+(?=\tremote\.origin\.url)/g) || [];
 | 
				
			||||||
                for (const configPath of configPaths) {
 | 
					                for (const configPath of configPaths) {
 | 
				
			||||||
@@ -279,7 +295,6 @@ class GitAuthHelper {
 | 
				
			|||||||
    removeAuth() {
 | 
					    removeAuth() {
 | 
				
			||||||
        return __awaiter(this, void 0, void 0, function* () {
 | 
					        return __awaiter(this, void 0, void 0, function* () {
 | 
				
			||||||
            yield this.removeSsh();
 | 
					            yield this.removeSsh();
 | 
				
			||||||
            yield this.removeToken();
 | 
					 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    removeGlobalConfig() {
 | 
					    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) {
 | 
					    replaceTokenPlaceholder(configPath) {
 | 
				
			||||||
        return __awaiter(this, void 0, void 0, function* () {
 | 
					        return __awaiter(this, void 0, void 0, function* () {
 | 
				
			||||||
            assert.ok(configPath, 'configPath is not defined');
 | 
					            assert.ok(configPath, 'configPath is not defined');
 | 
				
			||||||
@@ -407,12 +406,6 @@ class GitAuthHelper {
 | 
				
			|||||||
            yield this.removeGitConfig(SSH_COMMAND_KEY);
 | 
					            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) {
 | 
					    removeGitConfig(configKey, submoduleOnly = false) {
 | 
				
			||||||
        return __awaiter(this, void 0, void 0, function* () {
 | 
					        return __awaiter(this, void 0, void 0, function* () {
 | 
				
			||||||
            if (!submoduleOnly) {
 | 
					            if (!submoduleOnly) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,6 +20,7 @@ export interface IGitAuthHelper {
 | 
				
			|||||||
  configureGlobalAuth(): Promise<void>
 | 
					  configureGlobalAuth(): Promise<void>
 | 
				
			||||||
  configureSubmoduleAuth(): Promise<void>
 | 
					  configureSubmoduleAuth(): Promise<void>
 | 
				
			||||||
  configureTempGlobalConfig(): Promise<string>
 | 
					  configureTempGlobalConfig(): Promise<string>
 | 
				
			||||||
 | 
					  configureCredentialsHelper(): Promise<void>
 | 
				
			||||||
  removeAuth(): Promise<void>
 | 
					  removeAuth(): Promise<void>
 | 
				
			||||||
  removeGlobalConfig(): Promise<void>
 | 
					  removeGlobalConfig(): Promise<void>
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -34,7 +35,6 @@ export function createAuthHelper(
 | 
				
			|||||||
class GitAuthHelper {
 | 
					class GitAuthHelper {
 | 
				
			||||||
  private readonly git: IGitCommandManager
 | 
					  private readonly git: IGitCommandManager
 | 
				
			||||||
  private readonly settings: IGitSourceSettings
 | 
					  private readonly settings: IGitSourceSettings
 | 
				
			||||||
  private readonly tokenConfigKey: string
 | 
					 | 
				
			||||||
  private readonly tokenConfigValue: string
 | 
					  private readonly tokenConfigValue: string
 | 
				
			||||||
  private readonly tokenPlaceholderConfigValue: string
 | 
					  private readonly tokenPlaceholderConfigValue: string
 | 
				
			||||||
  private readonly insteadOfKey: string
 | 
					  private readonly insteadOfKey: string
 | 
				
			||||||
@@ -43,6 +43,7 @@ class GitAuthHelper {
 | 
				
			|||||||
  private sshKeyPath = ''
 | 
					  private sshKeyPath = ''
 | 
				
			||||||
  private sshKnownHostsPath = ''
 | 
					  private sshKnownHostsPath = ''
 | 
				
			||||||
  private temporaryHomePath = ''
 | 
					  private temporaryHomePath = ''
 | 
				
			||||||
 | 
					  private gitConfigPath = ''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  constructor(
 | 
					  constructor(
 | 
				
			||||||
    gitCommandManager: IGitCommandManager,
 | 
					    gitCommandManager: IGitCommandManager,
 | 
				
			||||||
@@ -53,7 +54,6 @@ class GitAuthHelper {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // Token auth header
 | 
					    // Token auth header
 | 
				
			||||||
    const serverUrl = urlHelper.getServerUrl(this.settings.githubServerUrl)
 | 
					    const serverUrl = urlHelper.getServerUrl(this.settings.githubServerUrl)
 | 
				
			||||||
    this.tokenConfigKey = `http.${serverUrl.origin}/.extraheader` // "origin" is SCHEME://HOSTNAME[:PORT]
 | 
					 | 
				
			||||||
    const basicCredential = Buffer.from(
 | 
					    const basicCredential = Buffer.from(
 | 
				
			||||||
      `x-access-token:${this.settings.authToken}`,
 | 
					      `x-access-token:${this.settings.authToken}`,
 | 
				
			||||||
      'utf8'
 | 
					      'utf8'
 | 
				
			||||||
@@ -78,10 +78,13 @@ class GitAuthHelper {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // Configure new values
 | 
					    // Configure new values
 | 
				
			||||||
    await this.configureSsh()
 | 
					    await this.configureSsh()
 | 
				
			||||||
    await this.configureToken()
 | 
					    await this.configureCredentialsHelper()
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  async configureTempGlobalConfig(): Promise<string> {
 | 
					  async configureTempGlobalConfig(): Promise<string> {
 | 
				
			||||||
 | 
					    if (!!this.gitConfigPath) {
 | 
				
			||||||
 | 
					      return this.gitConfigPath
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    // Already setup global config
 | 
					    // Already setup global config
 | 
				
			||||||
    if (this.temporaryHomePath?.length > 0) {
 | 
					    if (this.temporaryHomePath?.length > 0) {
 | 
				
			||||||
      return path.join(this.temporaryHomePath, '.gitconfig')
 | 
					      return path.join(this.temporaryHomePath, '.gitconfig')
 | 
				
			||||||
@@ -98,7 +101,7 @@ class GitAuthHelper {
 | 
				
			|||||||
      process.env['HOME'] || os.homedir(),
 | 
					      process.env['HOME'] || os.homedir(),
 | 
				
			||||||
      '.gitconfig'
 | 
					      '.gitconfig'
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    const newGitConfigPath = path.join(this.temporaryHomePath, '.gitconfig')
 | 
					    this.gitConfigPath = path.join(this.temporaryHomePath, '.gitconfig')
 | 
				
			||||||
    let configExists = false
 | 
					    let configExists = false
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
      await fs.promises.stat(gitConfigPath)
 | 
					      await fs.promises.stat(gitConfigPath)
 | 
				
			||||||
@@ -109,10 +112,10 @@ class GitAuthHelper {
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (configExists) {
 | 
					    if (configExists) {
 | 
				
			||||||
      core.info(`Copying '${gitConfigPath}' to '${newGitConfigPath}'`)
 | 
					      core.info(`Copying '${gitConfigPath}' to '${this.gitConfigPath}'`)
 | 
				
			||||||
      await io.cp(gitConfigPath, newGitConfigPath)
 | 
					      await io.cp(gitConfigPath, this.gitConfigPath)
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      await fs.promises.writeFile(newGitConfigPath, '')
 | 
					      await fs.promises.writeFile(this.gitConfigPath, '')
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Override HOME
 | 
					    // Override HOME
 | 
				
			||||||
@@ -121,7 +124,25 @@ class GitAuthHelper {
 | 
				
			|||||||
    )
 | 
					    )
 | 
				
			||||||
    this.git.setEnvironmentVariable('HOME', this.temporaryHomePath)
 | 
					    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> {
 | 
					  async configureGlobalAuth(): Promise<void> {
 | 
				
			||||||
@@ -129,8 +150,6 @@ class GitAuthHelper {
 | 
				
			|||||||
    const newGitConfigPath = await this.configureTempGlobalConfig()
 | 
					    const newGitConfigPath = await this.configureTempGlobalConfig()
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
      // Configure the token
 | 
					      // Configure the token
 | 
				
			||||||
      await this.configureToken(newGitConfigPath, true)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      // Configure HTTPS instead of SSH
 | 
					      // Configure HTTPS instead of SSH
 | 
				
			||||||
      await this.git.tryConfigUnset(this.insteadOfKey, true)
 | 
					      await this.git.tryConfigUnset(this.insteadOfKey, true)
 | 
				
			||||||
      if (!this.settings.sshKey) {
 | 
					      if (!this.settings.sshKey) {
 | 
				
			||||||
@@ -143,7 +162,6 @@ class GitAuthHelper {
 | 
				
			|||||||
      core.info(
 | 
					      core.info(
 | 
				
			||||||
        'Encountered an error when attempting to configure token. Attempting unconfigure.'
 | 
					        'Encountered an error when attempting to configure token. Attempting unconfigure.'
 | 
				
			||||||
      )
 | 
					      )
 | 
				
			||||||
      await this.git.tryConfigUnset(this.tokenConfigKey, true)
 | 
					 | 
				
			||||||
      throw err
 | 
					      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
 | 
					      // 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(
 | 
					      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
 | 
					        // 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
 | 
					        this.settings.nestedSubmodules
 | 
				
			||||||
      )
 | 
					      )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -190,7 +208,6 @@ class GitAuthHelper {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  async removeAuth(): Promise<void> {
 | 
					  async removeAuth(): Promise<void> {
 | 
				
			||||||
    await this.removeSsh()
 | 
					    await this.removeSsh()
 | 
				
			||||||
    await this.removeToken()
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  async removeGlobalConfig(): Promise<void> {
 | 
					  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> {
 | 
					  private async replaceTokenPlaceholder(configPath: string): Promise<void> {
 | 
				
			||||||
    assert.ok(configPath, 'configPath is not defined')
 | 
					    assert.ok(configPath, 'configPath is not defined')
 | 
				
			||||||
    let content = (await fs.promises.readFile(configPath)).toString()
 | 
					    let content = (await fs.promises.readFile(configPath)).toString()
 | 
				
			||||||
@@ -345,11 +334,6 @@ class GitAuthHelper {
 | 
				
			|||||||
    await this.removeGitConfig(SSH_COMMAND_KEY)
 | 
					    await this.removeGitConfig(SSH_COMMAND_KEY)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private async removeToken(): Promise<void> {
 | 
					 | 
				
			||||||
    // HTTP extra header
 | 
					 | 
				
			||||||
    await this.removeGitConfig(this.tokenConfigKey)
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  private async removeGitConfig(
 | 
					  private async removeGitConfig(
 | 
				
			||||||
    configKey: string,
 | 
					    configKey: string,
 | 
				
			||||||
    submoduleOnly: boolean = false
 | 
					    submoduleOnly: boolean = false
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user