Skip to content

Commit

Permalink
remove the code in EP001 for detecting duplicates
Browse files Browse the repository at this point in the history
  • Loading branch information
DinoChiesa committed Sep 27, 2024
1 parent ad3a05d commit 3e768a2
Showing 1 changed file with 74 additions and 165 deletions.
239 changes: 74 additions & 165 deletions lib/package/plugins/EP001-corsPolicyAttachment.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright 2019-2020 Google LLC
Copyright 2019-2020,2024 Google LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand All @@ -15,150 +15,63 @@
*/

const ruleId = require("../myUtil.js").getRuleId(),
debug = require("debug")("apigeelint:" + ruleId);
debug = require("debug")("apigeelint:" + ruleId);

const plugin = {
ruleId,
name: "Check for multiple CORS policies",
message:
"Only one CORS Policy is necessary. It should attach in the Proxy Preflow.",
fatal: false,
severity: 2, // error
nodeType: "Endpoint",
enabled: true
};

const onBundle = function(bundle, cb) {
debug('onBundle');
let checker = new BundleChecker(bundle);
let flagged = checker.check();

if (typeof(cb) == 'function') {
cb(null, flagged);
}
};

const onProxyEndpoint = function(endpoint, cb) {
debug('onProxyEndpoint');
let checker = new EndpointChecker(endpoint, true);
let flagged = checker.check();
if (typeof(cb) == 'function') {
cb(null, flagged);
}
};

const onTargetEndpoint = function(endpoint, cb) {
debug('onTargetEndpoint');
let checker = new EndpointChecker(endpoint, false);
let flagged = checker.check();
if (typeof(cb) == 'function') {
cb(null, flagged);
}
};

const _markPolicy = (policy, msg) => {
let result = {
ruleId: plugin.ruleId,
severity: plugin.severity,
source: policy.getSource(),
line: policy.getElement().lineNumber,
column: policy.getElement().columnNumber,
nodeType: "Policy",
message: msg
};
policy.addMessage(result);
};


const _markStep = (step, msg) => {
let result = {
ruleId: plugin.ruleId,
severity: plugin.severity,
entity: step,
line: step.getElement().lineNumber,
column: step.getElement().columnNumber,
nodeType: "Step",
message: msg
};
step.addMessage(result);
};

const _markEndpoint = (endpoint, msg) => {
var result = {
ruleId: plugin.ruleId,
severity: plugin.severity,
nodeType: plugin.nodeType,
message: msg
};
endpoint.addMessage(result);
};

