Skip to content

Commit

Permalink
Merge pull request #663 from fortify/develop
Browse files Browse the repository at this point in the history
Prepare for next release
  • Loading branch information
rsenden authored Dec 23, 2024
2 parents 0983b58 + 85bc662 commit f2be7b1
Show file tree
Hide file tree
Showing 19 changed files with 453 additions and 109 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,11 @@
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.nio.file.StandardOpenOption;
import java.nio.file.attribute.PosixFilePermission;
import java.nio.file.attribute.PosixFilePermissions;
import java.util.Comparator;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Stream;
import java.util.zip.GZIPInputStream;
import java.util.zip.ZipEntry;
Expand All @@ -39,6 +43,7 @@
// TODO For now, methods provided in this class are only used by the tools module,
// but potentially some methods or the full class could be moved to the common module.
public final class FileUtils {
public static final Set<PosixFilePermission> execPermissions = PosixFilePermissions.fromString("rwxr-xr-x");
private FileUtils() {}

@SneakyThrows
Expand Down Expand Up @@ -105,15 +110,55 @@ public static final void move(Path source, Path target) {
}
}

@SneakyThrows
public static final void setAllFilePermissions(Path path, Set<PosixFilePermission> permissions, boolean recursive) {
if ( path!=null && Files.exists(path) ) {
if ( Files.isDirectory(path) ) {
try (Stream<Path> walk = Files.walk(path)) {
walk.forEach(p->{
var isDir = Files.isDirectory(p);
if ( isDir && recursive ) {
setAllFilePermissions(p, permissions, recursive);
} else if ( !isDir ) {
setSinglePathPermissions(p, permissions);
}
});
}
}
}
}

@SneakyThrows
public static final void setSinglePathPermissions(Path p, Set<PosixFilePermission> permissions) {
try {
Files.setPosixFilePermissions(p, permissions);
} catch ( UnsupportedOperationException e ) {
// Log warning?
}
}

public static final Function<Path,Path> defaultExtractPathResolver(Path targetPath, Function<Path,Path> sourcePathRewriter) {
return sourcePath->{
var newSourcePath = sourcePathRewriter==null ? sourcePath : sourcePathRewriter.apply(sourcePath);
var resolvedPath = targetPath.resolve(newSourcePath);
if (!resolvedPath.startsWith(targetPath.normalize())) {
// see: https://snyk.io/research/zip-slip-vulnerability
throw new RuntimeException("Entry with an illegal path: " + sourcePath);
}
return resolvedPath;
};
}

@SneakyThrows
public static final void extractZip(File zipFile, Path targetDir) {
extractZip(zipFile, defaultExtractPathResolver(targetDir, null));
}

