diff --git a/CHANGELOG.md b/CHANGELOG.md
index c6706c5..7d58047 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,10 @@
## [2.0.0] - Unreleased
### Changes
+- add folder trust feature
+
+## [2.0.0] - v20221115.132308
+### Changes
- adds configuration wizard for custom endpoints
## [2.0.0] - v20221007.135736
diff --git a/plugin/META-INF/MANIFEST.MF b/plugin/META-INF/MANIFEST.MF
index 3d751ed..7e32b93 100644
--- a/plugin/META-INF/MANIFEST.MF
+++ b/plugin/META-INF/MANIFEST.MF
@@ -10,7 +10,7 @@ Require-Bundle: org.eclipse.ui,
org.eclipse.core.runtime,
org.eclipse.jdt.core,
org.eclipse.core.resources,
- org.eclipse.lsp4e;bundle-version="0.13.9",
+ org.eclipse.lsp4e;bundle-version="[0.13.9,0.14.0.qualifier]",
org.eclipse.lsp4e.jdt;bundle-version="0.10.1",
org.eclipse.equinox.security,
org.eclipse.equinox.security.ui,
@@ -33,5 +33,5 @@ Bundle-ClassPath: .,
target/dependency/httpcore-4.4.15.jar,
target/dependency/jackson-annotations-2.13.4.jar,
target/dependency/jackson-core-2.13.4.jar,
- target/dependency/jackson-databind-2.13.4.jar,
+ target/dependency/jackson-databind-2.13.4.2.jar,
target/dependency/javax.inject-1.jar
diff --git a/plugin/build.properties b/plugin/build.properties
index d38ca1b..44c1bbd 100644
--- a/plugin/build.properties
+++ b/plugin/build.properties
@@ -14,7 +14,7 @@ bin.includes = plugin.xml,\
target/dependency/httpcore-4.4.15.jar,\
target/dependency/jackson-annotations-2.13.4.jar,\
target/dependency/jackson-core-2.13.4.jar,\
- target/dependency/jackson-databind-2.13.4.jar,\
+ target/dependency/jackson-databind-2.13.4.2.jar,\
target/dependency/javax.inject-1.jar
src.includes =src/,\
icons/
diff --git a/plugin/io.snyk.eclipse.plugin.eml b/plugin/io.snyk.eclipse.plugin.eml
index 5ef4faa..ecca7d7 100644
--- a/plugin/io.snyk.eclipse.plugin.eml
+++ b/plugin/io.snyk.eclipse.plugin.eml
@@ -19,22 +19,22 @@
-
+
-
+
-
-
+
+
-
-
-
+
+
+
diff --git a/plugin/pom.xml b/plugin/pom.xml
index 5584584..6870cb6 100644
--- a/plugin/pom.xml
+++ b/plugin/pom.xml
@@ -29,7 +29,7 @@
com.fasterxml.jackson.core
jackson-databind
- 2.13.4
+ 2.13.4.2
jar
diff --git a/plugin/src/main/java/io/snyk/eclipse/plugin/properties/PreferencesPage.java b/plugin/src/main/java/io/snyk/eclipse/plugin/properties/PreferencesPage.java
index 2960692..a3f7943 100644
--- a/plugin/src/main/java/io/snyk/eclipse/plugin/properties/PreferencesPage.java
+++ b/plugin/src/main/java/io/snyk/eclipse/plugin/properties/PreferencesPage.java
@@ -8,6 +8,9 @@
import io.snyk.languageserver.LsRuntimeEnvironment;
import io.snyk.languageserver.download.HttpClientFactory;
import io.snyk.languageserver.download.LsBinaries;
+
+import java.io.File;
+
import org.eclipse.core.net.proxy.IProxyData;
import org.eclipse.jface.preference.BooleanFieldEditor;
import org.eclipse.jface.preference.FieldEditor;
@@ -19,103 +22,114 @@
import org.eclipse.ui.IWorkbenchPreferencePage;
public class PreferencesPage extends FieldEditorPreferencePage implements IWorkbenchPreferencePage {
- private BooleanFieldEditor snykCodeCheckbox;
-
- public PreferencesPage() {
- super(GRID);
- }
-
- @Override
- public void init(IWorkbench workbench) {
- setPreferenceStore(io.snyk.eclipse.plugin.properties.preferences.Preferences.getInstance().getStore());
- setMessage("Snyk Preferences");
- }
-
- @Override
- protected void createFieldEditors() {
- TokenFieldEditor tokenField = new TokenFieldEditor(
- io.snyk.eclipse.plugin.properties.preferences.Preferences.getInstance(),
- io.snyk.eclipse.plugin.properties.preferences.Preferences.AUTH_TOKEN_KEY, "Snyk API Token:",
- getFieldEditorParent());
- addField(tokenField);
- addField(new StringFieldEditor(io.snyk.eclipse.plugin.properties.preferences.Preferences.PATH_KEY, "Path:",
- getFieldEditorParent()));
- addField(new StringFieldEditor(io.snyk.eclipse.plugin.properties.preferences.Preferences.ENDPOINT_KEY,
- "Custom Endpoint:", getFieldEditorParent()));
- addField(new BooleanFieldEditor(io.snyk.eclipse.plugin.properties.preferences.Preferences.INSECURE_KEY,
- "Allow unknown certificate authorities", getFieldEditorParent()));
-
- addField(space());
+ private BooleanFieldEditor snykCodeCheckbox;
+
+ public PreferencesPage() {
+ super(GRID);
+ }
+
+ @Override
+ public void init(IWorkbench workbench) {
+ setPreferenceStore(io.snyk.eclipse.plugin.properties.preferences.Preferences.getInstance().getStore());
+ setMessage("Snyk Preferences");
+ }
+
+ @Override
+ protected void createFieldEditors() {
+ TokenFieldEditor tokenField = new TokenFieldEditor(
+ io.snyk.eclipse.plugin.properties.preferences.Preferences.getInstance(),
+ io.snyk.eclipse.plugin.properties.preferences.Preferences.AUTH_TOKEN_KEY, "Snyk API Token:",
+ getFieldEditorParent());
+ addField(tokenField);
+ addField(new StringFieldEditor(io.snyk.eclipse.plugin.properties.preferences.Preferences.PATH_KEY, "Path:",
+ getFieldEditorParent()));
+ addField(new StringFieldEditor(io.snyk.eclipse.plugin.properties.preferences.Preferences.ENDPOINT_KEY,
+ "Custom Endpoint:", getFieldEditorParent()));
+ addField(new BooleanFieldEditor(io.snyk.eclipse.plugin.properties.preferences.Preferences.INSECURE_KEY,
+ "Allow unknown certificate authorities", getFieldEditorParent()));
+
+ addField(space());
addField(new LabelFieldEditor("The following options involve the Snyk Language Server.",
getFieldEditorParent()));
- addField(new LabelFieldEditor(
- "Activating Snyk Code will cause upload of source code to Snyk or the given endpoint address.",
- getFieldEditorParent()));
- addField(space());
+ addField(new LabelFieldEditor(
+ "Activating Snyk Code will cause upload of source code to Snyk or the given endpoint address.",
+ getFieldEditorParent()));
+ addField(space());
addField(new BooleanFieldEditor(
io.snyk.eclipse.plugin.properties.preferences.Preferences.ACTIVATE_SNYK_OPEN_SOURCE,
- "Snyk Open Source enabled", getFieldEditorParent()));
- snykCodeCheckbox = new BooleanFieldEditor(
- io.snyk.eclipse.plugin.properties.preferences.Preferences.ACTIVATE_SNYK_CODE, "Snyk Code enable" + "d",
- getFieldEditorParent());
-
- addField(snykCodeCheckbox);
- addField(new BooleanFieldEditor(io.snyk.eclipse.plugin.properties.preferences.Preferences.ACTIVATE_SNYK_IAC,
- "Snyk Infrastructure-as-Code enabled", getFieldEditorParent()));
-
- addField(space());
- addField(new LabelFieldEditor("Advanced options:", getFieldEditorParent()));
- addField(new StringFieldEditor(io.snyk.eclipse.plugin.properties.preferences.Preferences.ORGANIZATION_KEY,
- "Organization:", getFieldEditorParent()));
- addField(new StringFieldEditor(io.snyk.eclipse.plugin.properties.preferences.Preferences.ADDITIONAL_PARAMETERS,
- "Additional Parameters:", getFieldEditorParent()));
- addField(new StringFieldEditor(io.snyk.eclipse.plugin.properties.preferences.Preferences.ADDITIONAL_ENVIRONMENT,
- "Additional Environment:", getFieldEditorParent()));
-
- addField(space());
- BooleanFieldEditor manageBinaries = new BooleanFieldEditor(Preferences.MANAGE_BINARIES_AUTOMATICALLY,
- "Update and install Snyk binaries automatically", getFieldEditorParent());
- manageBinaries.setPropertyChangeListener((PropertyChangeEvent propertyChangeEvent) -> {
- System.out.println("managed bionaries changed");
- });
- addField(manageBinaries);
- addField(new FileFieldEditor(io.snyk.eclipse.plugin.properties.preferences.Preferences.LS_BINARY_KEY,
- "Snyk Language Server:", getFieldEditorParent()));
- addField(new FileFieldEditor(io.snyk.eclipse.plugin.properties.preferences.Preferences.CLI_PATH, "Snyk CLI:",
- getFieldEditorParent()));
-
- addField(space());
-
- addField(new BooleanFieldEditor(io.snyk.eclipse.plugin.properties.preferences.Preferences.SEND_ERROR_REPORTS,
- "Send error reports to Snyk", getFieldEditorParent()));
+ "Snyk Open Source enabled", getFieldEditorParent()));
+ snykCodeCheckbox = new BooleanFieldEditor(
+ io.snyk.eclipse.plugin.properties.preferences.Preferences.ACTIVATE_SNYK_CODE, "Snyk Code enable" + "d",
+ getFieldEditorParent());
+
+ addField(snykCodeCheckbox);
+ addField(new BooleanFieldEditor(io.snyk.eclipse.plugin.properties.preferences.Preferences.ACTIVATE_SNYK_IAC,
+ "Snyk Infrastructure-as-Code enabled", getFieldEditorParent()));
+
+ addField(space());
+ addField(new LabelFieldEditor("Advanced options:", getFieldEditorParent()));
+ addField(new StringFieldEditor(io.snyk.eclipse.plugin.properties.preferences.Preferences.ORGANIZATION_KEY,
+ "Organization:", getFieldEditorParent()));
+ addField(new StringFieldEditor(io.snyk.eclipse.plugin.properties.preferences.Preferences.ADDITIONAL_PARAMETERS,
+ "Additional Parameters:", getFieldEditorParent()));
+ addField(new StringFieldEditor(io.snyk.eclipse.plugin.properties.preferences.Preferences.ADDITIONAL_ENVIRONMENT,
+ "Additional Environment:", getFieldEditorParent()));
+
+ addField(space());
+ BooleanFieldEditor manageBinaries = new BooleanFieldEditor(Preferences.MANAGE_BINARIES_AUTOMATICALLY,
+ "Update and install Snyk binaries automatically", getFieldEditorParent());
+ manageBinaries.setPropertyChangeListener((PropertyChangeEvent propertyChangeEvent) -> {
+ System.out.println("managed bionaries changed");
+ });
+ addField(manageBinaries);
+ addField(new FileFieldEditor(io.snyk.eclipse.plugin.properties.preferences.Preferences.LS_BINARY_KEY,
+ "Snyk Language Server:", getFieldEditorParent()));
+ addField(new FileFieldEditor(io.snyk.eclipse.plugin.properties.preferences.Preferences.CLI_PATH, "Snyk CLI:",
+ getFieldEditorParent()));
+
+ addField(space());
+
+ addField(new BooleanFieldEditor(io.snyk.eclipse.plugin.properties.preferences.Preferences.SEND_ERROR_REPORTS,
+ "Send error reports to Snyk", getFieldEditorParent()));
addField(new BooleanFieldEditor(Preferences.ENABLE_TELEMETRY, "Send usage statistics to Snyk",
getFieldEditorParent()));
- disableSnykCodeIfOrgDisabled();
- }
-
- private FieldEditor space() {
- return new LabelFieldEditor("", getFieldEditorParent());
- }
-
- @Override
- public boolean performOk() {
- boolean superOK = super.performOk();
- var snykView = SnykStartup.getSnykView();
- snykView.disableRunAbortActions();
- snykView.toggleRunActionEnablement();
- disableSnykCodeIfOrgDisabled();
-
- new LsConfigurationUpdater().configurationChanged();
- return superOK;
- }
-
- private void disableSnykCodeIfOrgDisabled() {
- var apiClient = new ApiClient();
- if (snykCodeCheckbox.getBooleanValue() && !apiClient.checkSnykCodeEnablement()) {
- String message = "Snyk Code disabled, because it is not enabled for your organization. After you close this preference page, it will stay disabled.";
- snykCodeCheckbox.setLabelText(snykCodeCheckbox.getLabelText()+" ("+message+")");
- SnykLogger.logInfo(message);
- }
- }
+
+ addField(space());
+
+ addField(new LabelFieldEditor(
+ "Only trusted paths are scanned by Snyk. The Trusted Folders setting allows to specify, which \n"
+ + "paths are safe to scan. Every path below a given path is considered safe to scan. \n"
+ + "Please separate entries with \"" + File.pathSeparator + "\".",
+ getFieldEditorParent()));
+ addField(new StringFieldEditor(io.snyk.eclipse.plugin.properties.preferences.Preferences.TRUSTED_FOLDERS,
+ "Trusted Folders:", getFieldEditorParent()));
+
+ disableSnykCodeIfOrgDisabled();
+ }
+
+ private FieldEditor space() {
+ return new LabelFieldEditor("", getFieldEditorParent());
+ }
+
+ @Override
+ public boolean performOk() {
+ boolean superOK = super.performOk();
+ var snykView = SnykStartup.getSnykView();
+ snykView.disableRunAbortActions();
+ snykView.toggleRunActionEnablement();
+ disableSnykCodeIfOrgDisabled();
+
+ new LsConfigurationUpdater().configurationChanged();
+ return superOK;
+ }
+
+ private void disableSnykCodeIfOrgDisabled() {
+ var apiClient = new ApiClient();
+ if (snykCodeCheckbox.getBooleanValue() && !apiClient.checkSnykCodeEnablement()) {
+ String message = "Snyk Code disabled, because it is not enabled for your organization. After you close this preference page, it will stay disabled.";
+ snykCodeCheckbox.setLabelText(snykCodeCheckbox.getLabelText() + " (" + message + ")");
+ SnykLogger.logInfo(message);
+ }
+ }
}
diff --git a/plugin/src/main/java/io/snyk/eclipse/plugin/properties/preferences/Preferences.java b/plugin/src/main/java/io/snyk/eclipse/plugin/properties/preferences/Preferences.java
index 341ef15..ff14c1d 100644
--- a/plugin/src/main/java/io/snyk/eclipse/plugin/properties/preferences/Preferences.java
+++ b/plugin/src/main/java/io/snyk/eclipse/plugin/properties/preferences/Preferences.java
@@ -26,6 +26,7 @@ public static synchronized Preferences getInstance(PreferenceStore store) {
return preferences;
}
+ public static final String TRUSTED_FOLDERS = "trustedFolders";
public static final String AUTH_TOKEN_KEY = "authtoken";
public static final String PATH_KEY = "path";
public static final String ENDPOINT_KEY = "endpoint";
diff --git a/plugin/src/main/java/io/snyk/eclipse/plugin/properties/preferences/SecurePreferenceStore.java b/plugin/src/main/java/io/snyk/eclipse/plugin/properties/preferences/SecurePreferenceStore.java
index 724600f..7839f63 100644
--- a/plugin/src/main/java/io/snyk/eclipse/plugin/properties/preferences/SecurePreferenceStore.java
+++ b/plugin/src/main/java/io/snyk/eclipse/plugin/properties/preferences/SecurePreferenceStore.java
@@ -4,7 +4,12 @@
import org.eclipse.equinox.security.storage.ISecurePreferences;
import org.eclipse.equinox.security.storage.SecurePreferencesFactory;
import org.eclipse.equinox.security.storage.StorageException;
+import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.preferences.ScopedPreferenceStore;
public class SecurePreferenceStore extends ScopedPreferenceStore implements PreferenceStore {
@@ -14,7 +19,21 @@ public class SecurePreferenceStore extends ScopedPreferenceStore implements Pref
public SecurePreferenceStore() {
super(InstanceScope.INSTANCE, QUALIFIER);
- node = SecurePreferencesFactory.getDefault().node(QUALIFIER);
+ ISecurePreferences secureStorage = SecurePreferencesFactory.getDefault();
+ if (secureStorage == null) {
+ PlatformUI.getWorkbench().getDisplay().asyncExec(() -> {
+ Display display = PlatformUI.getWorkbench().getDisplay();
+ Shell activeShell = display.getActiveShell();
+ String message = "Eclipse was unable to create or access the Secure Storage mechanism. "
+ + "Please check your Secure Storage in Eclipse preferences under "
+ + "General -> Security -> Secure Storage. "
+ + "The Snyk plugin will not be able to work reliably and save preferences "
+ + "or the authentication token until Secure Storage can be used.";
+ String title = "Error accessing Eclipse Secure Storage (Snyk)";
+ MessageDialog.openError(activeShell, title, message);
+ });
+ }
+ node = secureStorage.node(QUALIFIER);
}
@Override
diff --git a/plugin/src/main/java/io/snyk/eclipse/plugin/runner/SnykCliRunner.java b/plugin/src/main/java/io/snyk/eclipse/plugin/runner/SnykCliRunner.java
index a1ed528..df05e48 100644
--- a/plugin/src/main/java/io/snyk/eclipse/plugin/runner/SnykCliRunner.java
+++ b/plugin/src/main/java/io/snyk/eclipse/plugin/runner/SnykCliRunner.java
@@ -17,8 +17,6 @@ public class SnykCliRunner {
private static final String TEST_PARAMS = "test";
private static final String FILE_PARAM = "--file=";
- private static final String INSECURE = "--insecure";
-
private static final String MONITOR_PARAM = "monitor";
// private static final String AUTH_PARAM = "auth";
@@ -59,12 +57,20 @@ private ProcessResult snykRun(List arguments) {
private ProcessResult snykRun(List arguments, Optional navigatePath) {
try {
+ checkIfTrusted(navigatePath.get());
ProcessBuilder processBuilder = createProcessBuilderByOS(arguments, Preferences.getInstance().getPath());
return processRunner.run(processBuilder, navigatePath);
} catch (Exception e) {
return ProcessResult.error(e.getMessage());
}
}
+
+ private void checkIfTrusted(File file) {
+ var trustedPaths = Preferences.getInstance().getPref(Preferences.TRUSTED_FOLDERS, "");
+ if (!trustedPaths.contains(file.getAbsolutePath())) {
+ throw new UntrustedScanRequestedException(file.getAbsolutePath() + " is not trusted.");
+ }
+ }
private ProcessBuilder createProcessBuilderByOS(List params, Optional path) throws Exception {
ProcessBuilder processbuilder;
diff --git a/plugin/src/main/java/io/snyk/eclipse/plugin/runner/UntrustedScanRequestedException.java b/plugin/src/main/java/io/snyk/eclipse/plugin/runner/UntrustedScanRequestedException.java
new file mode 100644
index 0000000..2bc9afb
--- /dev/null
+++ b/plugin/src/main/java/io/snyk/eclipse/plugin/runner/UntrustedScanRequestedException.java
@@ -0,0 +1,27 @@
+package io.snyk.eclipse.plugin.runner;
+
+public class UntrustedScanRequestedException extends RuntimeException {
+
+ private static final long serialVersionUID = 4849361078384083852L;
+
+ public UntrustedScanRequestedException() {
+ }
+
+ public UntrustedScanRequestedException(String message) {
+ super(message);
+ }
+
+ public UntrustedScanRequestedException(Throwable cause) {
+ super(cause);
+ }
+
+ public UntrustedScanRequestedException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public UntrustedScanRequestedException(String message, Throwable cause, boolean enableSuppression,
+ boolean writableStackTrace) {
+ super(message, cause, enableSuppression, writableStackTrace);
+ }
+
+}
diff --git a/plugin/src/main/java/io/snyk/eclipse/plugin/wizards/SWTWidgetHelper.java b/plugin/src/main/java/io/snyk/eclipse/plugin/wizards/SWTWidgetHelper.java
new file mode 100644
index 0000000..97b6bb4
--- /dev/null
+++ b/plugin/src/main/java/io/snyk/eclipse/plugin/wizards/SWTWidgetHelper.java
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * bastian implementation
+ *******************************************************************************/
+
+
+package io.snyk.eclipse.plugin.wizards;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Group;
+
+/**
+ * @author bastian
+ * https://foss.heptapod.net/mercurial/mercurialeclipse/-/blob/branch/default/plugin/src/com/vectrace/MercurialEclipse/ui/SWTWidgetHelper.java
+ */
+public final class SWTWidgetHelper {
+ public static final int LABEL_WIDTH_HINT = 400;
+ public static final int LABEL_INDENT_WIDTH = 32;
+ public static final int LIST_HEIGHT_HINT = 100;
+ public static final int SPACER_HEIGHT = 8;
+
+ private SWTWidgetHelper() {
+ // hide constructor of utility class.
+ }
+
+ /**
+ * Creates a group that has and spans the given number of columns in its parent and which has the
+ * given style.
+ *
+ * @param parent
+ * the parent control.
+ * @param text
+ * the title of the group.
+ * @param span
+ * the number of columns (in the parent's layout) that this group will span, which is also the number of
+ * columns that this group has.
+ * @param style
+ * the chosen style of the grid layout for this group.
+ * @return a new group
+ */
+ public static Group createGroup(Composite parent, String text, int span, int style) {
+ Group group = new Group(parent, SWT.NULL);
+ group.setText(text);
+ GridData data = new GridData(style);
+ data.horizontalSpan = span;
+ // data.widthHint = GROUP_WIDTH;
+
+ group.setLayoutData(data);
+ GridLayout layout = new GridLayout();
+ layout.numColumns = span;
+ group.setLayout(layout);
+ return group;
+ }
+
+ /**
+ * Creates a group that spans two columns.
+ *
+ * @param parent
+ * the parent control
+ * @param text
+ * the title of the group
+ * @param style
+ * the chosen style for this group
+ * @return a new group
+ */
+ public static Group createGroup(Composite parent, String text, int style) {
+ return createGroup(parent, text, 2, style);
+ }
+
+ /**
+ * Creates a group that has two columns and which style is horizontal fill.
+ *
+ * @param parent
+ * the parent control
+ * @param text
+ * the title of the group
+ * @return a new group
+ */
+ public static Group createGroup(Composite parent, String text) {
+ return createGroup(parent, text, GridData.FILL_HORIZONTAL);
+ }
+}
diff --git a/plugin/src/main/java/io/snyk/eclipse/plugin/wizards/SnykWizard.java b/plugin/src/main/java/io/snyk/eclipse/plugin/wizards/SnykWizard.java
index c8ae8cd..80cda0f 100644
--- a/plugin/src/main/java/io/snyk/eclipse/plugin/wizards/SnykWizard.java
+++ b/plugin/src/main/java/io/snyk/eclipse/plugin/wizards/SnykWizard.java
@@ -11,9 +11,9 @@
public class SnykWizard extends Wizard implements INewWizard {
protected SnykWizardConfigureAPIPage configureAPIPage;
protected SnykWizardAuthenticatePage authenticatePage;
-
+
protected SnykWizardModel model;
-
+
protected IWorkbench workbench;
protected IStructuredSelection selection;
@@ -22,18 +22,18 @@ public SnykWizard() {
model = new SnykWizardModel();
setNeedsProgressMonitor(true);
}
-
+
@Override
public String getWindowTitle() {
return "Snyk Wizard";
}
-
+
@Override
public void addPages() {
- configureAPIPage = new SnykWizardConfigureAPIPage();
+ configureAPIPage = new SnykWizardConfigureAPIPage();
addPage(configureAPIPage);
-
- authenticatePage = new SnykWizardAuthenticatePage();
+
+ authenticatePage = new SnykWizardAuthenticatePage();
addPage(authenticatePage);
}
@@ -41,22 +41,23 @@ public void init(IWorkbench workbench, IStructuredSelection selection) {
this.workbench = workbench;
this.selection = selection;
}
-
+
public boolean canFinish() {
if (this.getContainer().getCurrentPage() == authenticatePage) {
return true;
}
return false;
}
-
+
public boolean performCancel() {
model.resetPreferences();
return true;
}
- public boolean performFinish() {
+ public boolean performFinish() {
new LsConfigurationUpdater().configurationChanged();
SnykExtendedLanguageClient.getInstance().triggerAuthentication();
+ SnykExtendedLanguageClient.getInstance().trustWorkspaceFolders();
return true;
}
}
diff --git a/plugin/src/main/java/io/snyk/eclipse/plugin/wizards/SnykWizardAuthenticatePage.java b/plugin/src/main/java/io/snyk/eclipse/plugin/wizards/SnykWizardAuthenticatePage.java
index c0a7bf6..f4e12c3 100644
--- a/plugin/src/main/java/io/snyk/eclipse/plugin/wizards/SnykWizardAuthenticatePage.java
+++ b/plugin/src/main/java/io/snyk/eclipse/plugin/wizards/SnykWizardAuthenticatePage.java
@@ -3,21 +3,27 @@
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Link;
import org.eclipse.swt.widgets.Text;
import io.snyk.eclipse.plugin.properties.preferences.Preferences;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Listener;
public class SnykWizardAuthenticatePage extends WizardPage implements Listener {
private Text endpoint;
private Button unknownCerts;
+ private String trustMessage = "⚠️ When scanning folder files, Snyk may automatically execute code such as invoking the package manager to get dependency information. "
+ + "You should only scan projects you trust. More Info"
+ + "\n\nOn finishing the wizard, the plugin will open a browser to authenticate you, trust the current workspace projects and trigger a scan.";
public SnykWizardAuthenticatePage() {
super("Snyk Wizard");
@@ -27,37 +33,45 @@ public SnykWizardAuthenticatePage() {
@Override
public void createControl(Composite parent) {
- Composite composite = new Composite(parent, SWT.NONE);
- GridLayout gl = new GridLayout();
- GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+ Composite composite = new Composite(parent, SWT.NONE);
+ GridData gd = new GridData(GridData.FILL_HORIZONTAL);
- int ncol = 2;
- gl.numColumns = ncol;
- composite.setLayout(gl);
+ GridLayout gl = new GridLayout();
+ int ncol = 2;
+ gl.numColumns = ncol;
+ composite.setLayout(gl);
- Label endpointLabel = new Label(composite, SWT.NONE);
- endpointLabel.setText("Endpoint:");
+ Group endpointGroup = SWTWidgetHelper.createGroup(composite, "");
- endpoint = new Text(composite, SWT.BORDER | SWT.READ_ONLY);
- endpoint.setLayoutData(gd);
-
- createLine(composite, ncol);
+ Label endpointLabel = new Label(endpointGroup, SWT.NONE);
+ endpointLabel.setText("Endpoint:");
+ endpoint = new Text(endpointGroup, SWT.BORDER | SWT.READ_ONLY);
+ endpoint.setLayoutData(gd);
- Label unknownCertsLabel = new Label(composite, SWT.NONE);
- unknownCertsLabel.setText("Allow unknown certificate authorities:");
+ Label unknownCertsLabel = new Label(endpointGroup, SWT.NONE);
+ unknownCertsLabel.setText("Allow unknown certificate authorities:");
- unknownCerts = new Button(composite, SWT.CHECK);
- unknownCerts.setLayoutData(gd);
+ unknownCerts = new Button(endpointGroup, SWT.CHECK);
+ unknownCerts.setLayoutData(gd);
- // required to avoid an error in the system
- setControl(composite);
- setPageComplete(false);
+ Group trustGroup = SWTWidgetHelper.createGroup(composite, "");
+
+ Link trustText = new Link(trustGroup, SWT.NONE);
+ trustText.setText(trustMessage);
+ gd = new GridData(GridData.FILL_BOTH);
+ trustText.setLayoutData(gd);
+ trustText.setBackground(new Color(0, 0, 0, 0));
+ trustText.addListener(SWT.Selection, event -> org.eclipse.swt.program.Program.launch(event.text));
+
+ // required to avoid an error in the system
+ setControl(composite);
+ setPageComplete(false);
}
public void handleEvent(Event e) {
getWizard().getContainer().updateButtons();
}
-
+
public boolean isPageComplete() {
return true;
}
@@ -66,11 +80,4 @@ void onEnterPage() {
endpoint.setText(Preferences.getInstance().getEndpoint());
unknownCerts.setSelection(Preferences.getInstance().getBooleanPref(Preferences.INSECURE_KEY));
}
-
- private void createLine(Composite parent, int ncol) {
- Label line = new Label(parent, SWT.SEPARATOR | SWT.HORIZONTAL | SWT.BOLD);
- GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
- gridData.horizontalSpan = ncol;
- line.setLayoutData(gridData);
- }
}
diff --git a/plugin/src/main/java/io/snyk/languageserver/LsConfigurationUpdater.java b/plugin/src/main/java/io/snyk/languageserver/LsConfigurationUpdater.java
index b1e7288..35b1871 100644
--- a/plugin/src/main/java/io/snyk/languageserver/LsConfigurationUpdater.java
+++ b/plugin/src/main/java/io/snyk/languageserver/LsConfigurationUpdater.java
@@ -4,6 +4,7 @@
import io.snyk.eclipse.plugin.properties.preferences.Preferences;
import io.snyk.eclipse.plugin.utils.SnykLogger;
+import java.io.File;
import java.util.Collections;
import org.eclipse.core.resources.IProject;
@@ -45,23 +46,30 @@ public void configurationChanged() {
Settings getCurrentSettings() {
Preferences preferences = Preferences.getInstance();
- String activateSnykOpenSource = preferences.getPref(Preferences.ACTIVATE_SNYK_OPEN_SOURCE, "true");
- String activateSnykCode = preferences.getPref(Preferences.ACTIVATE_SNYK_CODE, "false");
- String activateSnykIac = preferences.getPref(Preferences.ACTIVATE_SNYK_IAC, "true");
- String insecure = preferences.getPref(Preferences.INSECURE_KEY, "false");
+ String activateSnykOpenSource = preferences.getPref(Preferences.ACTIVATE_SNYK_OPEN_SOURCE,
+ Boolean.TRUE.toString());
+ String activateSnykCode = preferences.getPref(Preferences.ACTIVATE_SNYK_CODE, Boolean.FALSE.toString());
+ String activateSnykIac = preferences.getPref(Preferences.ACTIVATE_SNYK_IAC, Boolean.TRUE.toString());
+ String insecure = preferences.getPref(Preferences.INSECURE_KEY, Boolean.FALSE.toString());
String endpoint = preferences.getPref(Preferences.ENDPOINT_KEY, "");
String additionalParams = preferences.getPref(Preferences.ADDITIONAL_PARAMETERS, "");
String additionalEnv = preferences.getPref(Preferences.ADDITIONAL_ENVIRONMENT, "");
String path = preferences.getPref(Preferences.PATH_KEY, "");
String sendErrorReports = preferences.getPref(Preferences.SEND_ERROR_REPORTS, "");
- String enableTelemetry = preferences.getPref(Preferences.ENABLE_TELEMETRY, "false");
+ String enableTelemetry = preferences.getPref(Preferences.ENABLE_TELEMETRY, Boolean.FALSE.toString());
String organization = preferences.getPref(Preferences.ORGANIZATION_KEY, "");
- String manageBinariesAutomatically = preferences.getPref(Preferences.MANAGE_BINARIES_AUTOMATICALLY, "true");
+ String manageBinariesAutomatically = preferences.getPref(Preferences.MANAGE_BINARIES_AUTOMATICALLY, Boolean.TRUE.toString());
String cliPath = preferences.getPref(Preferences.CLI_PATH, "");
String token = preferences.getPref(Preferences.AUTH_TOKEN_KEY, "");
String integrationName = Activator.INTEGRATION_NAME;
String integrationVersion = Activator.PLUGIN_VERSION;
String automaticAuthentication = "false";
+ String trustedFoldersString = preferences.getPref(Preferences.TRUSTED_FOLDERS);
+ String[] trustedFolders = new String[0];
+ if (trustedFoldersString != null && !trustedFoldersString.isBlank()) {
+ trustedFolders = trustedFoldersString.split(File.pathSeparator);
+ }
+ String enableTrustedFolderFeature = Boolean.TRUE.toString();
return new Settings(activateSnykOpenSource,
activateSnykCode,
activateSnykIac,
@@ -78,7 +86,9 @@ Settings getCurrentSettings() {
token,
integrationName,
integrationVersion,
- automaticAuthentication
+ automaticAuthentication,
+ trustedFolders,
+ enableTrustedFolderFeature
);
}
@@ -101,6 +111,8 @@ static class Settings {
private final String integrationName;
private final String integrationVersion;
private final String automaticAuthentication;
+ private final String[] trustedFolders;
+ private final String enableTrustedFoldersFeature;
public Settings(String activateSnykOpenSource,
String activateSnykCode,
@@ -118,7 +130,9 @@ public Settings(String activateSnykOpenSource,
String token,
String integrationName,
String integrationVersion,
- String automaticAuthentication
+ String automaticAuthentication,
+ String[] trustedFolders,
+ String enableTrustedFoldersFeature
) {
this.activateSnykOpenSource = activateSnykOpenSource;
this.activateSnykCode = activateSnykCode;
@@ -137,6 +151,8 @@ public Settings(String activateSnykOpenSource,
this.integrationName = integrationName;
this.integrationVersion = integrationVersion;
this.automaticAuthentication = automaticAuthentication;
+ this.trustedFolders = trustedFolders;
+ this.enableTrustedFoldersFeature = enableTrustedFoldersFeature;
}
public String getPath() {
@@ -202,9 +218,17 @@ public String getIntegrationName() {
public String getIntegrationVersion() {
return integrationVersion;
}
-
+
public String getAutomaticAuthentication() {
return automaticAuthentication;
}
+
+ public String[] getTrustedFolders() {
+ return trustedFolders;
+ }
+
+ public String getEnableTrustedFoldersFeature() {
+ return enableTrustedFoldersFeature;
+ }
}
}
diff --git a/plugin/src/main/java/io/snyk/languageserver/download/LsBinaries.java b/plugin/src/main/java/io/snyk/languageserver/download/LsBinaries.java
index 86b9d22..f097115 100644
--- a/plugin/src/main/java/io/snyk/languageserver/download/LsBinaries.java
+++ b/plugin/src/main/java/io/snyk/languageserver/download/LsBinaries.java
@@ -4,7 +4,7 @@
public class LsBinaries {
private static final String LS_DOWNLOAD_BASE_URL = "https://static.snyk.io/snyk-ls";
- public static final String REQUIRED_LS_PROTOCOL_VERSION = "3";
+ public static final String REQUIRED_LS_PROTOCOL_VERSION = "4";
public static URI getBaseUri() {
return URI.create(String.format("%s/%s", LS_DOWNLOAD_BASE_URL, REQUIRED_LS_PROTOCOL_VERSION));
diff --git a/plugin/src/main/java/io/snyk/languageserver/protocolextension/SnykExtendedLanguageClient.java b/plugin/src/main/java/io/snyk/languageserver/protocolextension/SnykExtendedLanguageClient.java
index bb728b6..119d9c6 100644
--- a/plugin/src/main/java/io/snyk/languageserver/protocolextension/SnykExtendedLanguageClient.java
+++ b/plugin/src/main/java/io/snyk/languageserver/protocolextension/SnykExtendedLanguageClient.java
@@ -1,7 +1,12 @@
package io.snyk.languageserver.protocolextension;
+import java.io.File;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
import java.util.concurrent.CompletableFuture;
+import java.util.stream.Collectors;
import org.eclipse.core.resources.IProject;
import org.eclipse.jdt.internal.core.JavaProject;
@@ -19,6 +24,7 @@
import org.eclipse.lsp4j.ShowDocumentResult;
import org.eclipse.lsp4j.WorkDoneProgressCreateParams;
import org.eclipse.lsp4j.jsonrpc.services.JsonNotification;
+import org.eclipse.lsp4j.jsonrpc.validation.NonNull;
import org.eclipse.ui.ISelectionService;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
@@ -30,6 +36,7 @@
import io.snyk.eclipse.plugin.wizards.SnykWizard;
import io.snyk.languageserver.protocolextension.messageObjects.HasAuthenticatedParam;
import io.snyk.languageserver.protocolextension.messageObjects.SnykIsAvailableCliParams;
+import io.snyk.languageserver.protocolextension.messageObjects.SnykTrustedFoldersParams;
@SuppressWarnings("restriction")
public class SnykExtendedLanguageClient extends LanguageClientImpl {
@@ -50,9 +57,8 @@ public void triggerScan(IWorkbenchWindow window) {
if (Preferences.getInstance().getAuthToken().isBlank()) {
runSnykWizard();
} else {
- ExecuteCommandParams params = new ExecuteCommandParams("snyk.workspace.scan", new ArrayList<>());
try {
- getLanguageServer().getWorkspaceService().executeCommand(params);
+ executeCommand("snyk.workspace.scan", new ArrayList<>());
if (window == null) {
window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
@@ -82,12 +88,11 @@ public void triggerScan(IWorkbenchWindow window) {
}
public void triggerAuthentication() {
- ExecuteCommandParams params = new ExecuteCommandParams("snyk.login", new ArrayList<>());
- try {
- getLanguageServer().getWorkspaceService().executeCommand(params);
- } catch (Exception e) {
- SnykLogger.logError(e);
- }
+ executeCommand("snyk.login", new ArrayList<>());
+ }
+
+ public void trustWorkspaceFolders() {
+ executeCommand("snyk.trustWorkspaceFolders", new ArrayList<>());
}
@JsonNotification(value = "$/snyk.hasAuthenticated")
@@ -106,6 +111,21 @@ public void isAvailableCli(SnykIsAvailableCliParams param) {
enableSnykViewRunActions();
}
+ @JsonNotification(value = "$/snyk.addTrustedFolders")
+ public void addTrustedPaths(SnykTrustedFoldersParams param) {
+ var prefs = Preferences.getInstance();
+ var storedTrustedPaths = prefs.getPref(Preferences.TRUSTED_FOLDERS, "");
+ var trustedPaths = storedTrustedPaths.split(File.pathSeparator);
+ var pathSet = new HashSet<>(Arrays.asList(trustedPaths));
+ pathSet.addAll(Arrays.asList(param.getTrustedFolders()));
+ Preferences.getInstance().store(Preferences.TRUSTED_FOLDERS,
+ pathSet.stream()
+ .filter(s -> !s.isBlank())
+ .map(s -> s.trim())
+ .distinct()
+ .collect(Collectors.joining(File.pathSeparator)));
+ }
+
@Override
public CompletableFuture createProgress(WorkDoneProgressCreateParams params) {
return progressMgr.createProgress(params);
@@ -147,6 +167,15 @@ private void runForProject(String projectName) {
}
}
+ private void executeCommand(@NonNull String command, List