Skip to content

Commit

Permalink
feat: disable amplitude and sentry when using fedramp endpoints (#372)
Browse files Browse the repository at this point in the history
* feat: disable sending amplitude and sentry events when using fedramp endpoints
  • Loading branch information
j-luong authored Aug 31, 2023
1 parent dca2c24 commit 5fa297c
Show file tree
Hide file tree
Showing 8 changed files with 120 additions and 8 deletions.
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,27 @@
# Snyk Security - Code and Open Source Dependencies Changelog

## [1.21.5]

### Added

- Fedrammp endpoints will not send Sentry/Amplitude events

## [1.21.4]

### Changed

- Use Language Server to retrieve vulnerability count for HTML files

## [1.21.1]

### Fixed

- Snyk Learn links

## [1.21.0]

### Fixed

- Plugin Initialization

## [1.20.3]
Expand All @@ -28,6 +39,7 @@
## [1.18.3]

### Added

- Added support for OAuth2 authentication
- Snyk Learn: now uses language server to retrieve lessons

Expand Down
9 changes: 6 additions & 3 deletions src/snyk/common/analytics/itly.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import SegmentPlugin from '@itly/plugin-segment-node';
import itly, {
AnalysisIsReadyProperties,
AnalysisIsTriggeredProperties as _AnalysisIsTriggeredProperties,
FalsePositiveIsSubmittedProperties,
IssueHoverIsDisplayedProperties,
IssueInTreeIsClickedProperties,
QuickFixIsDisplayedProperties as _QuickFixIsDisplayedProperties,
ScanModeIsSelectedProperties,
TrackOptions,
AnalysisIsTriggeredProperties as _AnalysisIsTriggeredProperties,
QuickFixIsDisplayedProperties as _QuickFixIsDisplayedProperties,
} from '../../../ampli';
import { Configuration } from '../configuration/configuration';
import { SnykConfiguration } from '../configuration/snykConfiguration';
Expand Down Expand Up @@ -67,6 +67,7 @@ export class Iteratively implements IAnalytics {
private readonly user: User,
private logger: ILog,
private shouldReportEvents: boolean,
private isFedramp: boolean,
private isDevelopment: boolean,
private snykConfiguration?: SnykConfiguration,
) {}
Expand All @@ -77,9 +78,11 @@ export class Iteratively implements IAnalytics {
}

load(): Iteratively | null {
if (!this.shouldReportEvents) {
if (!this.shouldReportEvents || this.isFedramp) {
this.logger.debug(`Analytics are disabled. No analytics will be collected.`);
return null;
}
this.logger.debug(`Analytics are enabled. Analytics will be collected.`);

const segmentWriteKey = this.snykConfiguration?.segmentWriteKey;
if (!segmentWriteKey) {
Expand Down
28 changes: 28 additions & 0 deletions src/snyk/common/configuration/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ export interface IConfiguration {

getInsecure(): boolean;

isFedramp: boolean;

severityFilter: SeverityFilter;

scanningMode: string | undefined;
Expand All @@ -109,6 +111,8 @@ export interface IConfiguration {
getTrustedFolders(): string[];

setTrustedFolders(trustedFolders: string[]): Promise<void>;

setEndpoint(endpoint: string): Promise<void>;
}

export class Configuration implements IConfiguration {
Expand Down Expand Up @@ -180,6 +184,30 @@ export class Configuration implements IConfiguration {
return this.defaultAuthHost;
}

async setEndpoint(endpoint: string): Promise<void> {
await this.workspace.updateConfiguration(
CONFIGURATION_IDENTIFIER,
this.getConfigName(ADVANCED_CUSTOM_ENDPOINT),
endpoint.toString(),
true,
);
}

get isFedramp(): boolean {
if (!this.customEndpoint) return false;

// FEDRAMP URL e.g. https://api.fedramp.snykgov.io
const endpoint = new URL(this.customEndpoint);

// hostname validation
const hostnameParts = endpoint.hostname.split('.');
if (hostnameParts.length < 3) return false;

const isFedrampInstance = hostnameParts[1].includes('fedramp');
const isFedrampDomain = hostnameParts[2].includes('snykgov') && hostnameParts[3].includes('io');
return isFedrampDomain && isFedrampInstance;
}

get snykOssApiEndpoint(): string {
if (this.customEndpoint) {
return this.customEndpoint; // E.g. https://app.eu.snyk.io/api
Expand Down
2 changes: 1 addition & 1 deletion src/snyk/common/error/errorReporter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export class ErrorReporter {
beforeSend(event) {
// drop reporting, if user doesn't want to report events here
// https://github.com/getsentry/sentry-javascript/issues/2039
if (!userConfig.shouldReportErrors) {
if (!userConfig.shouldReportErrors || userConfig.isFedramp) {
return null;
}

Expand Down
1 change: 1 addition & 0 deletions src/snyk/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ class SnykExtension extends SnykLib implements IExtension {
this.user,
Logger,
configuration.shouldReportEvents,
configuration.isFedramp,
configuration.isDevelopment,
snykConfiguration,
);
Expand Down
14 changes: 11 additions & 3 deletions src/test/integration/analytics.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { strictEqual } from 'assert';
import { configuration } from '../../snyk/common/configuration/instance';
import * as vscode from 'vscode';
import { VSCODE_VIEW_CONTAINER_COMMAND } from '../../snyk/common/constants/commands';
import * as sinon from 'sinon';
import * as vscode from 'vscode';
import itly from '../../ampli';
import { configuration } from '../../snyk/common/configuration/instance';
import { VSCODE_VIEW_CONTAINER_COMMAND } from '../../snyk/common/constants/commands';

suite('Analytics', () => {
let welcomeIsViewed: sinon.SinonSpy;
Expand Down Expand Up @@ -34,4 +34,12 @@ suite('Analytics', () => {

strictEqual(welcomeIsViewed.notCalled, true);
});

test('"Welcome Is Viewed" not tracked if using fedramp endpoint', async () => {
await configuration.setEndpoint('https://api.fedramp.snykgov.io');
await vscode.commands.executeCommand('workbench.action.toggleSidebarVisibility');
await vscode.commands.executeCommand(VSCODE_VIEW_CONTAINER_COMMAND);

strictEqual(welcomeIsViewed.notCalled, true);
});
});
52 changes: 52 additions & 0 deletions src/test/unit/common/analytics/itly.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { strictEqual } from 'assert';
import { Iteratively } from '../../../../snyk/common/analytics/itly';
import { SnykConfiguration } from '../../../../snyk/common/configuration/snykConfiguration';
import { User } from '../../../../snyk/common/user';
import { LoggerMock } from '../../mocks/logger.mock';

suite.only('Iteratively', () => {
const snykConfig = {} as SnykConfiguration;
const isDevelopment = false;

suite('.load()', () => {
suite('when connecting to FEDRAMP endpoints', () => {
const isFedramp = true;
[true, false].forEach(shouldReportEvents => {
test(`Returns "null" when shouldReportEvents == ${shouldReportEvents}`, () => {
const iteratively = new Iteratively(
new User(),
new LoggerMock(),
shouldReportEvents,
isFedramp,
isDevelopment,
snykConfig,
);

const result = iteratively.load();

strictEqual(result, null);
});
});
});

suite('when connecting to non-FEDRAMP endpoints', () => {
const isFedramp = false;

test('Returns "null" when shouldReportEvents == false', () => {
const iteratively = new Iteratively(new User(), new LoggerMock(), false, isFedramp, isDevelopment, snykConfig);

const result = iteratively.load();

strictEqual(result, null);
});

test('Returns "Iteratively" when shouldReportEvents == true', () => {
const iteratively = new Iteratively(new User(), new LoggerMock(), true, isFedramp, isDevelopment, snykConfig);

const result = iteratively.load();

strictEqual(result instanceof Iteratively, true);
});
});
});
});
10 changes: 9 additions & 1 deletion src/test/unit/common/error/errorReporter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ suite('ErrorReporter', () => {
let configuration: IConfiguration;

setup(async () => {
configuration = {} as IConfiguration;
configuration = { isFedramp: false } as IConfiguration;
await ErrorReporter.init(configuration, snykConfig, '', envMock, new LoggerMock(), sentryTransport);
});

Expand Down Expand Up @@ -59,4 +59,12 @@ suite('ErrorReporter', () => {

strictEqual(testkit.reports().length, 0);
});

test("Doesn't report error when isFedramp == true", () => {
configuration.isFedramp = true;

ErrorReporter.capture(new Error());

strictEqual(testkit.reports().length, 0);
});
});

0 comments on commit 5fa297c

Please sign in to comment.