67 lines
2.7 KiB
JavaScript
67 lines
2.7 KiB
JavaScript
// Generate a "software footprint" detection rule from simple inputs, in the
|
|
// shape the deployment model already uses (`detectionType` + `detectionRule`).
|
|
// MSI maps to a product-code rule; file/registry produce Intune-style custom
|
|
// PowerShell detection scripts so they flow straight through publishing without
|
|
// extra mapping. Pure + unit-tested.
|
|
|
|
function fileDetectionScript({ path, version }) {
|
|
const lines = [`$path = '${path.replace(/'/g, "''")}'`, 'if (Test-Path -LiteralPath $path) {'];
|
|
if (version) {
|
|
lines.push(" $found = (Get-Item -LiteralPath $path).VersionInfo.ProductVersion");
|
|
lines.push(` if ($found -and [version]$found -ge [version]'${version}') { Write-Output 'Detected'; exit 0 }`);
|
|
} else {
|
|
lines.push(" Write-Output 'Detected'; exit 0");
|
|
}
|
|
lines.push('}');
|
|
lines.push('exit 1');
|
|
return lines.join('\n');
|
|
}
|
|
|
|
function registryDetectionScript({ keyPath, valueName, valueData }) {
|
|
const key = keyPath.replace(/'/g, "''");
|
|
const lines = [`$key = '${key}'`];
|
|
if (valueName) {
|
|
lines.push("$value = (Get-ItemProperty -LiteralPath $key -ErrorAction SilentlyContinue).'" + valueName.replace(/'/g, "''") + "'");
|
|
if (valueData) {
|
|
lines.push(`if ($value -eq '${valueData.replace(/'/g, "''")}') { Write-Output 'Detected'; exit 0 }`);
|
|
} else {
|
|
lines.push("if ($null -ne $value) { Write-Output 'Detected'; exit 0 }");
|
|
}
|
|
} else {
|
|
lines.push("if (Test-Path -LiteralPath $key) { Write-Output 'Detected'; exit 0 }");
|
|
}
|
|
lines.push('exit 1');
|
|
return lines.join('\n');
|
|
}
|
|
|
|
export function buildDetectionRule(input = {}) {
|
|
switch (input.type) {
|
|
case 'msi': {
|
|
if (!input.productCode) throw new Error('productCode is required for MSI detection');
|
|
return {
|
|
detectionType: 'msi-product-code',
|
|
detectionRule: input.productCode,
|
|
description: `MSI product code ${input.productCode}`
|
|
};
|
|
}
|
|
case 'file': {
|
|
if (!input.path) throw new Error('path is required for file detection');
|
|
return {
|
|
detectionType: 'custom-script',
|
|
detectionRule: fileDetectionScript(input),
|
|
description: input.version ? `File ${input.path} version ≥ ${input.version}` : `File exists: ${input.path}`
|
|
};
|
|
}
|
|
case 'registry': {
|
|
if (!input.keyPath) throw new Error('keyPath is required for registry detection');
|
|
return {
|
|
detectionType: 'custom-script',
|
|
detectionRule: registryDetectionScript(input),
|
|
description: input.valueName ? `Registry ${input.keyPath}\\${input.valueName}` : `Registry key ${input.keyPath}`
|
|
};
|
|
}
|
|
default:
|
|
throw new Error(`Unknown detection type "${input.type}" (expected msi, file, or registry)`);
|
|
}
|
|
}
|