diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..077bfc2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ + +Traversys-Swiss-Army-Knife-TPL.zip diff --git a/README.md b/README.md index 8840dfc..0e67b99 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,9 @@ -# Traversys Swiss-Army-Knife TPL Pattern +# Traversys Swiss-Army-Knife TPL License: GPL-3.0-or-later For use with BMC Discovery (ADDM). -Swiss Army Knife TPL file that features additional discovery commands to enrich Host information. +Swiss Army Knife TPL package that features additional discovery commands and fixes for host enrichment. + +Patterns can be applied separately or in one go, but all must include the GPL license file. diff --git a/traversys_BAIs.tpl b/traversys_BAIs.tpl new file mode 100644 index 0000000..6d2cc69 --- /dev/null +++ b/traversys_BAIs.tpl @@ -0,0 +1,97 @@ +// (C) 2019 Traversys Limited +// Licensed under GPL-3.0-or-later + +tpl 1.15 module makeBAIs; + +metadata + __name :='Generate BAIs'; + origin :='Traversys'; + description:='Generate BAIs by following relationships'; + tree_path :='Traversys', 'Software', 'Generate BAIs'; +end metadata; + +from TSAKLicense import gpl_license 1.0; + +configuration ignore 1.0 + """Ignore rules""" + + "Websites to ignore" websites := [ "_" ]; + +end configuration; + +pattern WebsiteBAIs 1.0 + + """ + Author: Wes Moskal-Fitzpatrick + + Work in progress - use typical relationships to generate some BAIs from Websites. + + Change History: + 2019-05-25 1.0 WMF : Created. + + """ + + overview + tags traversys, bai, website; + end overview; + + constants + type := "Website"; + end constants; + + triggers + on sc:= SoftwareComponent created, confirmed where type matches regex "\bWebsite\b"; + end triggers; + + body + if gpl_license.accept_gpl = false then + stop; + end if; + + if sc.instance in ignore.websites then + log.warn("Ignoring website %sc.instance%..."); + stop; + end if; + + instance := text.lower(sc.instance); + name := "%sc.instance% %type%"; + key := text.hash(instance); + + bai := model.BusinessApplicationInstance( + key := key, + type := type, + name := name, + instance := sc.instance, + _traversys:= true + ); + // ContainedSoftware:SoftwareContainment:SoftwareContainer:BusinessApplicationInstance + model.addContainment(bai, sc); + + containing_sis := search(in sc traverse ContainedSoftware:SoftwareContainment:SoftwareContainer:SoftwareInstance); + model.addContainment(bai, containing_sis); + + outgoing_sis := search(in containing_sis traverse Connecting:ObservedCommunication:Listening:SoftwareInstance); + model.addContainment(bai, outgoing_sis); + // Some of these will be DB servers, but the SIDs can vary so we can add the DB server and try to work it out manually. + databases := search(in outgoing_sis traverse ElementWithDetail:Detail:Detail:Database where lower(instance) = %instance%); + // Dependant:Dependency:DependedUpon:Database + model.rel.Dependency(Dependant := bai, DependedUpon := databases); + + si_dependencies:= search(in containing_sis traverse Dependant:Dependency:DependedUpon:SoftwareInstance); + model.addContainment(bai, si_dependencies); + + si_containers := search(in containing_sis traverse ContainedSoftware:SoftwareContainment:SoftwareContainer:SoftwareInstance); + model.addContainment(bai, si_containers); + + lb_members := search(in containing_sis traverse ServiceProvider:SoftwareService:Service:LoadBalancerMember); + lb_pools := search(in lb_members traverse ContainedMember:Containment:Container:LoadBalancerPool where lower(name) = "%instance%"); + lb_services := search(in lb_pools traverse ContainedPool:Containment:Container:LoadBalancerService); + model.addContainment(bai, lb_services); + + //lb_instances := search(in lb_pools traverse ContainedPool:Containment:Container:LoadBalancerInstance); + //lb_failover := search(in lb_instances traverse ContainedInstance:Containment:Container:LoadBalancerGroup + // traverse Container:Containment:ContainedInstance:LoadBalancerInstance where failover_state = "Standby"); + + end body; + +end pattern; diff --git a/traversys_Win2k8Fix.tpl b/traversys_Win2k8Fix.tpl new file mode 100644 index 0000000..3c94d2a --- /dev/null +++ b/traversys_Win2k8Fix.tpl @@ -0,0 +1,70 @@ +// (C) 2019 Traversys Limited +// Licensed under GPL-3.0-or-later + +tpl 1.15 module Win7_2008Fix; + +metadata + __name :='Windows 7/2008 R2 Fix'; + origin :='Traversys'; + description:='Fixes the problem where Win 7 Desktop identifies as Win 2008 R2 on WMI failure (RemQuery)'; + tree_path :='Traversys', 'Extensions', 'Windows 7/2008 R2 Fix'; +end metadata; + +from TSAKLicense import gpl_license 1.0; + +pattern Win7_2008Fix 1.0 + """ + This pattern fixes Windows Version 6.1.7601 which stands for both Windows 7 and Windows 2008 R2. + If WMI and RemQuery fails - then the OS name string is not returned. + + Change History: + 2018-05-01 1.0 WMF : Created. + + Validation Query: + search Host where os = 'Microsoft Windows [Version 6.1.7601]' + show name, type, os_version, os, age_count, #:::DiscoveryAccess.#:::DeviceInfo.os + + """ + + overview + tags Windows, Traversys; + end overview; + + triggers + on h:= Host created, confirmed where os = "Microsoft Windows [Version 6.1.7601]"; + end triggers; + + body + + if gpl_license.accept_gpl = false then + stop; + end if; + + sysInfo := discovery.runCommand(h, 'systeminfo | findstr /B /C:"OS Name" /C:"OS Version" /C:"OS Manufacturer"'); + regProductName := discovery.registryKey(h, raw "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProductName"); + + reqList := discovery.listRegistry(h, raw "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion"); + regReleaseId := discovery.registryKey(h, raw "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ReleaseId"); + + hOS:= h.os; + + if sysInfo and sysInfo.result then + hOS:= regex.extract(sysInfo.result, regex "OS Name:\s+(.*)", raw "\1"); + h.os_version:= regex.extract(hOS, regex "Microsoft Windows (.*) (Enterprise|Standard)", raw "\1", no_match:= hOS); + h.os_edition:= regex.extract(hOS, regex "Microsoft Windows (.*) (Enterprise|Standard)", raw "\2", no_match:= hOS); + elif regProductName and regProductName.value then + hOS:= regProductName.value; + h.os:= hOS; + h.os_version:= regex.extract(hOS, regex "Windows (.*) (Enterprise|Standard)", raw "\1", no_match:= hOS); + h.os_edition:= regex.extract(hOS, regex "Windows (.*) (Enterprise|Standard)", raw "\2", no_match:= hOS); + end if; + + if hOS matches "Windows 7" then + h.host_type:= "Windows Desktop"; + h.type:= "Windows Desktop"; + h._os_modified:= true; + end if; + + end body; + +end pattern;