diff --git a/src/snyk/common/analytics/itly.ts b/src/snyk/common/analytics/itly.ts index 90f7db690..684c24acb 100644 --- a/src/snyk/common/analytics/itly.ts +++ b/src/snyk/common/analytics/itly.ts @@ -64,7 +64,7 @@ export class Iteratively implements IAnalytics { private readonly user: User, private logger: ILog, private shouldReportEvents: boolean, - private isFedramp: boolean, + private analyticsPermitted: boolean, private isDevelopment: boolean, private snykConfiguration?: SnykConfiguration, ) {} @@ -75,7 +75,7 @@ export class Iteratively implements IAnalytics { } load(): Iteratively | null { - if (!this.shouldReportEvents || this.isFedramp) { + if (!this.shouldReportEvents || !this.analyticsPermitted) { this.logger.debug(`Analytics are disabled. No analytics will be collected.`); return null; } diff --git a/src/snyk/common/configuration/configuration.ts b/src/snyk/common/configuration/configuration.ts index 602f3ba40..6d235f346 100644 --- a/src/snyk/common/configuration/configuration.ts +++ b/src/snyk/common/configuration/configuration.ts @@ -99,6 +99,8 @@ export interface IConfiguration { isFedramp: boolean; + analyticsPermitted: boolean; + severityFilter: SeverityFilter; scanningMode: string | undefined; @@ -120,6 +122,7 @@ export class Configuration implements IConfiguration { private readonly defaultAuthHost = 'https://snyk.io'; private readonly defaultOssApiEndpoint = `${this.defaultAuthHost}/api/v1`; private readonly defaultBaseApiHost = 'https://api.snyk.io'; + private readonly analyticsPermittedEnvironments = { 'app.snyk.io': true, 'app.us.snyk.io': true }; constructor(private processEnv: NodeJS.ProcessEnv = process.env, private workspace: IVSCodeWorkspace) {} @@ -206,6 +209,13 @@ export class Configuration implements IConfiguration { return isFedrampDomain; } + get analyticsPermitted(): boolean { + if (!this.customEndpoint) return true; + + const hostname = new URL(this.customEndpoint).hostname; + return hostname in this.analyticsPermittedEnvironments + } + get snykOssApiEndpoint(): string { if (this.customEndpoint) { return this.customEndpoint; // E.g. https://app.eu.snyk.io/api diff --git a/src/snyk/extension.ts b/src/snyk/extension.ts index 669c942b2..371cd8418 100644 --- a/src/snyk/extension.ts +++ b/src/snyk/extension.ts @@ -125,7 +125,7 @@ class SnykExtension extends SnykLib implements IExtension { this.user, Logger, configuration.shouldReportEvents, - configuration.isFedramp, + configuration.analyticsPermitted, configuration.isDevelopment, snykConfiguration, ); diff --git a/src/test/unit/common/analytics/itly.test.ts b/src/test/unit/common/analytics/itly.test.ts index 02a6c5858..a5c0570ed 100644 --- a/src/test/unit/common/analytics/itly.test.ts +++ b/src/test/unit/common/analytics/itly.test.ts @@ -9,15 +9,15 @@ suite('Iteratively', () => { const isDevelopment = false; suite('.load()', () => { - suite('when connecting to FEDRAMP endpoints', () => { - const isFedramp = true; + suite('when analytics are not permitted', () => { + const analyticsPermitted = false; [true, false].forEach(shouldReportEvents => { test(`Returns "null" when shouldReportEvents == ${shouldReportEvents}`, () => { const iteratively = new Iteratively( new User(), new LoggerMock(), shouldReportEvents, - isFedramp, + analyticsPermitted, isDevelopment, snykConfig, ); @@ -29,11 +29,18 @@ suite('Iteratively', () => { }); }); - suite('when connecting to non-FEDRAMP endpoints', () => { - const isFedramp = false; + suite('when analytics are permitted', () => { + const analyticsPermitted = true; test('Returns "null" when shouldReportEvents == false', () => { - const iteratively = new Iteratively(new User(), new LoggerMock(), false, isFedramp, isDevelopment, snykConfig); + const iteratively = new Iteratively( + new User(), + new LoggerMock(), + false, + analyticsPermitted, + isDevelopment, + snykConfig, + ); const result = iteratively.load(); @@ -41,7 +48,14 @@ suite('Iteratively', () => { }); test('Returns "Iteratively" when shouldReportEvents == true', () => { - const iteratively = new Iteratively(new User(), new LoggerMock(), true, isFedramp, isDevelopment, snykConfig); + const iteratively = new Iteratively( + new User(), + new LoggerMock(), + true, + analyticsPermitted, + isDevelopment, + snykConfig, + ); const result = iteratively.load(); diff --git a/src/test/unit/common/configuration.test.ts b/src/test/unit/common/configuration.test.ts index 3f95c8ddc..797956f7b 100644 --- a/src/test/unit/common/configuration.test.ts +++ b/src/test/unit/common/configuration.test.ts @@ -229,4 +229,45 @@ suite('Configuration', () => { strictEqual(configuration.isFedramp, false); }); }); + + suite('.analyticsPermitted()', () => { + test('returns true when no custom endpoint configured', () => { + const workspace = stubWorkspaceConfiguration(ADVANCED_CUSTOM_ENDPOINT, undefined); + + const configuration = new Configuration({}, workspace); + strictEqual(configuration.analyticsPermitted, true); + }); + + test('returns true for app.snyk.io', () => { + const customEndpoint = 'https://app.snyk.io'; + const workspace = stubWorkspaceConfiguration(ADVANCED_CUSTOM_ENDPOINT, customEndpoint); + + const configuration = new Configuration({}, workspace); + strictEqual(configuration.analyticsPermitted, true); + }); + + test('returns true for app.us.snyk.io', () => { + const customEndpoint = 'https://app.us.snyk.io'; + const workspace = stubWorkspaceConfiguration(ADVANCED_CUSTOM_ENDPOINT, customEndpoint); + + const configuration = new Configuration({}, workspace); + strictEqual(configuration.analyticsPermitted, true); + }); + + test('returns false for app.snykgov.io', () => { + const customEndpoint = 'https://app.snykgov.io'; + const workspace = stubWorkspaceConfiguration(ADVANCED_CUSTOM_ENDPOINT, customEndpoint); + + const configuration = new Configuration({}, workspace); + strictEqual(configuration.analyticsPermitted, false); + }); + + test('returns false for app.eu.snyk.io', () => { + const customEndpoint = 'https://app.eu.snyk.io'; + const workspace = stubWorkspaceConfiguration(ADVANCED_CUSTOM_ENDPOINT, customEndpoint); + + const configuration = new Configuration({}, workspace); + strictEqual(configuration.analyticsPermitted, false); + }); + }); });