class BundleChecker {
constructor(bundle) {
debug('BundleChecker ctor');
this.bundle = bundle;
this.flagged = false;
}

check() {
if (this.bundle.policies) {

debug("number of policies: " + this.bundle.policies.length);
let corsPolicies = this.bundle.policies.filter(policy => (policy.getType() === "CORS"));
ruleId,
name: "Check for multiple CORS policies",
message:
"Only one CORS Policy is necessary. It should attach in the Proxy Preflow.",
fatal: false,
severity: 2, // error
nodeType: "Endpoint",
enabled: true
};

debug("number of CORS policies: " + corsPolicies.length);
if (corsPolicies.length > 1) {
this.flagged = this._checkForDuplicatePolicies(corsPolicies);
}
return this.flagged;
}
const onProxyEndpoint = function (endpoint, cb) {
debug("onProxyEndpoint");
const checker = new EndpointChecker(endpoint, true);
const flagged = checker.check();
if (typeof cb == "function") {
cb(null, flagged);
}
};

_checkForDuplicatePolicies(policies) {
let dupes = BundleChecker._getDuplicates('/CORS', policies);
if (dupes.length > 0) {
debug("there are " + dupes.length + " repeated policies.");
let duplicatePolicyNames = dupes.map( p => p.getName()).join(" ");
debug("duplicate policies: " + duplicatePolicyNames);
policies.forEach(policy => {
debug("duplicate policy warning for " + policy.getName());
_markPolicy(
policy,
"The following CORS policies are configured: " +
duplicatePolicyNames
);
});
return true;
}
const onTargetEndpoint = function (endpoint, cb) {
debug("onTargetEndpoint");
const checker = new EndpointChecker(endpoint, false);
const flagged = checker.check();
if (typeof cb == "function") {
cb(null, flagged);
}
};

static _getDuplicates(xpath, policies) {
let dupes = [];
for (var i = 0; i < policies.length - 1; i++) {
for (var j = i + 1; j < policies.length; j++) {
var p1 = policies[i].select(xpath).toString().trim();
var p2 = policies[j].select(xpath).toString().trim();
debug("comparing -> \n1st policy:\n" + p1 + "\n2nd policy:\n" + p2);
if (p1 === p2) {
if (dupes.indexOf(policies[i]) === -1) {
dupes.push(policies[i]);
debug(policies[i].getName() + " is a duplicate!");
}
if (dupes.indexOf(policies[j]) === -1) {
dupes.push(policies[j]);
debug(policies[j].getName() + " is a duplicate!");
}
}
}
}
return dupes;
}
}
const _markStep = (step, msg) => {
let result = {
ruleId: plugin.ruleId,
severity: plugin.severity,
entity: step,
line: step.getElement().lineNumber,
column: step.getElement().columnNumber,
nodeType: "Step",
message: msg
};
step.addMessage(result);
};

const _markEndpoint = (endpoint, msg) => {
var result = {
ruleId: plugin.ruleId,
severity: plugin.severity,
nodeType: plugin.nodeType,
message: msg
};
endpoint.addMessage(result);
};

class EndpointChecker {
constructor(endpoint, isProxyEndpoint) {
debug('EndpointChecker ctor (%s)', endpoint.getName());
debug("EndpointChecker ctor (%s)", endpoint.getName());
this.endpoint = endpoint;
this.bundle = endpoint.parent;
this.isProxyEndpoint = isProxyEndpoint;
Expand All @@ -170,62 +83,60 @@ class EndpointChecker {
this.corsPoliciesInBundle =
this.bundle.policies &&
this.bundle.policies
.filter(policy => (policy.getType() === "CORS"))
.reduce(function(obj, policy) {
obj[policy.getName()] = policy;
return obj;
}, {});
.filter((policy) => policy.getType() === "CORS")
.reduce(function (obj, policy) {
obj[policy.getName()] = policy;
return obj;
}, {});

if (this.corsPoliciesInBundle) {
let keys = Object.keys(this.corsPoliciesInBundle);
debug('CORS policies in endpoint: ' + JSON.stringify(keys));
debug("CORS policies in endpoint: " + JSON.stringify(keys));

// Ensure at most one attachment for any CORS policy,
// or, conditions on all CORS policies.
let corsStepsInEndpoint = this.endpoint
.getSteps()
.filter( step => keys.indexOf(step.getName())>=0);
.filter((step) => keys.indexOf(step.getName()) >= 0);

if (this.isProxyEndpoint) {
if (corsStepsInEndpoint.length > 1) {
this.flagged = this._checkStepsForMissingConditions(corsStepsInEndpoint);
}
else {
debug('zero or one CORS policies in this endpoint');
this.flagged =
this._checkStepsForMissingConditions(corsStepsInEndpoint);
} else {
debug("zero or one CORS policies in this endpoint");
}
}
else {
} else {
if (corsStepsInEndpoint.length > 0) {
corsStepsInEndpoint.forEach(step => {
corsStepsInEndpoint.forEach((step) => {
_markStep(
step,
"There is a CORS policy attached to a TargetEndpoint. Attach CORS policies to a ProxyEndpoint.");

"There is a CORS policy attached to a TargetEndpoint. Attach CORS policies to a ProxyEndpoint."
);
});
this.flagged = true;
}
}
}
return this.flagged;
}
catch(e) {
} catch (e) {
console.log(e);
return false;
}
}

_checkStepsForMissingConditions(steps) {
let anyStepsLackCondition =
steps.filter( step => {
if ( ! step.getCondition()) {
let name = step.getName();
_markStep(
step,
//this.corsPoliciesInBundle[name],
`There are multiple CORS policies and policy ${name} is attached to a Step without a Condition.`);
return true;
}
});
let anyStepsLackCondition = steps.filter((step) => {
if (!step.getCondition()) {
let name = step.getName();
_markStep(
step,
//this.corsPoliciesInBundle[name],
`There are multiple CORS policies and policy ${name} is attached to a Step without a Condition.`
);
return true;
}
});

if (anyStepsLackCondition.length > 0) {
_markEndpoint(
Expand All @@ -237,10 +148,8 @@ class EndpointChecker {
}
}


module.exports = {
plugin,
onBundle,
onProxyEndpoint,
onTargetEndpoint
};

0 comments on commit 3e768a2

Please sign in to comment.