Bypass purls (mostly) for deny checks
This commit is contained in:
+9
-1
@@ -233,7 +233,7 @@ function validatePURL(allow_dependencies_licenses: string[] | undefined): void {
|
||||
return
|
||||
}
|
||||
const invalid_purls = allow_dependencies_licenses.filter(
|
||||
purl => !PackageURL.fromString(purl)
|
||||
purl => !isPURLValid(purl)
|
||||
)
|
||||
|
||||
if (invalid_purls.length > 0) {
|
||||
@@ -243,3 +243,11 @@ function validatePURL(allow_dependencies_licenses: string[] | undefined): void {
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
const isPURLValid = (purl: string): boolean => {
|
||||
try {
|
||||
return PackageURL.fromString(purl) !== null
|
||||
} catch (error) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
+33
-14
@@ -1,6 +1,7 @@
|
||||
import * as core from '@actions/core'
|
||||
import {Change} from './schemas'
|
||||
import {PackageURL} from 'packageurl-js'
|
||||
import {parsePURL} from './utils'
|
||||
|
||||
export async function getDeniedChanges(
|
||||
changes: Change[],
|
||||
@@ -11,18 +12,10 @@ export async function getDeniedChanges(
|
||||
|
||||
let hasDeniedPackage = false
|
||||
for (const change of changes) {
|
||||
let changedPackage: PackageURL
|
||||
try {
|
||||
changedPackage = PackageURL.fromString(change.package_url)
|
||||
} catch (error) {
|
||||
core.error(`Error parsing package URL '${change.package_url}': ${error}`)
|
||||
continue
|
||||
}
|
||||
|
||||
for (const denied of deniedPackages) {
|
||||
if (
|
||||
(!denied.version || changedPackage.version === denied.version) &&
|
||||
changedPackage.name === denied.name
|
||||
(!denied.version || change.version === denied.version) &&
|
||||
change.name === denied.name
|
||||
) {
|
||||
changesDenied.push(change)
|
||||
hasDeniedPackage = true
|
||||
@@ -30,10 +23,8 @@ export async function getDeniedChanges(
|
||||
}
|
||||
|
||||
for (const denied of deniedGroups) {
|
||||
if (
|
||||
changedPackage.namespace &&
|
||||
changedPackage.namespace === denied.namespace
|
||||
) {
|
||||
const namespace = getNamespace(change)
|
||||
if (namespace && namespace === denied.namespace) {
|
||||
changesDenied.push(change)
|
||||
hasDeniedPackage = true
|
||||
}
|
||||
@@ -48,3 +39,31 @@ export async function getDeniedChanges(
|
||||
|
||||
return changesDenied
|
||||
}
|
||||
|
||||
// getNamespace returns the namespace associated with the given change.
|
||||
// it tries to get this from the package_url member, but that won't exist
|
||||
// for all changes, so as a fallback it may create a new purl based on the
|
||||
// ecosystem and name associated with the change, then extract the namespace
|
||||
// from that.
|
||||
// returns '' if there is no namespace.
|
||||
export const getNamespace = (change: Change): string => {
|
||||
let purl_str: string
|
||||
if (change.package_url) {
|
||||
purl_str = change.package_url
|
||||
} else {
|
||||
purl_str = `pkg:${change.ecosystem}/${change.name}`
|
||||
}
|
||||
|
||||
try {
|
||||
const purl = parsePURL(purl_str)
|
||||
const namespace = purl.namespace
|
||||
if (namespace === undefined || namespace === null) {
|
||||
return ''
|
||||
} else {
|
||||
return namespace
|
||||
}
|
||||
} catch (e) {
|
||||
core.error(`Error parsing purl '${purl_str}': ${e}`)
|
||||
return ''
|
||||
}
|
||||
}
|
||||
|
||||
+2
-4
@@ -1,6 +1,6 @@
|
||||
import spdxSatisfies from 'spdx-satisfies'
|
||||
import {Change, Changes} from './schemas'
|
||||
import {isSPDXValid, octokitClient} from './utils'
|
||||
import {isSPDXValid, octokitClient, parsePURL} from './utils'
|
||||
import {PackageURL} from 'packageurl-js'
|
||||
|
||||
/**
|
||||
@@ -45,9 +45,7 @@ export async function getInvalidLicenseChanges(
|
||||
return true
|
||||
}
|
||||
|
||||
const changeAsPackageURL = PackageURL.fromString(
|
||||
encodeURI(change.package_url)
|
||||
)
|
||||
const changeAsPackageURL = parsePURL(encodeURI(change.package_url))
|
||||
|
||||
// We want to find if the licenseExclussion list contains the PackageURL of the Change
|
||||
// If it does, we want to filter it out and therefore return false
|
||||
|
||||
+27
-1
@@ -80,10 +80,36 @@ export const parsePURL = (purlString: string): PackageURL => {
|
||||
) {
|
||||
//packageurl-js does not support empty names, so will manually override it for deny-groups
|
||||
//https://github.com/package-url/packageurl-js/blob/master/src/package-url.js#L216
|
||||
const purl = PackageURL.fromString(`${purlString}TEMP_NAME`)
|
||||
const fixedPurlString = addTempName(purlString)
|
||||
const purl = PackageURL.fromString(fixedPurlString)
|
||||
purl.name = ''
|
||||
return purl
|
||||
} else if ((error as Error).message === `version must be percent-encoded`) {
|
||||
core.error(
|
||||
`Version must be percent-encoded. Removing version from purl: '${purlString}.`
|
||||
)
|
||||
const fixedPurlString = removeVersion(purlString)
|
||||
const purl = parsePURL(fixedPurlString)
|
||||
purl.version = ''
|
||||
return purl
|
||||
}
|
||||
core.error(`Error parsing purl: ${purlString}`)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
export const removeVersion = (purlString: string): string => {
|
||||
// sometimes these errors are actually caused by a final '/', so try removing that first
|
||||
if (purlString.endsWith('/')) {
|
||||
return purlString.substring(0, purlString.length - 1)
|
||||
}
|
||||
const idx = purlString.lastIndexOf('@')
|
||||
return purlString.substring(0, idx)
|
||||
}
|
||||
|
||||
export const addTempName = (purlString: string): string => {
|
||||
if (purlString.endsWith('/')) {
|
||||
return `${purlString}TEMP_NAME`
|
||||
}
|
||||
return `${purlString}/TEMP_NAME`
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user