@SneakyThrows
public static final void extractZip(File zipFile, Function<Path, Path> extractPathResolver) {
try (FileInputStream fis = new FileInputStream(zipFile); ZipInputStream zipIn = new ZipInputStream(fis)) {
for (ZipEntry ze; (ze = zipIn.getNextEntry()) != null; ) {
Path resolvedPath = targetDir.resolve(ze.getName()).normalize();
if (!resolvedPath.startsWith(targetDir.normalize())) {
// see: https://snyk.io/research/zip-slip-vulnerability
throw new RuntimeException("Entry with an illegal path: " + ze.getName());
}
Path resolvedPath = extractPathResolver.apply(Path.of(ze.getName())).normalize();
if (ze.isDirectory()) {
Files.createDirectories(resolvedPath);
} else {
Expand All @@ -126,13 +171,18 @@ public static final void extractZip(File zipFile, Path targetDir) {

@SneakyThrows
public static final void extractTarGZ(File tgzFile, Path targetDir) {
extractTarGZ(tgzFile, defaultExtractPathResolver(targetDir, null));
}

@SneakyThrows
public static final void extractTarGZ(File tgzFile, Function<Path,Path> extractPathResolver) {
try (InputStream source = Files.newInputStream(tgzFile.toPath());
GZIPInputStream gzip = new GZIPInputStream(source);
TarArchiveInputStream tar = new TarArchiveInputStream(gzip)) {

TarArchiveEntry entry;
while ((entry = tar.getNextEntry()) != null) {
Path extractTo = targetDir.resolve(entry.getName());
Path extractTo = extractPathResolver.apply(Path.of(entry.getName()));
if(entry.isDirectory()) {
Files.createDirectories(extractTo);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,5 @@ public static class NetworkAuthenticationType {
private Integer timeBoxInHours;
@Builder.Default
private Boolean requestFalsePositiveRemoval = false;

private String networkName; // FoDConnect Network Name
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

//TODO Enum case? See comments in FoDAppTypeOptions
public class FoDSdlcStatusTypeOptions {
public enum FoDSdlcStatusType {Development, QA, Production}
public enum FoDSdlcStatusType {Development, QA, Production, Retired}

public static final class FoDSdlcStatusTypeIterable extends ArrayList<String> {
private static final long serialVersionUID = 1L;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ public class FoDDastAutomatedScanSetupApiCommand extends AbstractFoDScanSetupCom
private String password;
@Option(names = {"--false-positive-removal"})
private Boolean requestFalsePositiveRemoval;
@Option(names = {"--vpn"})
private String fodConnectNetwork;

@Override
protected String getScanType() {
Expand Down Expand Up @@ -94,11 +96,14 @@ protected HttpRequest<?> getBaseRequest(UnirestInstance unirest, String releaseI
networkAuthenticationSettings = new FoDScanDastAutomatedSetupBaseRequest.NetworkAuthenticationType(networkAuthenticationType, username, password);
}
String timeZoneToUse = FoDScanHelper.validateTimezone(unirest, timezone);

if (fodConnectNetwork != null) {
// if Fortify Connect network site override environmentFacingType to Internal
environmentFacingType = FoDEnums.DynamicScanEnvironmentFacingType.Internal;
}

FoDScanAssessmentTypeDescriptor assessmentTypeDescriptor = FoDScanHelper.getEntitlementToUse(unirest, releaseId, FoDScanType.Dynamic,
assessmentType, entitlementFrequencyTypeMixin.getEntitlementFrequencyType(), entitlementId);
entitlementId = assessmentTypeDescriptor.getEntitlementId();

FoDScanDastAutomatedSetupBaseRequest setupBaseRequest = FoDScanDastAutomatedSetupBaseRequest.builder()
.dynamicScanEnvironmentFacingType(environmentFacingType != null ?
environmentFacingType :
Expand All @@ -111,6 +116,7 @@ protected HttpRequest<?> getBaseRequest(UnirestInstance unirest, String releaseI
.assessmentTypeId(assessmentTypeDescriptor.getAssessmentTypeId())
.entitlementId(entitlementId)
.entitlementFrequencyType(FoDEnums.EntitlementFrequencyType.valueOf(assessmentTypeDescriptor.getFrequencyType()))
.networkName(fodConnectNetwork != null ? fodConnectNetwork : "")
.build();

if (apiType.equals(FoDEnums.DastAutomatedApiTypes.Postman)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ public class FoDDastAutomatedScanSetupWebsiteCommand extends AbstractFoDScanSetu
private String macroSecondaryUsername;
@Option(names = {"--macro-secondary-password"})
private String macroSecondaryPassword;
@Option(names = {"--vpn"})
private String fodConnectNetwork;

@Override
protected String getScanType() {
Expand Down Expand Up @@ -116,6 +118,10 @@ protected HttpRequest<?> getBaseRequest(UnirestInstance unirest, String releaseI
loginMacroFileCreationSettings = new FoDScanDastAutomatedSetupWebsiteRequest.LoginMacroFileCreationType(macroPrimaryUsername,
macroPrimaryPassword, macroSecondaryUsername, macroSecondaryPassword);
}
if (fodConnectNetwork != null) {
// if Fortify Connect network site override environmentFacingType to Internal
environmentFacingType = FoDEnums.DynamicScanEnvironmentFacingType.Internal;
}

FoDScanAssessmentTypeDescriptor assessmentTypeDescriptor = FoDScanHelper.getEntitlementToUse(unirest, releaseId, FoDScanType.Dynamic,
assessmentType, entitlementFrequencyTypeMixin.getEntitlementFrequencyType(), entitlementId);
Expand All @@ -129,7 +135,7 @@ protected HttpRequest<?> getBaseRequest(UnirestInstance unirest, String releaseI
.restrictToDirectoryAndSubdirectories(restrictToDirectoryAndSubdirectories != null ? restrictToDirectoryAndSubdirectories : false)
.policy(scanPolicy)
.timeBoxInHours(timebox)
.dynamicScanEnvironmentFacingType(environmentFacingType != null ? environmentFacingType : FoDEnums.DynamicScanEnvironmentFacingType.Internal)
.dynamicScanEnvironmentFacingType(environmentFacingType != null ? environmentFacingType : FoDEnums.DynamicScanEnvironmentFacingType.External)
.timeZone(timeZoneToUse)
.requiresNetworkAuthentication(requiresNetworkAuthentication)
.networkAuthenticationSettings(networkAuthenticationSettings)
Expand All @@ -139,6 +145,7 @@ protected HttpRequest<?> getBaseRequest(UnirestInstance unirest, String releaseI
.requestFalsePositiveRemoval(requestFalsePositiveRemoval != null ? requestFalsePositiveRemoval : false)
.requestLoginMacroFileCreation(requiresLoginMacroCreation)
.loginMacroFileCreationDetails(loginMacroFileCreationSettings)
.networkName(fodConnectNetwork != null ? fodConnectNetwork : "")
.build();

return unirest.put(FoDUrls.DAST_AUTOMATED_SCANS + "/website-scan-setup")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ public class FoDDastAutomatedScanSetupWorkflowCommand extends AbstractFoDScanSet
private String password;
@Option(names = {"--false-positive-removal"})
private Boolean requestFalsePositiveRemoval;
@Option(names = {"--vpn"})
private String fodConnectNetwork;

@Override
protected String getScanType() {
Expand Down Expand Up @@ -85,7 +87,11 @@ protected HttpRequest<?> getBaseRequest(UnirestInstance unirest, String releaseI
networkAuthenticationSettings = new FoDScanDastAutomatedSetupWorkflowRequest.NetworkAuthenticationType(networkAuthenticationType, username, password);
}
String timeZoneToUse = FoDScanHelper.validateTimezone(unirest, timezone);

if (fodConnectNetwork != null) {
// if Fortify Connect network site override environmentFacingType to Internal
environmentFacingType = FoDEnums.DynamicScanEnvironmentFacingType.Internal;
}

FoDScanAssessmentTypeDescriptor assessmentTypeDescriptor = FoDScanHelper.getEntitlementToUse(unirest, releaseId, FoDScanType.Dynamic,
assessmentType, entitlementFrequencyTypeMixin.getEntitlementFrequencyType(), entitlementId);
entitlementId = assessmentTypeDescriptor.getEntitlementId();
Expand All @@ -100,6 +106,7 @@ protected HttpRequest<?> getBaseRequest(UnirestInstance unirest, String releaseI
.entitlementId(entitlementId)
.entitlementFrequencyType(FoDEnums.EntitlementFrequencyType.valueOf(assessmentTypeDescriptor.getFrequencyType()))
.requestFalsePositiveRemoval(requestFalsePositiveRemoval != null ? requestFalsePositiveRemoval : false)
.networkName(fodConnectNetwork != null ? fodConnectNetwork : "")
.build();

return unirest.put(FoDUrls.DAST_AUTOMATED_SCANS + "/workflow-scan-setup")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
FoDMastScanGetConfigCommand.class,
FoDMastScanImportCommand.class,
FoDMastScanListCommand.class,
//FoDMastScanSetupCommand.class,
FoDMastScanSetupCommand.class,
FoDMastScanStartCommand.class,
FoDMastScanWaitForCommand.class,
}
Expand Down
Loading

0 comments on commit f2be7b1

Please sign in to comment.