Module: Paloalto

Defined in:
lib/paloalto.rb,
lib/paloalto/ngfw.rb,
lib/paloalto/version.rb,
lib/paloalto/nexpose_helper.rb,
lib/paloalto/utilities/nx_logger.rb

Defined Under Namespace

Modules: NexposeHelper, Ngfw Classes: NxLogger

Constant Summary collapse

VERSION =
"0.1.3"
VENDOR =
"Palo Alto"
PRODUCT =
"NGFW"

Class Method Summary collapse

Class Method Details

.enable_loggingObject



148
149
150
151
152
153
154
# File 'lib/paloalto.rb', line 148

def self.enable_logging()
  @log = Paloalto::NxLogger.instance
  @log.setup_statistics_collection(Paloalto::VENDOR,
                                   Paloalto::PRODUCT,
                                   Paloalto::VERSION)
  @log.setup_logging(true, 'info')
end

.set_variables(options) ⇒ Object



156
157
158
159
160
161
162
163
164
165
# File 'lib/paloalto.rb', line 156

def self.set_variables(options)
  settings = {}
  options.each_key do |key|
    value = ENV[key.to_s.upcase]
    value ||= options[key]
    @log.log_message('No configuration value found for #{key}') if value.nil?
    settings[key] = value
  end
  settings
end

.start_integration(nexpose_settings, pan_settings) ⇒ Object



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/paloalto.rb', line 7

