Skip to content

Commit

Permalink
devonfw#103: rephrase interaction, mapUtil, LICENCE
Browse files Browse the repository at this point in the history
also SecurityRiskInteraction returns configured version and latest version when possible.

conversion between cpe and ulr version more rebust by using map and inverse function where map fails.

Added asciidoc
  • Loading branch information
MattesMrzik committed Dec 21, 2023
1 parent 1b9224b commit 9a86e34
Show file tree
Hide file tree
Showing 10 changed files with 441 additions and 100 deletions.
63 changes: 24 additions & 39 deletions cli/src/main/java/com/devonfw/tools/ide/tool/ToolCommandlet.java
Original file line number Diff line number Diff line change
Expand Up @@ -173,16 +173,6 @@ public boolean install(boolean silent) {
return doInstall(silent);
}

protected String securityRiskInteractionQuestion(String question, String... options) {

question += "Do you want to";
for (int i = 0; i < options.length - 1; i++) {
options[i] += " or";
}
options[options.length - 1] += "?";
return this.context.question(question, options);
}

/**
* Checks if the given {@link VersionIdentifier} has a matching security warning in the {@link UrlSecurityJsonFile}.
*
Expand All @@ -193,16 +183,10 @@ protected String securityRiskInteractionQuestion(String question, String... opti
*/
protected VersionIdentifier securityRiskInteraction(VersionIdentifier configuredVersion) {

// TODO maybe instead of returning current return configuredVersion if the users chooses "stay"

// TODO webpage:\nhttps://github.com/devonfw/ide/blob/master/documentation/vulnerabilities.asciidoc\n\n";

UrlSecurityJsonFile securityFile = this.context.getUrls().getEdition(this.tool, this.getEdition())
.getSecurityJsonFile();

VersionIdentifier current = this.context.getUrls().getVersion(this.tool, this.getEdition(), configuredVersion);
// TODO oder doch eher sowas wie VersionIdentifier resolvedVersion = toolRepository.resolveVersion(this.tool,
// edition, selectedVersion); sollte immer das selbe ergeben

if (!securityFile.contains(current, true, this.context)) {
return configuredVersion;
Expand All @@ -212,7 +196,6 @@ protected VersionIdentifier securityRiskInteraction(VersionIdentifier configured
VersionIdentifier latest = allVersions.get(0);

int currentVersionIndex = allVersions.indexOf(current);

VersionIdentifier nextSafe = null;
for (int i = currentVersionIndex - 1; i >= 0; i--) {
if (!securityFile.contains(allVersions.get(i), true, this.context)) {
Expand All @@ -232,10 +215,12 @@ protected VersionIdentifier securityRiskInteraction(VersionIdentifier configured
String currentIsUnsafe = "Currently, version " + current + " of " + this.getName() + " is selected, "
+ "which is has one or more vulnerabilities:\n\n" + cves + "\n\n(See also " + securityFile.getPath() + ")\n\n";

String stay = "stay with the current unsafe version (" + current + ")";
String installLatestSafe = "install the latest safe version (" + latestSafe + ")";
String installSafeLatest = "install the (safe) latest version (" + latest + ")";
String installNextSafe = "install the next safe version (" + nextSafe + ")";
String ask = "Which version do you want to install?";

String stay = "Stay with the current unsafe version (" + current + ").";
String installLatestSafe = "Install the latest safe version (" + latestSafe + ").";
String installSafeLatest = "Install the (safe) latest version (" + latest + ").";
String installNextSafe = "Install the next safe version (" + nextSafe + ").";
// I don't need to offer "install latest which is unsafe" as option since the user can set to the latest and choose
// "stay"

Expand All @@ -245,38 +230,38 @@ protected VersionIdentifier securityRiskInteraction(VersionIdentifier configured
}

if (current.equals(latest)) {
String answer = securityRiskInteractionQuestion(currentIsUnsafe + "There are no updates available.", stay,
String answer = this.context.question(currentIsUnsafe + "There are no updates available. " + ask, stay,
installLatestSafe);
return answer.startsWith(stay) ? current : latestSafe;
return answer.equals(stay) ? configuredVersion : latestSafe;

} else if (nextSafe == null) {
String answer = securityRiskInteractionQuestion(currentIsUnsafe + " All newer versions are also not safe.", stay,
} else if (nextSafe == null) { // install an older version that is safe or stay with the current unsafe version
String answer = this.context.question(currentIsUnsafe + " All newer versions are also not safe. " + ask, stay,
installLatestSafe);
return answer.startsWith(stay) ? current : latestSafe;
return answer.equals(stay) ? configuredVersion : latestSafe;

} else if (nextSafe.equals(latest)) {
String answer = securityRiskInteractionQuestion(
currentIsUnsafe + " Of the newer versions, only the latest is safe.", stay, installSafeLatest);
return answer.startsWith(stay) ? current : latestSafe;
String answer = this.context.question(currentIsUnsafe + " Of the newer versions, only the latest is safe. " + ask,
stay, installSafeLatest);
return answer.equals(stay) ? configuredVersion : VersionIdentifier.LATEST;

} else if (nextSafe.equals(latestSafe)) {
String answer = securityRiskInteractionQuestion(currentIsUnsafe + " Of the newer versions, only the version "
+ nextSafe + " is safe, Which is not the latest.", stay, "Install the safe version (" + nextSafe + ")");
return answer.startsWith(stay) ? current : nextSafe;
String answer = this.context.question(
currentIsUnsafe + " Of the newer versions, only the version " + nextSafe
+ " is safe, which is however not the latest." + ask,
stay, "Install the safe version (" + nextSafe + ")");
return answer.equals(stay) ? configuredVersion : nextSafe;

} else {
if (latestSafe.equals(latest)) {
String answer = securityRiskInteractionQuestion(currentIsUnsafe, stay, installNextSafe, installSafeLatest);
return answer.startsWith(stay) ? current : answer.startsWith(installNextSafe) ? nextSafe : latestSafe;
String answer = this.context.question(currentIsUnsafe + ask, stay, installNextSafe, installSafeLatest);
return answer.equals(stay) ? configuredVersion
: answer.equals(installNextSafe) ? nextSafe : VersionIdentifier.LATEST;

} else {
String answer = securityRiskInteractionQuestion(currentIsUnsafe, stay, installNextSafe, installLatestSafe);
return answer.startsWith(stay) ? current : answer.startsWith(installNextSafe) ? nextSafe : latestSafe;
String answer = this.context.question(currentIsUnsafe + ask, stay, installNextSafe, installLatestSafe);
return answer.equals(stay) ? configuredVersion : answer.equals(installNextSafe) ? nextSafe : latestSafe;
}
}

// VersionIdentifier chosenVersion = securityRiskInteraction(configuredVersion);
// setVersion(chosenVersion, silent);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,4 @@ public String getCpeProduct() {

return "terraform";
}
// add matche cpe the the warning and print it in ide, to to wether the vul maybe oinly applies to the enterprise
// edition
// or can I filter this enterpsrise version by adding overriding the eidtion methiod with the normal edition string?
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,8 @@
*/
public class UrlSecurityJsonFile extends AbstractUrlFile<UrlEdition> {

/***
/**
* A simple container with the information about a security warning.
*
*/
public static class UrlSecurityWarning {

Expand Down Expand Up @@ -62,6 +61,8 @@ public UrlSecurityWarning() {
*
* @param versionRange the version range, specifying the versions of the tool to which the security risk applies.
* @param matchedCpe the matched CPE.
* @param interval the interval of vulnerability that was used to determine the {@link VersionRange}. This is used
* to check if the mapping from CPE version to UrlVersion was correct.
* @param severity the severity of the security risk.
* @param severityVersion Indicating from which version the {@code severity} was obtained. As of December 2023, this
* is either v2 or v3.
Expand Down Expand Up @@ -258,12 +259,13 @@ public boolean addSecurityWarning(VersionRange versionRange) {
return added;
}

/***
/**
* Adds a new security warning to the security json file.
*
* @param versionRange the version range, specifying the versions of the tool to which the security risk applies.
* @param matchedCpe the matched CPE.
* @param interval the interval of vulnerability that was used to determine the version range.
* @param interval the interval of vulnerability that was used to determine the {@link VersionRange}. This is used to
* check if the mapping from CPE version to UrlVersion was correct.
* @param severity the severity of the security risk.
* @param severityVersion Indicating from which version the {@code severity} was obtained. As of December 2023, this
* is either v2 or v3.
Expand All @@ -283,7 +285,7 @@ public boolean addSecurityWarning(VersionRange versionRange, String matchedCpe,
return added;
}

/***
/**
* For a given version, returns whether there is a security risk by locking at the warnings in the security json file.
*
* @param version the version to check for security risks.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,24 +97,23 @@ protected final String getToolWithEdition() {
return tool + "/" + edition;
}

/***
*
/**
* @return the vendor of the tool as specified in the CPE (Common Platform Enumeration)
*/
public String getCpeVendor() {

return null;
}

/***
/**
* @return the product name of the tool as specified in the CPE (Common Platform Enumeration)
*/
public String getCpeProduct() {

return null;
}

/***
/**
* @return the edition of the tool as specified in the CPE (Common Platform Enumeration)
*/
public String getCpeEdition() {
Expand All @@ -132,7 +131,13 @@ public String mapUrlVersionToCpeVersion(String version) {
}

/**
* @return maps the cpe version to the version as specified in the CPE (Common Platform Enumeration).
* This method is only used as fallback if the passed version is not in the image of
* {@link #mapUrlVersionToCpeVersion(String)}. This doesn't have to be inverse of
* {@link #mapUrlVersionToCpeVersion(String)}. It must only be sufficient to get the correct VersionRange from the
* matched vulnerable software.
*
* @return maps the version as specified in the CPE (Common Platform Enumeration) to the version as specified by the
* directory name in the url repository
*/
public String mapCpeVersionToUrlVersion(String version) {

Expand Down
34 changes: 34 additions & 0 deletions cli/src/main/java/com/devonfw/tools/ide/util/MapUtil.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.devonfw.tools.ide.util;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
* Utility class for operations on maps.
*/
public class MapUtil {

/**
* Creates a {@link HashMap} with the given {@code keys} and {@code values} which are passed as {@link List lists}.
* The map is populated by iterating through both lists simultaneously until one of the list is exhausted.
*/
public static <K, V> Map<K, V> createMapWithLists(List<K> keys, List<V> values) {

Map<K, V> resultMap = new HashMap<>();

// Create iterators for both lists
Iterator<K> keysIterator = keys.iterator();
Iterator<V> valuesIterator = values.iterator();

// Iterate through both iterators simultaneously
while (keysIterator.hasNext() && valuesIterator.hasNext()) {
K key = keysIterator.next();
V value = valuesIterator.next();
resultMap.put(key, value);
}

return resultMap;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@
import com.devonfw.tools.ide.version.VersionIdentifier;
import com.devonfw.tools.ide.version.VersionRange;

/***
/**
* Test of {@link ToolCommandlet}.
*/
public class ToolCommandletTest extends AbstractIdeContextTest {

/***
/**
* Test of {@link ToolCommandlet#securityRiskInteraction(VersionIdentifier)} where no safe version is available. But
* there is a warning that affects all versions. This warning is then ignored, but the other warnings are considered.
*/
Expand All @@ -26,7 +26,7 @@ public void testSecurityRiskInteractionAllVersionAffectedBySingleWarning() {

// arrange
Class<? extends ToolCommandlet> dummyTool = Azure.class;
String[] answers = {"1", "2", "3"};
String[] answers = { "1", "2", "3" };
IdeContext context = getContextForSecurityJsonTests(dummyTool, answers);
ToolCommandlet tool = context.getCommandletManager().getCommandlet(dummyTool);
UrlSecurityJsonFile securityFile = context.getUrls().getEdition(tool.getName(), tool.getEdition())
Expand All @@ -44,11 +44,10 @@ public void testSecurityRiskInteractionAllVersionAffectedBySingleWarning() {
// answer to the interaction is 2
assertThat(tool.securityRiskInteraction(VersionIdentifier.of("2"))).isEqualTo(VersionIdentifier.of("6"));
// answer to the interaction is 3
assertThat(tool.securityRiskInteraction(VersionIdentifier.of("2"))).isEqualTo(VersionIdentifier.of("9"));
assertThat(tool.securityRiskInteraction(VersionIdentifier.of("2"))).isEqualTo(VersionIdentifier.of("*"));
}


/***
/**
* Test of {@link ToolCommandlet#securityRiskInteraction(VersionIdentifier)} where no safe version is available. Only
* the warnings all considered together cover all versions and there is no single warning that affects all versions.
*/
Expand All @@ -70,7 +69,8 @@ public void testSecurityRiskInteractionAllVersionAffectedByMultipleWarning() {
assertThat(tool.securityRiskInteraction(VersionIdentifier.of("9"))).isEqualTo(VersionIdentifier.of("9"));
assertThat(tool.securityRiskInteraction(VersionIdentifier.of("*"))).isEqualTo(VersionIdentifier.of("*"));
}
/***

/**
* Test of {@link ToolCommandlet#securityRiskInteraction(VersionIdentifier)} where the set version is the latest but
* vulnerable.
*/
Expand All @@ -89,12 +89,12 @@ public void testSecurityRiskInteractionCurrentIsLatest() {

// act & assert
// answer to the interaction is 1
assertThat(tool.securityRiskInteraction(VersionIdentifier.of("*"))).isEqualTo(VersionIdentifier.of("9"));
assertThat(tool.securityRiskInteraction(VersionIdentifier.of("*"))).isEqualTo(VersionIdentifier.of("*"));
// answer to the interaction is 2
assertThat(tool.securityRiskInteraction(VersionIdentifier.of("*"))).isEqualTo(VersionIdentifier.of("6"));
}

/***
/**
* Test of {@link ToolCommandlet#securityRiskInteraction(VersionIdentifier)} where there are no newer versions that
* are safe, but there is a previous version that is safe.
*/
Expand All @@ -119,7 +119,7 @@ public void testSecurityRiskInteractionNextSafeIsNull() {
assertThat(tool.securityRiskInteraction(VersionIdentifier.of("6"))).isEqualTo(VersionIdentifier.of("5"));
}

/***
/**
* Test of {@link ToolCommandlet#securityRiskInteraction(VersionIdentifier)} where the next safe version is also the
* latest.
*/
Expand All @@ -141,10 +141,10 @@ public void testSecurityRiskInteractionNextSafeIsLatest() {
// answer to the interaction is 1
assertThat(tool.securityRiskInteraction(VersionIdentifier.of("7"))).isEqualTo(VersionIdentifier.of("7"));
// answer to the interaction is 2
assertThat(tool.securityRiskInteraction(VersionIdentifier.of("7"))).isEqualTo(VersionIdentifier.of("9"));
assertThat(tool.securityRiskInteraction(VersionIdentifier.of("7"))).isEqualTo(VersionIdentifier.of("*"));
}

/***
/**
* Test of {@link ToolCommandlet#securityRiskInteraction(VersionIdentifier)} where the next safe version is also the
* latest safe version, and the overall latest version is not safe.
*/
Expand All @@ -169,7 +169,7 @@ public void testSecurityRiskInteractionNextSafeIsLatestSafe() {
assertThat(tool.securityRiskInteraction(VersionIdentifier.of("5"))).isEqualTo(VersionIdentifier.of("7"));
}

/***
/**
* Test of {@link ToolCommandlet#securityRiskInteraction(VersionIdentifier)} where the next safe version differs from
* the latest safe, which is also the overall latest version.
*/
Expand All @@ -193,10 +193,10 @@ public void testSecurityRiskInteractionLatestSafeDiffersFromNextSafeButIsLatest(
// answer to the interaction is 2
assertThat(tool.securityRiskInteraction(VersionIdentifier.of("5"))).isEqualTo(VersionIdentifier.of("7"));
// answer to the interaction is 3
assertThat(tool.securityRiskInteraction(VersionIdentifier.of("5"))).isEqualTo(VersionIdentifier.of("9"));
assertThat(tool.securityRiskInteraction(VersionIdentifier.of("5"))).isEqualTo(VersionIdentifier.of("*"));
}

/***
/**
* Test of {@link ToolCommandlet#securityRiskInteraction(VersionIdentifier)} where the next safe version differs from
* the latest safe, and the overall latest version is not safe.
*/
Expand All @@ -223,7 +223,7 @@ public void testSecurityRiskInteractionLatestSafeDiffersFromNextSafeAndLatest()
assertThat(tool.securityRiskInteraction(VersionIdentifier.of("3"))).isEqualTo(VersionIdentifier.of("7"));
}

/***
/**
* Test of {@link ToolCommandlet#securityRiskInteraction(VersionIdentifier)} where set version is safe.
*/
@Test
Expand All @@ -243,9 +243,7 @@ public void testSecurityRiskInteractionCurrentVersionIsSafe() {
assertThat(tool.securityRiskInteraction(VersionIdentifier.of("9"))).isEqualTo(VersionIdentifier.of("9"));
}



/***
/**
* Creates the context and data for the tests of {@link ToolCommandlet#securityRiskInteraction(VersionIdentifier)}.
*
* @param dummyTool the dummy tool to be used for the tests. The
Expand Down
Loading

0 comments on commit 9a86e34

Please sign in to comment.