Skip to content

Commit b0b3083

Browse files
authored
Merge pull request #2195 from jmyersmsft/onPremSwitching
Ignore empty path filters, disable cred provider on hosted, disable config creds on on-prem (M103)
2 parents afefbcb + 5f087b1 commit b0b3083

File tree

10 files changed

+110
-16
lines changed

10 files changed

+110
-16
lines changed

Tasks/Common/nuget-task-common/NuGetConfigHelper.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,9 @@ export class NuGetConfigHelper {
4444
};
4545

4646
if (this._nugetConfigPath) {
47-
tl.cp("-f", this._nugetConfigPath, this.tempNugetConfigPath);
47+
// don't use cp as that copies the read-only flag, and tfvc sets that on files
48+
let content = fs.readFileSync(this._nugetConfigPath);
49+
fs.writeFileSync(this.tempNugetConfigPath, content);
4850
}
4951
else {
5052
// small file, use writeFileSync

Tasks/Common/nuget-task-common/NuGetToolRunner.ts

Lines changed: 77 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {ToolRunner, IExecOptions, IExecResult} from 'vsts-task-lib/toolrunner';
66
import * as auth from "./Authentication"
77
import * as os from 'os';
88
import * as path from 'path';
9+
import * as url from 'url';
910

1011
interface EnvironmentDictionary { [key: string]: string }
1112

@@ -50,6 +51,7 @@ function prepareNuGetExeEnvironment(input: EnvironmentDictionary, settings: NuGe
5051
env['NUGET_CREDENTIAL_PROVIDER_OVERRIDE_DEFAULT'] = 'true';
5152

5253
if (credProviderPath) {
54+
tl.debug(`credProviderPath = ${credProviderPath}`);
5355
env['NUGET_CREDENTIALPROVIDERS_PATH'] = credProviderPath;
5456
}
5557

@@ -155,6 +157,79 @@ export function locateNuGetExe(userNuGetExePath: string): string {
155157
return toolPath;
156158
}
157159

160+
function isHosted(): boolean {
161+
// not an ideal way to detect hosted, but there isn't a variable for it, and we can't make network calls from here
162+
// due to proxy issues.
163+
const collectionUri = tl.getVariable("System.TeamFoundationCollectionUri");
164+
const parsedCollectionUri = url.parse(collectionUri);
165+
return /\.visualstudio\.com$/i.test(parsedCollectionUri.hostname);
166+
}
167+
168+
// Currently, there is a race condition of some sort that causes nuget to not send credentials sometimes
169+
// when using the credential provider.
170+
// Unfortunately, on on-premises TFS, we must use credential provider to override NTLM auth with the build
171+
// identity's token.
172+
// Therefore, we are enabling credential provider on on-premises and disabling it on hosted. We allow for test
173+
// instances by an override variable.
174+
175+
export function isCredentialProviderEnabled(): boolean {
176+
// set NuGet.ForceEnableCredentialProvider to "true" to force allowing the credential provider flow, "false"
177+
// to force *not* allowing the credential provider flow, or unset/anything else to fall through to the
178+
// hosted environment detection logic
179+
const credentialProviderOverrideFlag = tl.getVariable("NuGet.ForceEnableCredentialProvider");
180+
if (credentialProviderOverrideFlag === "true") {
181+
tl.debug("Credential provider is force-enabled for testing purposes.");
182+
return true;
183+
}
184+
185+
if (credentialProviderOverrideFlag === "false") {
186+
tl.debug("Credential provider is force-disabled for testing purposes.");
187+
return false;
188+
}
189+
190+
if (isHosted()) {
191+
tl.debug("Credential provider is disabled on hosted.");
192+
return false;
193+
}
194+
else {
195+
tl.debug("Credential provider is enabled.")
196+
return true;
197+
}
198+
}
199+
200+
export function isCredentialConfigEnabled(): boolean {
201+
// set NuGet.ForceEnableCredentialConfig to "true" to force allowing config-based credential flow, "false"
202+
// to force *not* allowing config-based credential flow, or unset/anything else to fall through to the
203+
// hosted environment detection logic
204+
const credentialConfigOverrideFlag = tl.getVariable("NuGet.ForceEnableCredentialConfig");
205+
if (credentialConfigOverrideFlag === "true") {
206+
tl.debug("Credential config is force-enabled for testing purposes.");
207+
return true;
208+
}
209+
210+
if (credentialConfigOverrideFlag === "false") {
211+
tl.debug("Credential config is force-disabled for testing purposes.");
212+
return false;
213+
}
214+
215+
// credentials in config will always fail for on-prem
216+
if (!isHosted()) {
217+
tl.debug("Credential config is disabled on on-premises TFS.");
218+
return false;
219+
}
220+
else {
221+
tl.debug("Credential config is enabled.")
222+
return true;
223+
}
224+
}
225+
158226
export function locateCredentialProvider(): string {
159-
return locateTool('CredentialProvider.TeamBuild.exe');
160-
}
227+
const credentialProviderLocation = locateTool('CredentialProvider.TeamBuild.exe');
228+
if(!credentialProviderLocation) {
229+
tl.debug("Credential provider is not present.");
230+
return null;
231+
}
232+
233+
return isCredentialProviderEnabled() ? credentialProviderLocation : null;
234+
}
235+

Tasks/Common/nuget-task-common/Utility.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ import * as os from 'os';
66

77
// Attempts to resolve paths the same way the legacy PowerShell's Find-Files worked
88
export function resolveFilterSpec(filterSpec: string, basePath?: string, allowEmptyMatch?: boolean): string[] {
9-
let patterns = filterSpec.split(";");
9+
// make sure to remove any empty entries, or else we'll accidentally match the current directory.
10+
let patterns = filterSpec.split(";").map(x => x.trim()).filter(x => !!x);
1011
let result = new Set<string>();
1112

1213
patterns.forEach(pattern => {
@@ -23,6 +24,8 @@ export function resolveFilterSpec(filterSpec: string, basePath?: string, allowEm
2324
pattern = path.resolve(basePath, pattern);
2425
}
2526

27+
tl.debug(`pattern: ${pattern}, isNegative: ${isNegative}`);
28+
2629
let thisPatternFiles = resolveWildcardPath(pattern, true);
2730
thisPatternFiles.forEach(file => {
2831
if (isNegative) {
@@ -44,10 +47,15 @@ export function resolveFilterSpec(filterSpec: string, basePath?: string, allowEm
4447

4548
export function resolveWildcardPath(pattern: string, allowEmptyWildcardMatch?: boolean): string[] {
4649
let isWindows = os.platform() === 'win32';
47-
50+
4851
// Resolve files for the specified value or pattern
4952
var filesList: string[];
50-
if (pattern.indexOf('*') == -1 && pattern.indexOf('?') == -1) {
53+
54+
// empty patterns match nothing (otherwise they will effectively match the current directory)
55+
if (!pattern) {
56+
filesList = [];
57+
}
58+
else if (pattern.indexOf('*') == -1 && pattern.indexOf('?') == -1) {
5159

5260
// No pattern found, check literal path to a single file
5361
tl.checkPath(pattern, 'files');

Tasks/NuGetInstaller/nugetinstaller.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ var solution = tl.getPathInput('solution', true, false);
3535
var filesList = nutil.resolveFilterSpec(solution, tl.getVariable('System.DefaultWorkingDirectory') || process.cwd());
3636
filesList.forEach(solutionFile => {
3737
if (!tl.stats(solutionFile).isFile()) {
38-
throw new Error(tl.loc('NotARegularFile'));
38+
throw new Error(tl.loc('NotARegularFile', solutionFile));
3939
}
4040
});
4141

@@ -67,7 +67,7 @@ var serviceUri = tl.getEndpointUrl("SYSTEMVSSCONNECTION", false);
6767

6868
//find nuget location to use
6969
var nuGetPathToUse = ngToolRunner.locateNuGetExe(userNuGetPath);
70-
var credProviderPath = null;//ngToolRunner.locateCredentialProvider();
70+
var credProviderPath = ngToolRunner.locateCredentialProvider();
7171

7272
var credProviderDir: string = null;
7373
if (credProviderPath) {
@@ -123,7 +123,10 @@ locationHelpers.assumeNuGetUriPrefixes(serviceUri)
123123

124124
var configFilePromise = Q<string>(nugetConfigPath);
125125
var credCleanup = () => { return };
126-
if (!credProviderDir || (userNuGetPath && preCredProviderNuGet)) {
126+
if (!ngToolRunner.isCredentialConfigEnabled()) {
127+
tl.debug("Not configuring credentials in nuget.config");
128+
}
129+
else if (!credProviderDir || (userNuGetPath && preCredProviderNuGet)) {
127130
if (nugetConfigPath) {
128131
var nuGetConfigHelper = new NuGetConfigHelper(nuGetPathToUse, nugetConfigPath, authInfo, environmentSettings);
129132
configFilePromise = nuGetConfigHelper.getSourcesFromConfig()

Tasks/NuGetInstaller/task.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"version": {
1010
"Major": 0,
1111
"Minor": 2,
12-
"Patch": 6
12+
"Patch": 7
1313
},
1414
"minimumAgentVersion": "1.83.0",
1515
"groups": [

Tasks/NuGetInstaller/task.loc.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"version": {
1010
"Major": 0,
1111
"Minor": 2,
12-
"Patch": 6
12+
"Patch": 7
1313
},
1414
"minimumAgentVersion": "1.83.0",
1515
"groups": [

Tasks/NugetPublisher/nugetpublisher.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ var searchPattern = tl.getPathInput('searchPattern', true, false);
3636
var filesList = nutil.resolveFilterSpec(searchPattern, tl.getVariable('System.DefaultWorkingDirectory') || process.cwd());
3737
filesList.forEach(packageFile => {
3838
if (!tl.stats(packageFile).isFile()) {
39-
throw new Error(tl.loc('NotARegularFile'));
39+
throw new Error(tl.loc('NotARegularFile', packageFile));
4040
}
4141
});
4242

@@ -64,7 +64,7 @@ var serviceUri = tl.getEndpointUrl("SYSTEMVSSCONNECTION", false);
6464

6565
//find nuget location to use
6666
var nuGetPathToUse = ngToolRunner.locateNuGetExe(userNuGetPath);
67-
var credProviderPath = null;//ngToolRunner.locateCredentialProvider();
67+
var credProviderPath = ngToolRunner.locateCredentialProvider();
6868

6969
var credProviderDir: string = null;
7070
if (credProviderPath) {
@@ -123,7 +123,10 @@ locationHelpers.assumeNuGetUriPrefixes(serviceUri)
123123
var feedUri: string;
124124
var credCleanup = () => { return };
125125
if (nuGetFeedType == "internal") {
126-
if (!credProviderDir || (userNuGetPath && preCredProviderNuGet)) {
126+
if (!ngToolRunner.isCredentialConfigEnabled()) {
127+
tl.debug("Not configuring credentials in nuget.config");
128+
}
129+
else if (!credProviderDir || (userNuGetPath && preCredProviderNuGet)) {
127130
var nuGetConfigHelper = new NuGetConfigHelper(nuGetPathToUse, null, authInfo, environmentSettings);
128131
nuGetConfigHelper.setSources([{ feedName: "internalFeed", feedUri: internalFeedUri }]);
129132
configFilePromise = Q(nuGetConfigHelper.tempNugetConfigPath);

Tasks/NugetPublisher/task.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"version": {
1010
"Major": 0,
1111
"Minor": 2,
12-
"Patch": 6
12+
"Patch": 7
1313
},
1414
"demands": [
1515
"Cmd"

Tasks/NugetPublisher/task.loc.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"version": {
1010
"Major": 0,
1111
"Minor": 2,
12-
"Patch": 6
12+
"Patch": 7
1313
},
1414
"demands": [
1515
"Cmd"

definitions/nuget-task-common.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,8 @@ declare module 'nuget-task-common/NuGetToolRunner' {
107107
}
108108
export function createNuGetToolRunner(nuGetExePath: string, settings: NuGetEnvironmentSettings): NuGetToolRunner;
109109
export function locateNuGetExe(userNuGetExePath: string): string;
110+
export function isCredentialProviderEnabled(): boolean;
111+
export function isCredentialConfigEnabled(): boolean;
110112
export function locateCredentialProvider(): string;
111113

112114
}
@@ -123,6 +125,7 @@ declare module 'nuget-task-common/NuGetConfigHelper' {
123125
private _nugetConfigPath;
124126
private _authInfo;
125127
private _environmentSettings;
128+
private tempNugetConfigBaseDir;
126129
private tempNugetConfigDir;
127130
private tempNugetConfigFileName;
128131
tempNugetConfigPath: string;

0 commit comments

Comments
 (0)