def self.start_integration(nexpose_settings, pan_settings)
  # Asset query.
  asset_query = "select asset_id, da.ip_address, string_agg(DISTINCT '<' || dt.tag_name, '>') || '>' as tags
  from dim_site_asset
  LEFT OUTER JOIN dim_asset da USING (asset_id)
  LEFT OUTER JOIN dim_tag_asset dta using (asset_id)
  LEFT OUTER JOIN dim_tag dt using (tag_id)
  GROUP BY asset_id, da.ip_address"

  nexpose_url = nexpose_settings[:nexpose_url]
  nexpose_username = nexpose_settings[:nexpose_username]
  nexpose_password = nexpose_settings[:nexpose_password]
  nexpose_port = nexpose_settings[:nexpose_port]

  pan_url = pan_settings[:pan_url]
  pan_username = pan_settings[:pan_username]
  pan_password = pan_settings[:pan_password]

  report_timeout = nexpose_settings[:timeout]

  # Nexpose sites and DAGs to import. Uses Site Id and DAG ID e.g.
  # 'sites = [1,2,3,4]'. Leave as nil to run on all sites and DAGs the user
  # has access to or set as an empty array e.g. 'dags=[]' to not run on any sites/dags.
  sites = nexpose_settings[:sites]
  dags = nexpose_settings[:dag]

  @log.log_message("Running with user configured site IDs <#{sites}> and dynamic asset group IDs #{dags}.")

  # Log in to nexpose.
  nsc = Paloalto::NexposeHelper.(nexpose_url,
                                      nexpose_username,
                                      nexpose_password,
                                      nexpose_port)

  # Gather the sites
  all_sites = nsc.sites
  all_sites.delete_if {|site| !(sites.include? site.id)} unless sites.nil?
  all_sites_names = []
  all_sites.each { |site|  (all_sites_names ||= []) << site.name.to_s }

  # Handle any Nexpose Dynamic Asset Groups
  # These will have a single tag (The Nexpose group name) with a Dynamic group name the same.
  nexpose_dag_query_results = Paloalto::NexposeHelper.generate_dag_asset_groups({timeout: report_timeout}, nsc)
  all_nexpose_dag_details  = Paloalto::NexposeHelper.parse_dag_details(nexpose_dag_query_results)
  all_nexpose_dag_details.delete_if {|dag_details| !(dags.include? dag_details[0].to_i)} unless dags.nil?

  @log.log_message("User has access to the following site IDs <#{all_sites.each {|site| site.id}}> and dynamic asset group IDs #{all_nexpose_dag_details.each {|dag| dag[0]}}.")

  # Login to PAN.
  pan_key = Paloalto::Ngfw.(pan_url, pan_username, pan_password)

  # Get the device config
  device_config_xml = Paloalto::Ngfw.retrieve_device_config(pan_url, pan_key)

  # Get the device names
  device_name = Paloalto::Ngfw.parse_device_name(device_config_xml)
  vsys_name = Paloalto::Ngfw.parse_vsys_name(device_config_xml)

  @log.log_message("Found device configuration. Name <#{device_name}> and vsys <#{vsys_name}>.")

  # Get this device's config
  vsys_config = Paloalto::Ngfw.retrieve_device_config(pan_url, pan_key, device_name, vsys_name)

  # Get the existing tags
  existing_tags = Paloalto::Ngfw.parse_existing_tags(vsys_config)

  # Gather the tags we want to create
  wanted_tags = []
  all_sites_names.each {|site_name| wanted_tags << site_name.gsub(/[()]/, "")}
  wanted_tags << 'Nexpose'
  all_nexpose_dag_details.each {|details| wanted_tags << details[1].gsub(/[()']/, "")}

  # Finds which new tags need to be created
  tags_to_create = wanted_tags - existing_tags

  @log.log_message("New tags to be created <#{tags_to_create}>.")

  # Find the existing DAGs
  existing_dags = Paloalto::Ngfw.parse_existing_dags(vsys_config)

  # Gather the dags we want to create
  wanted_dags = []
  all_sites_names.each {|site_name| wanted_dags << site_name.gsub(/[()]/, "")}
  wanted_dags << 'Nexpose'
  all_nexpose_dag_details.each {|details| wanted_dags << details[1].gsub(/[()']/, "")}

  # Find which new dags need to be created
  dags_to_create = wanted_dags - existing_dags

  @log.log_message("New DAGs to be created <#{dags_to_create}>.")

  # Create the new tags
  @log.log_message("Creating tags...")
  tags_element=''
  tags_to_create.each {|tag_to_create| tags_element << Paloalto::Ngfw.generate_tag_xml(tag_to_create, 'color3', "Nexpose tag for asset grouping: #{tag_to_create}")}
  response = Paloalto::Ngfw.create_tags(pan_url, pan_key, device_name, vsys_name, tags_element) unless tags_element.empty?

  # Create the new dags
  @log.log_message("Creating DAGs...")
  dags_element=''
  dags_to_create.each {|dag_to_create| dags_element << Paloalto::Ngfw.generate_dag_xml(dag_to_create, "'Nexpose' AND '#{dag_to_create}'", dag_to_create)}
  Paloalto::Ngfw.create_dags(pan_url, pan_key, device_name, vsys_name, dags_element) unless dags_element.empty?

  @log.log_message('Committing the changes...')

  # Commit the changes
  response = Paloalto::Ngfw.commit(pan_url, pan_key)

  @log.log_message("Commit response <#{response}>")

  all_sites.each do |site|
    #Fetch this site's details
    @log.log_message("Getting asset details for site <#{site.id}>.")
    report_output = Paloalto::NexposeHelper.generate_report({timeout: report_timeout, site: site.id.to_s, query: asset_query}, nsc)
    asset_details =  Paloalto::NexposeHelper.parse_asset_query_details(report_output, site.name)

    @log.log_message("Unregistering assets for site <#{site.id}>.")
    # Unregister devices. Note have to do this because any "add" updates will append instead of overwriting.
    Paloalto::Ngfw.unregister_devices(pan_url, pan_key, asset_details, site.id)

    @log.log_message("Registering asset details for site <#{site.id}>.")
    # Register the new devices
    Paloalto::Ngfw.register_devices(pan_url, pan_key, asset_details, site.id)

  end

  #Repeat for Nexpose DAGs
  all_nexpose_dag_details.each do |dag_details|
    #Fetch this DAG's details
    @log.log_message("Getting DAG details details for DAG <#{dag_details[0]}>.")
    report_output = Paloalto::NexposeHelper.generate_report({timeout: report_timeout, query: Paloalto::NexposeHelper.generate_dag_assets_query(dag_details[0])}, nsc)
    dag_parsed_details =  Paloalto::NexposeHelper.parse_dag_query_details(report_output, dag_details[1].gsub(/[()']/, ""))

    @log.log_message("Registering asset details for DAG <#{dag_details[0]}>.")
    #Add devices. Note we do not remove these devices first as it will clean wipe the site configuration
    Paloalto::Ngfw.register_devices(pan_url, pan_key, dag_parsed_details, "dag_#{dag_details[0]}")
  end

  @log.log_message('Exiting..')
end