-
Notifications
You must be signed in to change notification settings - Fork 3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' into v-mchatla/Rapid7InsightVM-UpdatingLastSave…
…dTime
- Loading branch information
Showing
1,174 changed files
with
111,020 additions
and
30,115 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
import { InvalidFileContentError } from "./../utils/validationError"; | ||
import { ExitCode } from "../utils/exitCode"; | ||
import fs from "fs"; | ||
|
||
type AttributeConfig = { | ||
mainTemplateAttributes: string[]; | ||
createUIDefinitionAttributes: string[]; | ||
}; | ||
|
||
const attributeConfig: AttributeConfig = { | ||
mainTemplateAttributes: ["descriptionMarkdown", "description"], | ||
createUIDefinitionAttributes: ["text", "description"], | ||
}; | ||
|
||
export function IsValidBrandingContent(filePath: string): ExitCode { | ||
// Skip validation if file path contains "SentinelOne" | ||
if (filePath.includes("SentinelOne")) { | ||
return ExitCode.SUCCESS; | ||
} | ||
|
||
const errors: string[] = []; | ||
|
||
// check if the file is mainTemplate.json or createUiDefinition.json | ||
if (filePath.endsWith("mainTemplate.json")) { | ||
validateFileContent(filePath, attributeConfig.mainTemplateAttributes, errors); | ||
} else if (filePath.endsWith("createUiDefinition.json")) { | ||
validateFileContent(filePath, attributeConfig.createUIDefinitionAttributes, errors); | ||
} else { | ||
console.warn(`Could not identify JSON file as mainTemplate.json or createUiDefinition.json. Skipping. File path: ${filePath}`); | ||
} | ||
|
||
// Throw a single error with all the error messages concatenated | ||
if (errors.length > 0) { | ||
throw new InvalidFileContentError(errors.join("\n")); | ||
} | ||
|
||
// Return success code after completion of the check | ||
return ExitCode.SUCCESS; | ||
} | ||
|
||
function validateFileContent(filePath: string, attributeNames: string[], errors: string[]): void { | ||
const fileContent = fs.readFileSync(filePath, "utf8"); | ||
const jsonContent = JSON.parse(fileContent); | ||
|
||
traverseAttributes(jsonContent, attributeNames, errors); | ||
} | ||
|
||
function traverseAttributes(jsonContent: any, attributeNames: string[], errors: string[]): void { | ||
for (const key in jsonContent) { | ||
if (jsonContent.hasOwnProperty(key)) { | ||
const attributeValue = jsonContent[key]; | ||
if (attributeNames.includes(key) && typeof attributeValue === "string") { | ||
validateAttribute(attributeValue, key, errors); | ||
} | ||
if (typeof attributeValue === "object" && attributeValue !== null) { | ||
traverseAttributes(attributeValue, attributeNames, errors); | ||
} | ||
} | ||
} | ||
} | ||
|
||
function validateAttribute(attributeValue: string, attributeName: string, errors: string[]): void { | ||
const sentinelRegex = /(?<!Microsoft\s)(?<!\S)Sentinel(?!\S)/g; | ||
const updatedValue = attributeValue.replace(sentinelRegex, "Microsoft Sentinel"); | ||
|
||
if (attributeValue !== updatedValue) { | ||
const error = `Inaccurate product branding used in '${attributeName}' for '${attributeValue}'. Use "Microsoft Sentinel" instead of "Sentinel"`; | ||
errors.push(error); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import { InvalidSolutionIDValidationError } from "./../utils/validationError"; | ||
import { ExitCode } from "../utils/exitCode"; | ||
import fs from "fs"; | ||
|
||
export function IsValidSolutionID(filePath: string): ExitCode { | ||
// Check if the file path ends with mainTemplate.json | ||
if (!filePath.endsWith("mainTemplate.json")) { | ||
return ExitCode.SUCCESS; | ||
} | ||
|
||
// Parse the JSON content from the file | ||
const jsonContent = JSON.parse(fs.readFileSync(filePath, "utf8")); | ||
|
||
// Get the 'variables' section from the JSON | ||
const variables = jsonContent.variables; | ||
|
||
// Check if 'solutionId' attribute is present | ||
if (variables && "solutionId" in variables) { | ||
const solutionId = variables.solutionId; | ||
|
||
// Validate if the solution ID is empty | ||
if (!solutionId) { | ||
throw new InvalidSolutionIDValidationError(`Empty solution ID. Expected format: publisherID.offerID. and it must be in lowercase. Found empty value.`); | ||
} | ||
|
||
// Validate the solution ID format | ||
const regex = /^[^.]+\.[^.]+$/; | ||
if (!regex.test(solutionId)) { | ||
throw new InvalidSolutionIDValidationError(`Invalid solution ID format. Expected format: publisherID.offerID. and it must be in lowercase. Found: ${solutionId}`); | ||
} | ||
|
||
// Validate the solution ID case (lowercase) | ||
if (solutionId !== solutionId.toLowerCase()) { | ||
throw new InvalidSolutionIDValidationError(`Invalid solution ID format. Expected format: publisherID.offerID. and it must be in lowercase. Found: ${solutionId}`); | ||
} | ||
} else { | ||
throw new InvalidSolutionIDValidationError(`Missing 'solutionId' attribute in the file. File path: ${filePath}`); | ||
} | ||
|
||
// Return success code after completion of the check | ||
return ExitCode.SUCCESS; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,190 @@ | ||
function GetCatelogDetails($offerId) | ||
{ | ||
if ($null -eq $offerId -or $offerId -eq '') | ||
{ | ||
Write-Host "Provided OfferId for CatelogAPI details is blank! Please provide valid OfferId!"; | ||
return $null; | ||
} | ||
else { | ||
try { | ||
$formatUri = 'https://catalogapi.azure.com/offers?api-version=2018-08-01-beta&$filter=(categoryIds/any(cat:+cat+eq+''AzureSentinelSolution'')+or+keywords/any(key:+contains(key,''f1de974b-f438-4719-b423-8bf704ba2aef'')))+and+(offerId+eq+%27'+ $offerId +'%27)' | ||
$response = Invoke-RestMethod -Uri $formatUri -Method 'GET' -Headers $headers -Body $body | ||
|
||
$offerDetails = $response.items | Where-Object offerId -eq $offerId | ||
|
||
if ($null -eq $offerDetails) | ||
{ | ||
# when not found by offerId then use planId | ||
$offerDetails = $response.items | Where-Object planId -eq $offerId | ||
} | ||
|
||
if ($null -eq $offerDetails) | ||
{ | ||
# DETAILS NOT FOUND | ||
Write-Host "CatelogAPI Details not found for offerId $offerId" | ||
return $null; | ||
} | ||
else { | ||
Write-Host "CatelogAPI Details found for offerId $offerId" | ||
return $offerDetails; | ||
} | ||
} | ||
catch { | ||
Write-Host "Error occured in CatelogAPI. Error Details : $_"; | ||
return $null; | ||
} | ||
} | ||
} | ||
|
||
function CompareVersionStrings([string]$Version1, [string]$Version2) { | ||
|
||
$v1 = $Version1.Split('.') -replace '^0', '0.' | ||
$v2 = $Version2.Split('.') -replace '^0', '0.' | ||
|
||
[Array]::Resize( [ref] $v1, 4 ) | ||
[Array]::Resize( [ref] $v2, 4 ) | ||
|
||
for ($i=0; $i-lt 4; $i++) { | ||
switch (($v1[$i].length).CompareTo(($v2[$i].length))) { | ||
{$_ -lt 0} { $v1[$i] = $v1[$i].PadRight($v2[$i].Length,'0') } | ||
{$_ -gt 0} { $v2[$i] = $v2[$i].PadRight($v1[$i].Length,'0') } | ||
} | ||
} | ||
|
||
$v1f = $v1 | % {[float]$_} | ||
$v2f = $v2 | % {[float]$_} | ||
|
||
return [Collections.StructuralComparisons]::StructuralComparer.Compare( $v1f, $v2f ) | ||
} | ||
|
||
function GetNewVersion($packageVersionAttribute, $dataFileContentObject, $defaultPackageVersion, $templateSpecAttribute, $isNewSolution) | ||
{ | ||
$templateSpecDefaultVersion = '2.0.0' | ||
if($packageVersionAttribute) | ||
{ | ||
if ($null -eq $dataFileContentObject.Version -or $dataFileContentObject.Version -eq '') | ||
{ | ||
return $templateSpecAttribute ? ($templateSpecDefaultVersion, $true) : ($defaultPackageVersion, $true) | ||
} | ||
else | ||
{ | ||
return ($dataFileContentObject.Version, $false) | ||
} | ||
} | ||
else | ||
{ | ||
return $templateSpecAttribute ? ($templateSpecDefaultVersion, $true) : ($defaultPackageVersion, $true) | ||
} | ||
} | ||
|
||
function GetIncrementedVersion($version) | ||
{ | ||
$major,$minor,$build,$revision = $version.split(".") | ||
$newBuildVersion = [int]$build + 1 | ||
return "$major.$minor.$newBuildVersion" | ||
} | ||
|
||
function GetOfferVersion($offerId, $mainTemplateUrl) | ||
{ | ||
if ($null -eq $mainTemplateUrl -or $mainTemplateUrl -eq '') | ||
{ | ||
Write-Host "Provided MainTemplateUrl for GetOfferVersion details is blank! Please provide valid MainTemplateUrl!"; | ||
return $null; | ||
} | ||
else | ||
{ | ||
try | ||
{ | ||
$response = Invoke-RestMethod -Uri $mainTemplateUrl -Method 'GET' -Headers $headers | ||
$metadataDetails = $response.resources | Where-Object { ($_.name -eq "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/', variables('_solutionId'))]" -or $_.name -eq "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/', variables('_sourceId'))]") -and ($_.type -eq "Microsoft.OperationalInsights/workspaces/providers/metadata")}; | ||
|
||
if ($null -eq $metadataDetails -or $metadataDetails -eq '') | ||
{ | ||
Write-Host "Offer Metadata Version details in MainTemplate is not found!" | ||
return $null; | ||
} | ||
else | ||
{ | ||
Write-Host "Offer Metadata Version details in MainTemplate is found!" | ||
return $metadataDetails.properties.version; | ||
} | ||
} | ||
catch | ||
{ | ||
Write-Host "Error occured in CatelogAPI. Error Details11 : $_"; | ||
return $null; | ||
} | ||
} | ||
} | ||
|
||
function GetPackageVersion($defaultPackageVersion, $offerId, $offerDetails, $packageVersionAttribute, $userInputPackageVersion) | ||
{ | ||
if ($packageVersionAttribute) | ||
{ | ||
$userInputMajor,$userInputMinor,$userInputBuild,$userInputRevision = $userInputPackageVersion.split(".") | ||
$defaultMajor,$defaultMinor,$defaultBuild,$defaultRevision = $defaultPackageVersion.split(".") | ||
|
||
if ($userInputMajor -ge '2' -and $userInputMinor -gt $defaultMinor) | ||
{ | ||
#return as is value of package version as middle value is greater | ||
return $userInputPackageVersion | ||
} | ||
} | ||
|
||
$defaultVersionMessage = "Package Version set to Default version $defaultPackageVersion" | ||
if ($null -eq $offerDetails) | ||
{ | ||
Write-Host "CatalogAPI Offer details not found for given offerId $offerId. $defaultVersionMessage" | ||
return $defaultPackageVersion | ||
} | ||
else | ||
{ | ||
$mainTemplateDetails = $offerDetails.plans.artifacts | Where-Object {$_.type -eq "Template" -and $_.name -eq "DefaultTemplate"} | ||
|
||
if ($null -eq $mainTemplateDetails) | ||
{ | ||
# WE WILL TAKE WHATEVER VERSION IS SPECIFIED IN THE DATA INPUT FILE WITHOUT INCREMENTING IT | ||
Write-Host "CatalogAPI mainTemplate details not found for given offerId $offerId. $defaultVersionMessage" | ||
return $defaultPackageVersion | ||
} | ||
else | ||
{ | ||
# CHECK IF CATELOG API HAS DETAILS AND IDENTIFY THE VERSION | ||
$mainTemplateUri = $mainTemplateDetails.uri | ||
|
||
if ($null -eq $mainTemplateUri) | ||
{ | ||
Write-Host "CatalogAPI mainTemplate details missing URI for given offerId $offerId. $defaultVersionMessage" | ||
return $defaultPackageVersion | ||
} | ||
else | ||
{ | ||
# OFFER DETAILS FOUND SO IDENTIFY THE VERSION IN MAINTEMPLATE FILE | ||
$offerMetadataVersion = GetOfferVersion $offerId $mainTemplateUri | ||
if ($null -eq $offerMetadataVersion -or $offerMetadataVersion -eq '') | ||
{ | ||
Write-Host "CatalogAPI mainTemplate details URI file is missing version or version is blank so $defaultVersionMessage" | ||
return $defaultPackageVersion | ||
} | ||
else | ||
{ | ||
$identifiedOfferVersion = $offerMetadataVersion | ||
$catelogMajor,$catelogminor,$catelogbuild,$catelogrevision = $identifiedOfferVersion.split(".") | ||
$defaultMajor,$defaultminor,$defaultbuild,$defaultrevision = $defaultPackageVersion.split(".") | ||
|
||
if ($defaultMajor -gt $catelogMajor) | ||
{ | ||
# eg: 3.0.0 > 2.0.1 ==> 3.0.0 | ||
Write-Host "Default Package version is greater then the CatalogAPI version so $defaultVersionMessage" | ||
return $defaultPackageVersion | ||
} | ||
else | ||
{ | ||
$packageVersion = GetIncrementedVersion $identifiedOfferVersion | ||
return $packageVersion | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -183,6 +183,10 @@ | |
{ | ||
"Name": "Process", | ||
"Type": "string" | ||
}, | ||
{ | ||
"Name": "Username", | ||
"Type": "string" | ||
} | ||
] | ||
} |
Oops, something went wrong.