diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 892ea97f..f9ed2e52 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,6 +1,32 @@ CHANGELOG -2.1.15 +2.1.16 +UTIL: +* type=address | new 'filter=(name same.as.region.predefined)' +* class UTIL | extend if API mode - with App-id/AV/WF/Threat version info +* type=address | introduce 'filter=(tag is.set)' +* type=xml-issue | extend with rule tag object validation for twice set the same tag object +* introduce GroupTagRuleContainer to all Rule classes + +BUGFIX: +* class Sub | bugfix for default-securiy-rules | if partial config is already available +* type=address-merger | bugfix to not delete TAG object from upperlevel if TAG object with same name exist at childDG +* type=address/service actions=move | bugfix if group with same name already exist - correctly skip movement +* class PANConf | fix for PHP 8.2 +* type=address/service actions=move:shared location=any - bugfix for Firewall config +* type=rule-merger | bugfix to not add description twice, which exceeds description length to >1024 +* type=tag actions=delete 'filter=(object is.unused) | bugfix for group-tag used in Rules, reference missing +* introduce GroupTagRulecontainer - to fix type=tag-merger issue if group-tag is used +* class PANConf - bugfix for type=stats on FW config for tmp/ghost object count on 'shared' +* type=XYZ outputformatset=setcommand.txt | bugfix to always have correct xPath availalble for set commands +* bugfix - related to TAG objects where name include character '(' and/or ')' - final fix for tag-merger including method createTag() +* bugfix for argument outputformatset - no multi-vsys device - remove vsys1 to fit set commands + +GENERAL: +* develop pan-os-php-api | per default enable shadow-json checkbox - with shadow-nojson, output has a bug and filter are not working correctly - fixing later + + +2.1.15 (20230830) UTIL: BUGFIX: diff --git a/READMEdocker.md b/READMEdocker.md index 2ecc45c8..e1b08213 100644 --- a/READMEdocker.md +++ b/READMEdocker.md @@ -71,50 +71,34 @@ cd [/rootFolder/parentFolder/childFolder] #Additional Information -Docker build -============ - -There are Dockerfiles available with OS: Ubuntu20/22 and CentOS 7 - -For a quick start please use [WIKI docker](https://github.com/PaloAltoNetworks/pan-os-php/wiki/docker) - - -* **MacOS** : [run on MacOS terminal] - ```bash - cd [pan-os-php Root folder] - docker build -t pan-os-php -f docker/Dockerfile . - cd [go to the Folder you like to share with the Container] - docker run --name panosphp --rm -v ${PWD}:/share -it pan-os-php - ``` - -* **WINDOWS** : [run on Windows terminal] - ```bash - cd [pan-os-php Root folder] - docker build -t pan-os-php -f docker/Dockerfile . - cd [go to the Folder you like to share with the Container] - docker run --name panosphp --rm -v "%CD%":/share -it pan-os-php - ``` - - - - Docker PAN-OS-PHP API and UI ============ final production Container: ```bash - cd [pan-os-php Root folder] - docker build -t pan-os-php-api:latest -f docker/Dockerfile-API . - docker run -d -p 8082:80 pan-os-php-api:latest + docker run -d -p 8082:80 swaschkut/pan-os-php-api:latest ``` -local Development Container: +PAN-OS-PHP UI is available at: (which triggers next PAN-OS-PHP API) ```bash - docker run -d -p 8082:80 --mount type=bind,source="[absolute_ROOTFOLDER]/pan-os-php",target=/var/www/html -v [absolute_ROOTFOLDER]/pan-os-php/var/docker/uploads.ini:/usr/local/etc/php/conf.d/uploads.ini php:apache + http://localhost:8082/utils/develop/ui ``` -PAN-OS-PHP UI is available at: (which triggers next PAN-OS-PHP API) +PAN-OS-PHP API is also working with PAN-OS XML API, therefor you need to prepare you Docker installation: +```bash + API: http://localhost:8082/utils/api/v1/tool.php/key-manager?&add=MGMTIP&user=USERNAME&pw=PASSWORD + ``` + + +Examples to run PAN-OS-PHP against PAN-OS FW and Panorama offline configuration files, and manipulate in the same way as on PAN-OS-PHP ClI: ```bash - http://localhost:8082/utils/develop/ui + ClI: pan-os-php type=address help + API: http://localhost:8082/utils/api/v1/tool.php/address?help ``` + ```bash + CLI: pan-os-php type=address listactions + API: http://localhost:8082/utils/api/v1/tool.php/address?listactions + ``` + + To get it working on your own PAN-OS Firewall / Panorama config files, please upload your config files via PAN-OS-PHP UI (URL above) @@ -171,18 +155,34 @@ The following "RESTAPI" routes are available: - /xml-op-json - /bpa-generator -PAN-OS-PHP API is also working with PAN-OS XML API, therefor you need to prepare you Docker installation: -```bash - API: http://localhost:8082/utils/api/v1/tool.php/key-manager?&add=MGMTIP&user=USERNAME&pw=PASSWORD - ``` -Examples to run PAN-OS-PHP against PAN-OS FW and Panorama offline configuration files, and manipulate in the same way as on PAN-OS-PHP ClI: - ```bash - ClI: pan-os-php type=address help - API: http://localhost:8082/utils/api/v1/tool.php/address?help - ``` +Docker build +============ + +There are Dockerfiles available with OS: Ubuntu20/22 and CentOS 7 + +For a quick start please use [WIKI docker](https://github.com/PaloAltoNetworks/pan-os-php/wiki/docker) + + +* **MacOS** : [run on MacOS terminal] + ```bash + cd [pan-os-php Root folder] + docker build -t pan-os-php -f docker/Dockerfile . + cd [go to the Folder you like to share with the Container] + docker run --name panosphp --rm -v ${PWD}:/share -it pan-os-php + ``` + +* **WINDOWS** : [run on Windows terminal] + ```bash + cd [pan-os-php Root folder] + docker build -t pan-os-php -f docker/Dockerfile . + cd [go to the Folder you like to share with the Container] + docker run --name panosphp --rm -v "%CD%":/share -it pan-os-php + ``` + +---------------- +local Development Container: ```bash - CLI: pan-os-php type=address listactions - API: http://localhost:8082/utils/api/v1/tool.php/address?listactions - ``` + docker run -d -p 8082:80 --mount type=bind,source="[absolute_ROOTFOLDER]/pan-os-php",target=/var/www/html -v [absolute_ROOTFOLDER]/pan-os-php/var/docker/uploads.ini:/usr/local/etc/php/conf.d/uploads.ini php:apache + ``` \ No newline at end of file diff --git a/docker/Dockerfile-API b/docker/Dockerfile-API index b02a8948..bae6935f 100644 --- a/docker/Dockerfile-API +++ b/docker/Dockerfile-API @@ -1,4 +1,4 @@ -FROM php:8.0-apache +FROM php:8.1-apache SHELL ["/bin/bash", "-c"] diff --git a/lib/container-classes/GroupTagRuleContainer.php b/lib/container-classes/GroupTagRuleContainer.php new file mode 100644 index 00000000..4ee03f7c --- /dev/null +++ b/lib/container-classes/GroupTagRuleContainer.php @@ -0,0 +1,266 @@ +owner = $owner; + $this->name = 'group-tag'; + + $this->findParentCentralStore( 'tagStore' ); + } + + + public function removeAllTags() + { + $this->removeAll(); + $this->rewriteXML(); + } + + public function removeTag(Tag $tag, $rewriteXML = TRUE) + { + + $ret = $this->remove($tag); + + if( $ret && $rewriteXML ) + { + $this->rewriteXML(); + } + + return $ret; + } + + public function API_removeTag(Tag $tag, $rewriteXML = TRUE) + { + if( $this->removeTag($tag, $rewriteXML) ) + { + $con = findConnectorOrDie($this); + $xpath = $this->getXPath(); + $con->sendDeleteRequest($xpath); + + return TRUE; + } + + return FALSE; + } + + + public function merge(GroupTagRuleContainer $container, $exclusionFilter = null) + { + $change = FALSE; + foreach( $container->o as $obj ) + { + if( !$this->has($obj) ) + { + $exclude = FALSE; + if( $exclusionFilter !== null ) + { + foreach( $exclusionFilter as &$filter ) + { + if( strpos($obj->name(), $filter) === 0 ) + { + $exclude = TRUE; + break; + } + } + } + + if( !$exclude ) + { + $change = TRUE; + $this->addTag($obj); + } + } + } + + return $change; + } + + /** + * @param Tag|string can be Tag object or tag name (string). this is case sensitive + * @param bool + * @return bool + */ + public function hasTag($tag, $caseSensitive = TRUE) + { + return $this->has($tag, $caseSensitive); + } + + /** + * @param Tag|string can be Tag object or tag name (string). this is case sensitive + * @return bool + */ + public function hasTagRegex($regex) + { + return $this->hasObjectRegex($regex); + } + + + /** + * add a Tag to this container + * @param string|Tag + * @param bool + * @return bool + */ + public function addTag($Obj, $rewriteXML = TRUE) + { + if( is_string($Obj) ) + { + $f = $this->parentCentralStore->findOrCreate($Obj); + if( $f === null ) + { + derr(": Error : cannot find tag named '" . $Obj . "'\n"); + } + return $this->addTag($f); + } + + $ret = $this->add($Obj); + + if( $ret && $rewriteXML ) + { + $this->rewriteXML(); + } + + return $ret; + } + + /** + * @param Tag|String $Obj + * @param bool|true $rewriteXML + * @return bool + */ + public function API_addTag($Obj, $rewriteXML = TRUE) + { + if( $this->addTag($Obj, $rewriteXML) ) + { + $con = findConnectorOrDie($this); + + $con->sendSetRequest($this->getXPath(), $Obj->name()); + + return TRUE; + } + + return FALSE; + } + + public function &getXPath() + { + $xpath = $this->owner->getXPath() . '/group-tag'; + return $xpath; + } + + + /** + * returns a copy of current Tag array + * @return Tag[] + */ + public function tags() + { + return $this->o; + } + + + /** + * @param DOMElement $xml + * * should only be called from a Rule constructor + * @ignore + */ + public function load_from_domxml($xml) + { + $this->xmlroot = $xml; + $toBeCleaned = array(); + + $f = $this->parentCentralStore->findOrCreate($xml->textContent, $this); + $this->o[] = $f; + /* + foreach( $xml->childNodes as $node ) + { + if( $node->nodeType != 1 ) continue; + + if( strlen($node->textContent) < 1 ) + { + mwarning('invalid (empty) tag name found in rule "' . $this->owner->toString() . '", IT WILL BE CLEANED', $node); + $toBeCleaned[] = $node; + } + else + { + $f = $this->parentCentralStore->findOrCreate($node->textContent, $this); + $this->o[] = $f; + } + } + + foreach( $toBeCleaned as $cleanMe ) + { + $xml->removeChild($cleanMe); + } + */ + } + + public function rewriteXML() + { + if( count($this->o) > 0 ) + { + if( $this->xmlroot === null ) + $this->xmlroot = DH::createElement($this->owner->xmlroot, 'group-tag'); + $tmpKey = key($this->o); + #print "|".$this->o[$tmpKey]->name()."|\n"; + $tmpName = $this->o[$tmpKey]->name(); + TAG::revertreplaceNamewith( $tmpName ); + $this->xmlroot->textContent = $tmpName; + #DH::Hosts_to_xmlDom($this->xmlroot, $this->o, 'member', FALSE); + } + else + { + if( $this->xmlroot !== null ) + { + $this->owner->xmlroot->removeChild($this->xmlroot); + $this->xmlroot = null; + } + } + } + + + + public function copy(GroupTagRuleContainer $other) + { + $this->removeAll(); + + foreach( $other->o as $member ) + { + $this->add($member); + } + + $this->rewriteXML(); + } + +} + + + diff --git a/lib/device-and-system-classes/PANConf.php b/lib/device-and-system-classes/PANConf.php index b18bc726..d8e36f95 100644 --- a/lib/device-and-system-classes/PANConf.php +++ b/lib/device-and-system-classes/PANConf.php @@ -144,6 +144,8 @@ class PANConf public $_auditComment = false; + public $panorama = null; + public function name() { return $this->name; @@ -903,12 +905,12 @@ public function display_statistics( $connector = null ) $stdoutarray['address objects']['unused'] = $gnaddresssUnused; $stdoutarray['addressgroup objects'] = array(); - $stdoutarray['addressgroup objects']['shared'] = $this->addressStore->countTmpAddresses(); + $stdoutarray['addressgroup objects']['shared'] = $this->addressStore->countAddressGroups(); $stdoutarray['addressgroup objects']['total VSYSs'] = $gnaddressGs; $stdoutarray['addressgroup objects']['unused'] = $gnaddressGsUnused; $stdoutarray['temporary address objects'] = array(); - $stdoutarray['temporary address objects']['shared'] = $this->addressStore->countAddresses(); + $stdoutarray['temporary address objects']['shared'] = $this->addressStore->countTmpAddresses(); $stdoutarray['temporary address objects']['total VSYSs'] = $gnTmpAddresses; $stdoutarray['region objects'] = array(); diff --git a/lib/device-and-system-classes/Sub.php b/lib/device-and-system-classes/Sub.php index 4456e680..f5e7ca65 100644 --- a/lib/device-and-system-classes/Sub.php +++ b/lib/device-and-system-classes/Sub.php @@ -47,10 +47,7 @@ function load_defaultSecurityRule( ) $finalroot = DH::findFirstElement('rules', $tmproot); if( $finalroot !== FALSE ) { - if( !DH::hasChild($finalroot) ) - $finalroot = $this->createDefaultSecurityRule( ); - else - $finalroot = $this->createPartialDefaultSecurityRule( $finalroot ); + $finalroot = $this->createPartialDefaultSecurityRule( $finalroot ); } } diff --git a/lib/misc-classes/DH.php b/lib/misc-classes/DH.php index 72921728..8d85a10a 100644 --- a/lib/misc-classes/DH.php +++ b/lib/misc-classes/DH.php @@ -519,7 +519,7 @@ static public function elementToPanXPath($element) /** * @param DOMNode $element */ - static public function elementToPanSetCommand( $type, $element, &$array ) + static public function elementToPanSetCommand( $type, $element, $xpath, &$array, $multiVSYS, $debug = false ) { if( $type !== "set" && $type !== "delete" ) return; @@ -528,7 +528,11 @@ static public function elementToPanSetCommand( $type, $element, &$array ) $element = DH::firstChildElement($element); //get xPATH - $orig_fullxpath = DH::elementToPanXPath($element); + #$orig_fullxpath = DH::elementToPanXPath($element); + $orig_fullxpath = $xpath; + + if( $debug ) + PH::print_stdout( "orig_fullpath|".$orig_fullxpath."|"); $fullpath = $orig_fullxpath; $replace = "/config"; @@ -536,15 +540,21 @@ static public function elementToPanSetCommand( $type, $element, &$array ) $replace = "/devices/entry[@name='localhost.localdomain']"; $fullpath = str_replace($replace, "", $fullpath); - //bug related to multi-vsys - $replace = "/vsys/entry[@name='vsys1']"; - $fullpath = str_replace($replace, "", $fullpath); + //Todo: 20230907 - if FW - no multivsys - remove it + if( !$multiVSYS ) + { + $replace = "/vsys/entry[@name='vsys1']"; + $fullpath = str_replace($replace, "", $fullpath); + } + $fullpath = str_replace("/", " ", $fullpath); $fullpath = str_replace("entry[@name='", '"', $fullpath); $fullpath = str_replace("']", '"', $fullpath); $xpath = $type . $fullpath; + if( $debug ) + PH::print_stdout( "|".$fullpath."|"); if( strpos( $xpath, " member" ) !== FALSE ) { @@ -561,7 +571,7 @@ static public function elementToPanSetCommand( $type, $element, &$array ) if( $element->nodeType == XML_ELEMENT_NODE ) //1 { $string = ""; - self::CHILDelementToPanSetCommand( $type, $element, $array, $xpath, $string); + self::CHILDelementToPanSetCommand( $type, $element, $array, $xpath, $string, $debug); } else derr('unsupported node type=' . $element->nodeType); @@ -570,7 +580,7 @@ static public function elementToPanSetCommand( $type, $element, &$array ) /** * @param DOMNode $element */ - static public function CHILDelementToPanSetCommand( $type, $element, &$array, $xpath, $string ) + static public function CHILDelementToPanSetCommand( $type, $element, &$array, $xpath, $string, $debug = false ) { #print "---------------\n"; #print "nodename: ".$element->nodeName."\n"; @@ -589,7 +599,7 @@ static public function CHILDelementToPanSetCommand( $type, $element, &$array, $x { $finalstring = $xpath.$string; - self::setCommandvalidation( $finalstring, $array); + self::setCommandvalidation( $finalstring, $array, $debug); return; } @@ -641,7 +651,7 @@ static public function CHILDelementToPanSetCommand( $type, $element, &$array, $x #print "1-2\n"; $finalstring = $xpath.$string; - self::setCommandvalidation( $finalstring, $array); + self::setCommandvalidation( $finalstring, $array, $debug); return; } @@ -654,14 +664,14 @@ static public function CHILDelementToPanSetCommand( $type, $element, &$array, $x { #print "xpath: ".$xpath."\n"; #print "string: ".$string."\n"; - self::CHILDelementToPanSetCommand( $type, $childElement, $array, $xpath, $string ); + self::CHILDelementToPanSetCommand( $type, $childElement, $array, $xpath, $string, $debug ); } if( $element->hasChildNodes() === FALSE ) { $finalstring = $xpath.$string; - self::setCommandvalidation( $finalstring, $array); + self::setCommandvalidation( $finalstring, $array, $debug); } } else @@ -680,7 +690,7 @@ static public function CHILDelementToPanSetCommand( $type, $element, &$array, $x #print "final: ".$finalstring."\n"; - self::setCommandvalidation( $finalstring, $array); + self::setCommandvalidation( $finalstring, $array, $debug); } } } @@ -689,7 +699,7 @@ static public function CHILDelementToPanSetCommand( $type, $element, &$array, $x * @param string $finalstring * @param array $array **/ - static public function setCommandvalidation( $finalstring, &$array ) + static public function setCommandvalidation( $finalstring, &$array, $debug = false ) { if( strpos($finalstring, "set ") !== FALSE && strpos($finalstring, " profiles zone-protection-profile ") !== FALSE @@ -718,7 +728,12 @@ static public function setCommandvalidation( $finalstring, &$array ) if( !empty( $finalstring ) ) + { + if( $debug ) + PH::print_stdout($finalstring); $array[] = $finalstring; + } + } /** diff --git a/lib/misc-classes/PH.php b/lib/misc-classes/PH.php index bc9b46f0..fd32cf7e 100644 --- a/lib/misc-classes/PH.php +++ b/lib/misc-classes/PH.php @@ -182,7 +182,7 @@ function __construct($argv, $argc) private static $library_version_major = 2; private static $library_version_sub = 1; - private static $library_version_bugfix = 15; + private static $library_version_bugfix = 16; //BASIC AUTH PAN-OS 7.1 public static $softwareupdate_key = "658d787f293e631196dac9fb29490f1cc1bb3827"; diff --git a/lib/misc-classes/RQueryContext.php b/lib/misc-classes/RQueryContext.php index a5993e32..49433d03 100644 --- a/lib/misc-classes/RQueryContext.php +++ b/lib/misc-classes/RQueryContext.php @@ -16,6 +16,8 @@ class RQueryContext public $nestedQueries; public $cachedSubRQuery; + public $cachedList; + function __construct(RQuery $r, $value = null, $nestedQueries = null) { $this->rQueryObject = $r; diff --git a/lib/misc-classes/filters/filters-Address.php b/lib/misc-classes/filters/filters-Address.php index d43d7849..8543daad 100644 --- a/lib/misc-classes/filters/filters-Address.php +++ b/lib/misc-classes/filters/filters-Address.php @@ -479,6 +479,42 @@ }, 'arg' => TRUE ); +RQuery::$defaultFilters['address']['name']['operators']['same.as.region.predefined'] = array( + 'Function' => function (AddressRQueryContext $context) { + $object = $context->object; + + if( !isset($context->cachedList) ) + { + $list = array(); + $filename = dirname(__FILE__) . '/../../object-classes/predefined.xml'; + + $xmlDoc_region = new DOMDocument(); + $xmlDoc_region->load($filename, XML_PARSE_BIG_LINES); + + $cursor = DH::findXPathSingleEntryOrDie('/predefined/region', $xmlDoc_region); + foreach( $cursor->childNodes as $region_entry ) + { + if( $region_entry->nodeType != XML_ELEMENT_NODE ) + continue; + + $region_name = DH::findAttribute('name', $region_entry); + #PH::print_stdout( $region_name ); + $list[$region_name] = TRUE; + } + + $context->cachedList = &$list; + } + else + $list = &$context->cachedList; + + return isset($list[$object->name()]); + }, + 'arg' => FALSE, + 'ci' => array( + 'fString' => '(%PROP% new test 1)', + 'input' => 'input/panorama-8.0.xml' + ) +); RQuery::$defaultFilters['address']['netmask']['operators']['>,<,=,!'] = array( 'eval' => '!$object->isGroup() && !$object->isRegion() && $object->isType_ipNetmask() && $object->getNetworkMask() !operator! !value!', 'arg' => TRUE, @@ -549,6 +585,19 @@ 'input' => 'input/panorama-8.0.xml' ) ); +RQuery::$defaultFilters['address']['tag']['operators']['is.set'] = array( + 'Function' => function (AddressRQueryContext $context) { + if( $context->object->isRegion() ) + return FALSE; + return count($context->object->tags->getAll()) > 0; + }, + 'arg' => FALSE, + 'argObjectFinder' => "\$objectFind=null;\n\$objectFind=\$object->tags->parentCentralStore->find('!value!');", + 'ci' => array( + 'fString' => '(%PROP% grp.shared-group1)', + 'input' => 'input/panorama-8.0.xml' + ) +); RQuery::$defaultFilters['address']['location']['operators']['is'] = array( 'Function' => function (AddressRQueryContext $context) { $owner = $context->object->owner->owner; diff --git a/lib/misc-classes/filters/filters-Rule.php b/lib/misc-classes/filters/filters-Rule.php index eacf1cef..193a3ac8 100644 --- a/lib/misc-classes/filters/filters-Rule.php +++ b/lib/misc-classes/filters/filters-Rule.php @@ -1276,7 +1276,7 @@ RQuery::$defaultFilters['rule']['group-tag']['operators']['is'] = array( 'eval' => function ($object, &$nestedQueries, $value) { /** @var Rule|SecurityRule|NatRule|DecryptionRule|AppOverrideRule|CaptivePortalRule|AuthenticationRule|PbfRule|QoSRule|DoSRule $object */ - return $object->grouptagIs( $value ) === TRUE; + return $object->grouptag->hasTag( $value ) === TRUE; }, 'arg' => TRUE, 'argObjectFinder' => "\$objectFind=null;\n\$objectFind=\$object->tags->parentCentralStore->find('!value!');", @@ -1292,12 +1292,8 @@ if( !$rule->isSecurityRule() && !$rule->isDoSRule() && !$rule->isPbfRule() && !$rule->isQoSRule() ) return FALSE; - $grouptag = $rule->groupTag(); - - if( is_object( $grouptag ) ) - { + if( count($rule->grouptag->getAll() ) > 0 ) return TRUE; - } return FALSE; }, @@ -1314,17 +1310,20 @@ if( !$rule->isSecurityRule() && !$rule->isDoSRule() && !$rule->isPbfRule() && !$rule->isQoSRule() ) return FALSE; - $grouptag = $rule->groupTag(); - - if( is_object( $grouptag ) ) + $grouptags = $rule->grouptag->getAll(); + foreach($grouptags as $grouptag) { - $matching = preg_match($context->value, $grouptag->name()); - if( $matching === FALSE ) - derr("regular expression error on '{$context->value}'"); - if( $matching === 1 ) - return TRUE; + if( is_object( $grouptag ) ) + { + $matching = preg_match($context->value, $grouptag->name()); + if( $matching === FALSE ) + derr("regular expression error on '{$context->value}'"); + if( $matching === 1 ) + return TRUE; + } } + return FALSE; }, 'arg' => TRUE, diff --git a/lib/misc-classes/trait/ObjectWithDescription.php b/lib/misc-classes/trait/ObjectWithDescription.php index 6880715d..fb4fe290 100644 --- a/lib/misc-classes/trait/ObjectWithDescription.php +++ b/lib/misc-classes/trait/ObjectWithDescription.php @@ -113,6 +113,12 @@ public function description_merge( $other ) $description = $this->description(); $other_description = $other->description(); + $description = iconv('UTF-8', 'ISO-8859-1//TRANSLIT//IGNORE', $description); + $other_description = iconv('UTF-8', 'ISO-8859-1//TRANSLIT//IGNORE', $other_description); + + #$description = mb_convert_encoding($description, 'UTF-8', 'ISO-8859-1'); + #$other_description = mb_convert_encoding($other_description, 'UTF-8', 'ISO-8859-1'); + if ( (empty($description) && empty($other_description)) || ( !empty($description) && !empty($other_description) && strpos($description, $other_description) !== false )) { return; } diff --git a/lib/object-classes/Address.php b/lib/object-classes/Address.php index bf12ba71..909ab6a8 100644 --- a/lib/object-classes/Address.php +++ b/lib/object-classes/Address.php @@ -60,7 +60,7 @@ class Address public $_ip4Map = null; public $ancestor; - + public $childancestor; /** * you should not need this one for normal use @@ -678,9 +678,15 @@ public function merge_tag_description_to( $pickedObject, $apiMode = false ) /** @var Tag $tag*/ if( !$pickedObject->tags->hasTag( $tag ) ) { + $upperLevelTag = null; + if( isset($pickedObject->owner->owner->tagStore->parentCentralStore) ) + $upperLevelTag = $pickedObject->owner->owner->tagStore->parentCentralStore->find( $tag->name() ); + + $newTag = $pickedObject->owner->owner->tagStore->find( $tag->name() ); if( $newTag === null ) { + PH::print_stdout( " - tag not found - create it in: ".$pickedObject->owner->owner->tagStore->_PANC_shortName() ); $newTag = $pickedObject->owner->owner->tagStore->createTag( $tag->name() ); $newTag->setColor( $tag->getColor() ); $newTag->addComments( $tag->getComments() ); @@ -688,6 +694,8 @@ public function merge_tag_description_to( $pickedObject, $apiMode = false ) if( $apiMode ) $newTag->API_sync(); } + else + PH::print_stdout( " - tag found in: ".$newTag->owner->_PANC_shortName() ); if( $apiMode ) { @@ -695,17 +703,42 @@ public function merge_tag_description_to( $pickedObject, $apiMode = false ) if( $tag !== $newTag) { $tag->replaceMeGlobally($newTag); - $tag->owner->API_removeTag($tag); + + if( get_class($tag->owner->owner) !== "PanoramaConf" ) + { + $tagDG_childDGS = $tag->owner->owner->childDeviceGroups(TRUE); + if( !in_array($newTag->owner->owner->name(), $tagDG_childDGS) ) + $tag->owner->API_removeTag($tag); + } } } else { + PH::print_stdout( " - add tag to picked object: ".$pickedObject->name() ); $pickedObject->tags->addTag( $newTag ); if( $tag !== $newTag) { $tag->replaceMeGlobally($newTag); if( $tag->owner !== null ) - $tag->owner->removeTag($tag); + { + /* + if( $upperLevelTag === null ) + { + PH::print_stdout( " - delete old tag from: ".$tag->owner->_PANC_shortName() ); + $tag->owner->removeTag($tag); + }*/ + if( get_class($tag->owner->owner) !== "PanoramaConf" ) + { + $tagDG_childDGS = $tag->owner->owner->childDeviceGroups(true); + if( !in_array( $newTag->owner->owner->name(), $tagDG_childDGS ) ) + { + //do not delete TAG if TAG is from upperlevel DG and newtag is from childDG + PH::print_stdout( " - delete old tag from: ".$tag->owner->_PANC_shortName() ); + $tag->owner->removeTag($tag); + } + } + + } } } } diff --git a/lib/object-classes/TagStore.php b/lib/object-classes/TagStore.php index dc1640c0..b4429478 100644 --- a/lib/object-classes/TagStore.php +++ b/lib/object-classes/TagStore.php @@ -138,8 +138,6 @@ public function tags() function createTag($name, $ref = null) { - TAG::replaceNamewith( $name ); - if( $this->find($name, null, FALSE) !== null ) derr('Tag named "' . $name . '" already exists, cannot create'); diff --git a/lib/pan_php_framework.php b/lib/pan_php_framework.php index 8dbe2cca..da8b2922 100644 --- a/lib/pan_php_framework.php +++ b/lib/pan_php_framework.php @@ -199,6 +199,7 @@ function my_shutdown() require_once $basedir . '/container-classes/ObjRuleContainer.php'; require_once $basedir . '/container-classes/ZoneRuleContainer.php'; require_once $basedir . '/container-classes/TagRuleContainer.php'; +require_once $basedir . '/container-classes/GroupTagRuleContainer.php'; require_once $basedir . '/container-classes/AppRuleContainer.php'; require_once $basedir . '/container-classes/AddressRuleContainer.php'; require_once $basedir . '/container-classes/ServiceRuleContainer.php'; diff --git a/lib/rule-classes/AppOverrideRule.php b/lib/rule-classes/AppOverrideRule.php index 389db555..147e2230 100644 --- a/lib/rule-classes/AppOverrideRule.php +++ b/lib/rule-classes/AppOverrideRule.php @@ -45,6 +45,7 @@ public function __construct($owner, $fromTemplateXML = FALSE) $this->parentServiceStore = $this->owner->owner->serviceStore; $this->tags = new TagRuleContainer($this); + $this->grouptag = new TagRuleContainer($this); $this->from = new ZoneRuleContainer($this); $this->from->name = 'from'; diff --git a/lib/rule-classes/AuthenticationRule.php b/lib/rule-classes/AuthenticationRule.php index d1b56be2..a9e52e54 100644 --- a/lib/rule-classes/AuthenticationRule.php +++ b/lib/rule-classes/AuthenticationRule.php @@ -53,6 +53,7 @@ public function __construct($owner, $fromTemplateXML = FALSE) $this->parentServiceStore = $this->owner->owner->serviceStore; $this->tags = new TagRuleContainer($this); + $this->grouptag = new TagRuleContainer($this); $this->from = new ZoneRuleContainer($this); $this->from->name = 'from'; diff --git a/lib/rule-classes/CaptivePortalRule.php b/lib/rule-classes/CaptivePortalRule.php index 844ad0b2..594bfe0c 100644 --- a/lib/rule-classes/CaptivePortalRule.php +++ b/lib/rule-classes/CaptivePortalRule.php @@ -52,6 +52,7 @@ public function __construct($owner, $fromTemplateXML = FALSE) $this->parentServiceStore = $this->owner->owner->serviceStore; $this->tags = new TagRuleContainer($this); + $this->grouptag = new TagRuleContainer($this); $this->from = new ZoneRuleContainer($this); $this->from->name = 'from'; diff --git a/lib/rule-classes/DecryptionRule.php b/lib/rule-classes/DecryptionRule.php index 8430f546..c6d3fa30 100644 --- a/lib/rule-classes/DecryptionRule.php +++ b/lib/rule-classes/DecryptionRule.php @@ -49,6 +49,7 @@ public function __construct($owner, $fromTemplateXML = FALSE) $this->parentServiceStore = $this->owner->owner->serviceStore; $this->tags = new TagRuleContainer($this); + $this->grouptag = new TagRuleContainer($this); $this->from = new ZoneRuleContainer($this); $this->from->name = 'from'; diff --git a/lib/rule-classes/DefaultSecurityRule.php b/lib/rule-classes/DefaultSecurityRule.php index 1115eb61..594c3c72 100644 --- a/lib/rule-classes/DefaultSecurityRule.php +++ b/lib/rule-classes/DefaultSecurityRule.php @@ -82,6 +82,7 @@ public function __construct($owner, $fromTemplateXML = FALSE) $this->parentServiceStore = $this->owner->owner->serviceStore; $this->tags = new TagRuleContainer($this); + $this->grouptag = new TagRuleContainer($this); $this->from = new ZoneRuleContainer($this); $this->from->name = 'from'; diff --git a/lib/rule-classes/DoSRule.php b/lib/rule-classes/DoSRule.php index 01594207..822fa299 100644 --- a/lib/rule-classes/DoSRule.php +++ b/lib/rule-classes/DoSRule.php @@ -141,6 +141,7 @@ public function __construct($owner, $fromTemplateXML = FALSE) $this->parentServiceStore = $this->owner->owner->serviceStore; $this->tags = new TagRuleContainer($this); + $this->grouptag = new TagRuleContainer($this); $this->source = new AddressRuleContainer($this); $this->source->name = 'source'; diff --git a/lib/rule-classes/NatRule.php b/lib/rule-classes/NatRule.php index 314c3459..85f0cdcb 100644 --- a/lib/rule-classes/NatRule.php +++ b/lib/rule-classes/NatRule.php @@ -86,6 +86,7 @@ public function __construct($owner, $fromTemplateXML = FALSE) $this->parentServiceStore = $this->owner->owner->serviceStore; $this->tags = new TagRuleContainer($this); + $this->grouptag = new TagRuleContainer($this); $this->from = new ZoneRuleContainer($this); $this->from->name = 'from'; diff --git a/lib/rule-classes/NetworkPacketBrokerRule.php b/lib/rule-classes/NetworkPacketBrokerRule.php index e5e18f32..05a35850 100644 --- a/lib/rule-classes/NetworkPacketBrokerRule.php +++ b/lib/rule-classes/NetworkPacketBrokerRule.php @@ -43,6 +43,7 @@ public function __construct($owner, $fromTemplateXML = FALSE) $this->parentServiceStore = $this->owner->owner->serviceStore; $this->tags = new TagRuleContainer($this); + $this->grouptag = new TagRuleContainer($this); $this->from = new ZoneRuleContainer($this); $this->from->name = 'from'; diff --git a/lib/rule-classes/PbfRule.php b/lib/rule-classes/PbfRule.php index 728fc632..fa600979 100644 --- a/lib/rule-classes/PbfRule.php +++ b/lib/rule-classes/PbfRule.php @@ -66,6 +66,7 @@ public function __construct($owner, $fromTemplateXML = FALSE) $this->parentServiceStore = $this->owner->owner->serviceStore; $this->tags = new TagRuleContainer($this); + $this->grouptag = new TagRuleContainer($this); $this->source = new AddressRuleContainer($this); $this->source->name = 'source'; diff --git a/lib/rule-classes/QoSRule.php b/lib/rule-classes/QoSRule.php index 5be27a76..5e9dc6d4 100644 --- a/lib/rule-classes/QoSRule.php +++ b/lib/rule-classes/QoSRule.php @@ -71,6 +71,7 @@ public function __construct($owner, $fromTemplateXML = FALSE) $this->parentServiceStore = $this->owner->owner->serviceStore; $this->tags = new TagRuleContainer($this); + $this->grouptag = new TagRuleContainer($this); $this->from = new ZoneRuleContainer($this); $this->from->name = 'from'; diff --git a/lib/rule-classes/Rule.php b/lib/rule-classes/Rule.php index 3f06864a..de5c3e96 100644 --- a/lib/rule-classes/Rule.php +++ b/lib/rule-classes/Rule.php @@ -54,8 +54,8 @@ class Rule */ public $tags; - /** @var Tag */ - #public $grouptag = null; + /** @var GroupTagRuleContainer */ + public $grouptag; /** * @var ServiceRuleContainer @@ -194,8 +194,13 @@ protected function load_common_from_domxml() } else if( $node->nodeName == 'group-tag' ) { + $this->grouptag->load_from_domxml($node); + /* + $this->grouptag->xmlroot = $node; $grouptagName = $node->textContent; - $this->grouptag = $this->owner->owner->tagStore->find( $grouptagName, $this->grouptag); + $tmpTag = $this->owner->owner->tagStore->find( $grouptagName, $this->grouptag); + $this->grouptag->addTag($tmpTag); + */ } else if( $node->nodeName == 'description' ) { diff --git a/lib/rule-classes/SDWanRule.php b/lib/rule-classes/SDWanRule.php index 2ff970c2..647cadd1 100644 --- a/lib/rule-classes/SDWanRule.php +++ b/lib/rule-classes/SDWanRule.php @@ -43,6 +43,7 @@ public function __construct($owner, $fromTemplateXML = FALSE) $this->parentServiceStore = $this->owner->owner->serviceStore; $this->tags = new TagRuleContainer($this); + $this->grouptag = new TagRuleContainer($this); $this->from = new ZoneRuleContainer($this); $this->from->name = 'from'; diff --git a/lib/rule-classes/SecurityRule.php b/lib/rule-classes/SecurityRule.php index bb05ef64..c8087949 100644 --- a/lib/rule-classes/SecurityRule.php +++ b/lib/rule-classes/SecurityRule.php @@ -115,6 +115,7 @@ public function __construct($owner, $fromTemplateXML = FALSE) $this->parentServiceStore = $this->owner->owner->serviceStore; $this->tags = new TagRuleContainer($this); + $this->grouptag = new GroupTagRuleContainer($this); $this->from = new ZoneRuleContainer($this); $this->from->name = 'from'; @@ -1150,11 +1151,9 @@ public function display($padding = 0) foreach( $this->tags->getAll() as $tag ) PH::$JSON_TMP['sub']['object'][$this->name()]['tag'][] = $tag->name(); - if( $this->grouptag !== null ) - { - PH::print_stdout( $padding . " GroupTag: " . $this->grouptag->name() ); - PH::$JSON_TMP['sub']['object'][$this->name()]['group-tag'] = $this->grouptag->name(); - } + PH::print_stdout( $padding . " Group-Tag: " . $this->grouptag->toString_inline() ); + foreach( $this->grouptag->getAll() as $tag ) + PH::$JSON_TMP['sub']['object'][$this->name()]['group-tag'] = $tag->name(); if( $this->_targets !== null ) { @@ -1668,6 +1667,7 @@ public function cleanForDestruction() $this->source->__destruct(); $this->destination->__destruct(); $this->tags->__destruct(); + $this->grouptag->__destruct(); $this->apps->__destruct(); $this->services->__destruct(); diff --git a/lib/rule-classes/TunnelInspectionRule.php b/lib/rule-classes/TunnelInspectionRule.php index 6434fcda..47d79dd2 100644 --- a/lib/rule-classes/TunnelInspectionRule.php +++ b/lib/rule-classes/TunnelInspectionRule.php @@ -43,6 +43,7 @@ public function __construct($owner, $fromTemplateXML = FALSE) $this->parentServiceStore = $this->owner->owner->serviceStore; $this->tags = new TagRuleContainer($this); + $this->grouptag = new TagRuleContainer($this); $this->from = new ZoneRuleContainer($this); $this->from->name = 'from'; diff --git a/utils/common/actions-address.php b/utils/common/actions-address.php index 0a068470..1b80e8a5 100644 --- a/utils/common/actions-address.php +++ b/utils/common/actions-address.php @@ -1451,10 +1451,6 @@ if( $targetLocation == 'shared' ) { - $findSubSystem = $rootObject->findSubSystemByName($targetLocation); - if( $findSubSystem === null ) - derr("cannot find VSYS/DG named '$targetLocation'"); - $targetStore = $rootObject->addressStore; } else @@ -1562,62 +1558,66 @@ } } - //validation if upper/lower level is not changed - $tmplocalSub = $rootObject->findSubSystemByName($localLocation); - if( $tmplocalSub->isPanorama() ) + if( !$context->subSystem->isFirewall() && !$context->subSystem->isVirtualSystem() ) { - /** @var PanoramaConf $tmplocalSub */ - $tmpChildSubs = $tmplocalSub->deviceGroups; - } - else - $tmpChildSubs = $tmplocalSub->childDeviceGroups(); - $lowerLevelMove = false; - foreach( $tmpChildSubs as $childDG ) - { - if( $targetLocation == $childDG->name() ) - $lowerLevelMove = true; - } - if( !$lowerLevelMove ) - { - $startLocation = $tmplocalSub; - $endLocation = $findSubSystem; - } - else - { - $endLocation = $tmplocalSub; - $startLocation = $findSubSystem; - } - $skipped = FALSE; - do - { - if( !isset($startLocation->parentDeviceGroup->addressStore) ) - break; + //validation if upper/lower level is not changed + $tmplocalSub = $rootObject->findSubSystemByName($localLocation); + if( $tmplocalSub->isPanorama() ) + { + /** @var PanoramaConf $tmplocalSub */ + $tmpChildSubs = $tmplocalSub->deviceGroups; + } + else + $tmpChildSubs = $tmplocalSub->childDeviceGroups(); - $tmpObject = $startLocation->parentDeviceGroup->addressStore->find($object->name(), null, FALSE); - if( $tmpObject != null ) + $lowerLevelMove = FALSE; + foreach( $tmpChildSubs as $childDG ) { - if( ($object->isGroup() and !$tmpObject->isGroup()) || (!$object->isGroup() and $tmpObject->isGroup()) ) - $skipped = TRUE; - elseif( $object->type() != $tmpObject->type() ) - $skipped = TRUE; - elseif( $object->value() != $tmpObject->value() ) - $skipped = TRUE; + if( $targetLocation == $childDG->name() ) + $lowerLevelMove = TRUE; } - if( !$skipped ) - $startLocation = $startLocation->parentDeviceGroup; + if( !$lowerLevelMove ) + { + $startLocation = $tmplocalSub; + $endLocation = $findSubSystem; + } else { - if( !$lowerLevelMove ) - $string = "moving to upper level DG is not possible because of object available at lower DG level with same name but different object type or value"; - else - $string = "moving to lower level DG is not possible because of object available at upper DG level with same name but different object type or value"; - PH::ACTIONstatus($context, "SKIPPED", $string); - return; + $endLocation = $tmplocalSub; + $startLocation = $findSubSystem; } - } while( $startLocation != $endLocation ); + $skipped = FALSE; + do + { + if( !isset($startLocation->parentDeviceGroup->addressStore) ) + break; + $tmpObject = $startLocation->parentDeviceGroup->addressStore->find($object->name(), null, FALSE); + if( $tmpObject != null ) + { + if( ($object->isGroup() and $tmpObject->isGroup()) || ($object->isGroup() and !$tmpObject->isGroup()) || (!$object->isGroup() and $tmpObject->isGroup()) ) + $skipped = TRUE; + elseif( $object->type() != $tmpObject->type() ) + $skipped = TRUE; + elseif( $object->value() != $tmpObject->value() ) + $skipped = TRUE; + } + + if( !$skipped ) + $startLocation = $startLocation->parentDeviceGroup; + else + { + if( !$lowerLevelMove ) + $string = "moving to upper level DG is not possible because of object available at lower DG level with same name but different object type or value"; + else + $string = "moving to lower level DG is not possible because of object available at upper DG level with same name but different object type or value"; + PH::ACTIONstatus($context, "SKIPPED", $string); + return; + } + } while( $startLocation != $endLocation ); + } /////////////////////////////// $string = "moved, no conflict"; diff --git a/utils/common/actions-service.php b/utils/common/actions-service.php index 71a50049..75d6d0e5 100644 --- a/utils/common/actions-service.php +++ b/utils/common/actions-service.php @@ -573,10 +573,6 @@ if( $targetLocation == 'shared' ) { - $findSubSystem = $rootObject->findSubSystemByName($targetLocation); - if( $findSubSystem === null ) - derr("cannot find VSYS/DG named '$targetLocation'"); - $targetStore = $rootObject->serviceStore; } else @@ -661,62 +657,65 @@ } } - //validation if upper/lower level is not changed - $tmplocalSub = $rootObject->findSubSystemByName($localLocation); - if( $tmplocalSub->isPanorama() ) - { - /** @var PanoramaConf $tmplocalSub */ - $tmpChildSubs = $tmplocalSub->deviceGroups; - } - else - $tmpChildSubs = $tmplocalSub->childDeviceGroups(); - $lowerLevelMove = false; - foreach( $tmpChildSubs as $childDG ) - { - if( $targetLocation == $childDG->name() ) - $lowerLevelMove = true; - } - - if( !$lowerLevelMove ) - { - $startLocation = $tmplocalSub; - $endLocation = $findSubSystem; - } - else - { - $endLocation = $tmplocalSub; - $startLocation = $findSubSystem; - } - $skipped = FALSE; - do + if( !$context->subSystem->isFirewall() && !$context->subSystem->isVirtualSystem() ) { - if( !isset($startLocation->parentDeviceGroup->serviceStore) ) - break; + //validation if upper/lower level is not changed + $tmplocalSub = $rootObject->findSubSystemByName($localLocation); + if( $tmplocalSub->isPanorama() ) + { + /** @var PanoramaConf $tmplocalSub */ + $tmpChildSubs = $tmplocalSub->deviceGroups; + } + else + $tmpChildSubs = $tmplocalSub->childDeviceGroups(); - $tmpObject = $startLocation->parentDeviceGroup->serviceStore->find($object->name(), null, FALSE); - if( $tmpObject != null ) + $lowerLevelMove = FALSE; + foreach( $tmpChildSubs as $childDG ) { - if( ($object->isGroup() and !$tmpObject->isGroup()) || (!$object->isGroup() and $tmpObject->isGroup()) ) - $skipped = TRUE; - elseif( $object->protocol() != $tmpObject->protocol() ) - $skipped = TRUE; - elseif( $object->getDestPort() != $tmpObject->getDestPort() || $object->getSourcePort() != $tmpObject->getSourcePort() ) - $skipped = TRUE; + if( $targetLocation == $childDG->name() ) + $lowerLevelMove = TRUE; } - if( !$skipped ) - $startLocation = $startLocation->parentDeviceGroup; + if( !$lowerLevelMove ) + { + $startLocation = $tmplocalSub; + $endLocation = $findSubSystem; + } else { - if( !$lowerLevelMove ) - $string = "moving to upper level DG is not possible because of object available at lower DG level with same name but different object type or value"; - else - $string = "moving to lower level DG is not possible because of object available at upper DG level with same name but different object type or value"; - PH::ACTIONstatus($context, "SKIPPED", $string); - return; + $endLocation = $tmplocalSub; + $startLocation = $findSubSystem; } - } while( $startLocation != $endLocation ); + $skipped = FALSE; + do + { + if( !isset($startLocation->parentDeviceGroup->serviceStore) ) + break; + + $tmpObject = $startLocation->parentDeviceGroup->serviceStore->find($object->name(), null, FALSE); + if( $tmpObject != null ) + { + if( ($object->isGroup() and $tmpObject->isGroup()) || ($object->isGroup() and !$tmpObject->isGroup()) || (!$object->isGroup() and $tmpObject->isGroup()) ) + $skipped = TRUE; + elseif( $object->protocol() != $tmpObject->protocol() ) + $skipped = TRUE; + elseif( $object->getDestPort() != $tmpObject->getDestPort() || $object->getSourcePort() != $tmpObject->getSourcePort() ) + $skipped = TRUE; + } + if( !$skipped ) + $startLocation = $startLocation->parentDeviceGroup; + else + { + if( !$lowerLevelMove ) + $string = "moving to upper level DG is not possible because of object available at lower DG level with same name but different object type or value"; + else + $string = "moving to lower level DG is not possible because of object available at upper DG level with same name but different object type or value"; + PH::ACTIONstatus($context, "SKIPPED", $string); + return; + } + } while( $startLocation != $endLocation ); + } /////////////////////////////// diff --git a/utils/common/actions-tag.php b/utils/common/actions-tag.php index dbab38ba..5e5febf4 100644 --- a/utils/common/actions-tag.php +++ b/utils/common/actions-tag.php @@ -362,7 +362,7 @@ 'MainFunction' => function (TagCallContext $context) { $object = $context->object; $tmpName = $object->name(); - TAG::replaceNamewith( $tmpName ); + TAG::revertreplaceNamewith( $tmpName ); PH::print_stdout( " * " . get_class($object) . " '{$tmpName}' color: '{$object->getColor()}' comments: '{$object->getComments()}'" ); diff --git a/utils/develop/ui/ui_function.js b/utils/develop/ui/ui_function.js index eaafb908..a55ceb62 100644 --- a/utils/develop/ui/ui_function.js +++ b/utils/develop/ui/ui_function.js @@ -84,7 +84,7 @@ function addNewRow()
  • shadow-json -
  • location diff --git a/utils/lib/DIFF.php b/utils/lib/DIFF.php index 7fb34f25..d2099db5 100644 --- a/utils/lib/DIFF.php +++ b/utils/lib/DIFF.php @@ -1031,6 +1031,13 @@ public function displayDIFF( $xpath, $text, $plus, $minus, $edit = array() ) { if( $this->outputFormatSet ) { + $multiVSYS = FALSE; + if( $this->configType == 'panos' ) + { + if( count($this->pan->getVirtualSystems()) > 1 ) + $multiVSYS = TRUE; + } + if( $this->debugAPI ) { //intermediate, remove it later on @@ -1081,6 +1088,7 @@ public function displayDIFF( $xpath, $text, $plus, $minus, $edit = array() ) if( $this->debugAPI ) { + PH::print_stdout("\nXPATH: $xpath"); PH::print_stdout( "ADD"); //intermediate, remove it later on @@ -1092,7 +1100,7 @@ public function displayDIFF( $xpath, $text, $plus, $minus, $edit = array() ) } - DH::elementToPanSetCommand( 'set', $element, $array ); + DH::elementToPanSetCommand( 'set', $element, $xpath,$array, $multiVSYS, $this->debugAPI ); //manipulation needed based on flood xyz red issue in PAN-OS self::fixFloodSetCommand($array); @@ -1114,6 +1122,7 @@ public function displayDIFF( $xpath, $text, $plus, $minus, $edit = array() ) if( $this->debugAPI ) { + PH::print_stdout("\nXPATH: $xpath"); PH::print_stdout( "REMOVE"); //intermediate, remove it later on @@ -1126,7 +1135,7 @@ public function displayDIFF( $xpath, $text, $plus, $minus, $edit = array() ) } - DH::elementToPanSetCommand( 'delete', $element, $array ); + DH::elementToPanSetCommand( 'delete', $element, $xpath,$array, $multiVSYS, $this->debugAPI ); self::arraySetCommand( $array, "diff_delete" ); //Todo: swaschkut 20220728 diff --git a/utils/lib/MERGER.php b/utils/lib/MERGER.php index ad0c1953..ac9454f5 100644 --- a/utils/lib/MERGER.php +++ b/utils/lib/MERGER.php @@ -3446,7 +3446,9 @@ function tag_merging() $tmp_DG_name = 'shared'; /** @var Tag $tmp_tag */ - $tmp_tag = $store->find( $pickedObject->name() ); + $tmpPickedName = $pickedObject->name(); + TAG::revertreplaceNamewith($tmpPickedName); + $tmp_tag = $store->find( $tmpPickedName ); if( $tmp_tag == null ) { if( isset( $child_NamehashMap[ $pickedObject->name() ] ) ) @@ -3470,18 +3472,20 @@ function tag_merging() continue; } } - PH::print_stdout( " * create object in DG: '".$tmp_DG_name."' : '".$pickedObject->name()."'" ); + PH::print_stdout( " * create object in DG: '".$tmp_DG_name."' : '".$tmpPickedName."'" ); if( $this->action === "merge" ) { - $tmp_tag = $store->createTag($pickedObject->name() ); + $tmp_tag = $store->createTag($tmpPickedName ); $tmp_tag->setColor( $pickedObject->getColor() ); /** @var TagStore $store */ if( $this->apiMode ) $tmp_tag->API_sync(); - $value = $tmp_tag->name(); + $tmpPickedName = $tmp_tag->name(); + TAG::replaceNamewith($tmpPickedName); + $value = $tmpPickedName; $hashMap[$value][] = $tmp_tag; } else @@ -4274,7 +4278,9 @@ function object_merging( $objectType ) $tmp_DG_name = 'shared'; /** @var Tag $tmp_tag */ - $tmp_tag = $store->find( $pickedObject->name() ); + $tmpPickedName = $pickedObject->name(); + TAG::revertreplaceNamewith($tmpPickedName); + $tmp_tag = $store->find( $tmpPickedName ); if( $tmp_tag == null ) { if( isset( $child_NamehashMap[ $pickedObject->name() ] ) ) @@ -4297,18 +4303,20 @@ function object_merging( $objectType ) continue; } } - PH::print_stdout( " * create object in DG: '".$tmp_DG_name."' : '".$pickedObject->name()."'" ); + PH::print_stdout( " * create object in DG: '".$tmp_DG_name."' : '".$tmpPickedName."'" ); if( $this->action === "merge" ) { - $tmp_tag = $store->createTag($pickedObject->name() ); + $tmp_tag = $store->createTag($tmpPickedName ); $tmp_tag->setColor( $pickedObject->getColor() ); /** @var TagStore $store */ if( $this->apiMode ) $tmp_tag->API_sync(); - $value = $tmp_tag->name(); + $tmpPickedName = $tmp_tag->name(); + TAG::replaceNamewith($tmpPickedName); + $value = $tmpPickedName; $hashMap[$value][] = $tmp_tag; } else diff --git a/utils/lib/RULEMERGER.php b/utils/lib/RULEMERGER.php index b8d08a2e..f083cdf5 100644 --- a/utils/lib/RULEMERGER.php +++ b/utils/lib/RULEMERGER.php @@ -450,14 +450,14 @@ function UTIL_mergeRules($rule, $ruleToMerge) $ruleToMerge->owner->API_remove($ruleToMerge); $rule->tags->API_addTag( $mergedTag ); - $rule->API_setDescription( $rule->description()." |".$ruleToMerge->name() ); + #$rule->API_setDescription( $rule->description()." |".$ruleToMerge->name() ); } else { $ruleToMerge->owner->remove($ruleToMerge); $rule->tags->addTag( $mergedTag ); - $rule->setDescription( $rule->description()." |".$ruleToMerge->name() ); + #$rule->setDescription( $rule->description()." |".$ruleToMerge->name() ); } $ruleToMerge->alreadyMerged = TRUE; } diff --git a/utils/lib/UTIL.php b/utils/lib/UTIL.php index 4eb99343..4bd85ff2 100644 --- a/utils/lib/UTIL.php +++ b/utils/lib/UTIL.php @@ -1297,12 +1297,28 @@ public function load_config() PH::print_stdout( array( "value" => $this->loadArrayMem[0], "type" => $this->loadArrayMem[1]) , false, "loadmemory"); // -------------------- + $panc_version = $this->pan->appStore->predefinedStore_appid_version; + PH::print_stdout( " - PAN-OS-PHP APP-ID version: ".$panc_version ); + PH::print_stdout( array( $panc_version ), false, "PAN-OS-PHP APP-ID version" ); + + PH::print_stdout(); + if($this->configInput['type'] == 'api') + { + PH::print_stdout( " - PAN-OS APP-ID version: ".$this->configInput['connector']->info_app_version ); + PH::print_stdout( array( $this->configInput['connector']->info_app_version ), false, "PAN-OS APP-ID version" ); + + PH::print_stdout( " - PAN-OS AV version: ".$this->configInput['connector']->info_av_version ); + PH::print_stdout( array( $this->configInput['connector']->info_av_version ), false, "PAN-OS AV version" ); + + PH::print_stdout( " - PAN-OS WF version: ".$this->configInput['connector']->info_wildfire_version ); + PH::print_stdout( array( $this->configInput['connector']->info_wildfire_version ), false, "PAN-OS WF version" ); + + PH::print_stdout( " - PAN-OS THREAT version: ".$this->configInput['connector']->info_threat_version ); + PH::print_stdout( array( $this->configInput['connector']->info_threat_version ), false, "PAN-OS THREAT version" ); + } PH::print_stdout( " - PAN-OS version: {$this->pan->version}" ); PH::print_stdout( array( $this->pan->version ), false, "PAN-OS version" ); - $panc_version = $this->pan->appStore->predefinedStore_appid_version; - PH::print_stdout( " - PAN-OS APP-ID version: ".$panc_version ); - PH::print_stdout( array( $panc_version ), false, "PAN-OS APP-ID version" ); if( isset( $this->pan->timezone ) && $this->pan->timezone !== null ) PH::print_stdout( " - PAN-OS Device timezone: ".$this->pan->timezone ." is used. actual time: ".date('Y/m/d H:i:s') ); diff --git a/utils/lib/XMLISSUE.php b/utils/lib/XMLISSUE.php index eea3f710..99892cab 100644 --- a/utils/lib/XMLISSUE.php +++ b/utils/lib/XMLISSUE.php @@ -111,6 +111,9 @@ public function main() $countDuplicateServiceObjects = 0; $fixedDuplicateServiceObjects = 0; + $countDuplicateTagObjects = 0; + $fixedDuplicateTagObjects = 0; + $countDuplicateSecRuleObjects = 0; $countDuplicateNATRuleObjects = 0; @@ -122,6 +125,9 @@ public function main() $countMissconfiguredSecRuleApplicationObjects=0; $fixedSecRuleApplicationObjects=0; + $countMissconfiguredSecRuleTagObjects=0; + $fixedSecRuleTagObjects=0; + $countMissconfiguredSecRuleSourceObjects=0; $fixedSecRuleSourceObjects=0; $countMissconfiguredSecRuleDestinationObjects=0; @@ -984,6 +990,7 @@ public function main() $secRuleFrom = array(); $secRuleTo = array(); $secRuleCategory = array(); + $secRuleTags = array(); /** @var DOMElement $objectNode */ if( $objectNode->nodeType != XML_ELEMENT_NODE ) @@ -1039,6 +1046,31 @@ public function main() } + $objectNode_tags = DH::findFirstElement('tag', $objectNode); + if( $objectNode_tags !== false ) + { + $demo = iterator_to_array($objectNode_tags->childNodes); + foreach( $demo as $objectTag ) + { + /** @var DOMElement $objectTag */ + if( $objectTag->nodeType != XML_ELEMENT_NODE ) + continue; + + $objectTagName = $objectTag->textContent; + if( isset($secRuleTags[$objectTagName]) ) + { + //Secrule service has twice same service added + $text = " - Secrule: ".$objectName." has same tag defined twice: ".$objectTagName; + $objectNode_tags->removeChild($objectTag); + $text .= PH::boldText(" (removed - no manual fix needed)"); + PH::print_stdout( $text ); + $fixedSecRuleTagObjects++; + } + else + $secRuleTags[$objectTagName] = $objectTag; + } + } + //check if application has 'any' adn additional $objectNode_applications = DH::findFirstElement('application', $objectNode); $demo = iterator_to_array($objectNode_applications->childNodes); @@ -1721,6 +1753,7 @@ public function main() PH::print_stdout( " - FIXED: SecRule with duplicate service members: {$fixedSecRuleServiceObjects}"); PH::print_stdout( " - FIXED: SecRule with duplicate application members: {$fixedSecRuleApplicationObjects}"); PH::print_stdout( " - FIXED: SecRule with duplicate category members: {$fixedSecRuleCategoryObjects}"); + PH::print_stdout( " - FIXED: SecRule with duplicate tag members: {$fixedSecRuleTagObjects}"); PH::print_stdout( "\n - FIXED: ReadOnly duplicate DeviceGroup : {$fixedReadOnlyDeviceGroupobjects}"); PH::print_stdout( "\n - FIXED: ReadOnly duplicate Template : {$fixedReadOnlyTemplateobjects}");