Class: Shells::PfShellWrapper
- Inherits:
-
Object
- Object
- Shells::PfShellWrapper
- Defined in:
- lib/shells/pf_shell_wrapper.rb
Overview
A wrapper class around a base shell to execute pfSense PHP commands within.
Constant Summary collapse
- PF_SHELL =
The pfSense shell itself.
'/usr/local/sbin/pfSsh.php'- PF_PROMPT =
The prompt in the pfSense shell.
'pfSense shell:'
Instance Attribute Summary collapse
-
#output ⇒ Object
Gets the output from the pfSense PHP shell session.
Instance Method Summary collapse
-
#apply_filter_config ⇒ Object
Apply the firewall configuration.
-
#apply_user_config(user_id) ⇒ Object
Applies the user configuration for the specified user.
-
#config_parsed? ⇒ Boolean
Determines if the configuration has been parsed during this session.
-
#enable_cert_auth(public_key = '~/.ssh/id_rsa.pub') ⇒ Object
Enabled public key authentication for the current pfSense user.
-
#exec(*commands) ⇒ Object
Executes a series of commands on the pfSense shell.
-
#get_config_section(section_name) ⇒ Object
Gets a configuration section from the pfSense device.
-
#initialize(base_shell, &block) ⇒ PfShellWrapper
constructor
Creates the wrapper, executing the pfSense shell.
-
#parse_config ⇒ Object
Reloads the pfSense configuration on the device.
-
#quit ⇒ Object
Exits the shell session immediately.
-
#reboot ⇒ Object
Exits the shell session immediately and requests a reboot of the pfSense device.
-
#set_config_section(section_name, values, message = '') ⇒ Object
Sets a configuration section to the pfSense device.
Constructor Details
#initialize(base_shell, &block) ⇒ PfShellWrapper
Creates the wrapper, executing the pfSense shell.
The provided code block is yielded this wrapper for execution.
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 |
# File 'lib/shells/pf_shell_wrapper.rb', line 30 def initialize(base_shell, &block) raise ArgumentError, 'a code block is required' unless block_given? raise ArgumentError, 'the base shell must be a valid shell' unless base_shell.is_a?(::Shells::ShellBase) self.shell = base_shell wrapper = self code_block = block self.output = '' self.config_parsed = false shell.instance_eval do merge_local_buffer do begin temporary_prompt(PF_PROMPT) do debug 'Initializing the pfSense PHP shell...' queue_input PF_SHELL + line_ending wait_for_prompt 999, 10, true debug ' > initialized' begin code_block.call wrapper ensure debug 'Exiting the pfSense PHP shell...' if wait_for_prompt(5, 5, false) # only queue the exit command if we are still in the pfSense shell. queue_input 'exit' + line_ending end end end ensure # wait for the normal shell to return. wait_for_prompt 10, 10, true debug ' > exited' wrapper.output = output end end end end |
Instance Attribute Details
#output ⇒ Object
Gets the output from the pfSense PHP shell session.
24 25 26 |
# File 'lib/shells/pf_shell_wrapper.rb', line 24 def output @output end |
Instance Method Details
#apply_filter_config ⇒ Object
Apply the firewall configuration.
You need to apply the firewall configuration after you make changes to aliases, NAT rules, or filter rules.
123 124 125 126 127 128 129 |
# File 'lib/shells/pf_shell_wrapper.rb', line 123 def apply_filter_config exec( 'require_once("shaper.inc");', 'require_once("filter.inc");', 'filter_configure_sync();' ) end |
#apply_user_config(user_id) ⇒ Object
Applies the user configuration for the specified user.
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
# File 'lib/shells/pf_shell_wrapper.rb', line 133 def apply_user_config(user_id) user_id = user_id.to_i exec( 'require_once("auth.inc");', "$user_entry = $config[\"system\"][\"user\"][#{user_id}];", '$user_groups = array();', 'foreach ($config["system"]["group"] as $gidx => $group) {', ' if (is_array($group["member"])) {', " if (in_array(#{user_id}, $group[\"member\"])) { $user_groups[] = $group[\"name\"]; }", ' }', '}', # Intentionally run set_groups before and after to ensure group membership gets fully applied. 'local_user_set_groups($user_entry, $user_groups);', 'local_user_set($user_entry);', 'local_user_set_groups($user_entry, $user_groups);' ) end |
#config_parsed? ⇒ Boolean
Determines if the configuration has been parsed during this session.
87 88 89 |
# File 'lib/shells/pf_shell_wrapper.rb', line 87 def config_parsed? config_parsed end |
#enable_cert_auth(public_key = '~/.ssh/id_rsa.pub') ⇒ Object
Enabled public key authentication for the current pfSense user.
Once this has been done you should be able to connect without using a password.
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 |
# File 'lib/shells/pf_shell_wrapper.rb', line 155 def enable_cert_auth(public_key = '~/.ssh/id_rsa.pub') cert_regex = /^ssh-[rd]sa (?:[A-Za-z0-9+\/]{4})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=)? \S*$/m # get our cert unless the user provided a full cert for us. unless public_key =~ cert_regex public_key = File.(public_key) if File.exist?(public_key) public_key = File.read(public_key).to_s.strip else raise Shells::PfSenseCommon::PublicKeyNotFound end raise Shells::PfSenseCommon::PublicKeyInvalid unless public_key =~ cert_regex end cfg = get_config_section 'system' user_id = nil user_name = [:user].downcase cfg['user'].each_with_index do |user,index| if user['name'].downcase == user_name user_id = index authkeys = Base64.decode64(user['authorizedkeys'].to_s).gsub("\r\n", "\n").strip unless authkeys == '' || authkeys =~ cert_regex warn "Existing authorized keys for user #{[:user]} are invalid and are being reset." authkeys = '' end if authkeys == '' user['authorizedkeys'] = Base64.strict_encode64(public_key) else authkeys = authkeys.split("\n") unless authkeys.include?(public_key) authkeys << public_key unless authkeys.include?(public_key) user['authorizedkeys'] = Base64.strict_encode64(authkeys.join("\n")) end end break end end raise Shells::PfSenseCommon::UserNotFound unless user_id set_config_section 'system', cfg, "Enable certificate authentication for #{[:user]}." apply_user_config user_id end |
#exec(*commands) ⇒ Object
Executes a series of commands on the pfSense shell.
72 73 74 75 76 |
# File 'lib/shells/pf_shell_wrapper.rb', line 72 def exec(*commands) ret = '' commands.each { |cmd| ret += shell.exec(cmd) } ret + shell.exec('exec') end |
#get_config_section(section_name) ⇒ Object
Gets a configuration section from the pfSense device.
93 94 95 96 |
# File 'lib/shells/pf_shell_wrapper.rb', line 93 def get_config_section(section_name) parse_config unless config_parsed? JSON.parse exec("echo json_encode($config[#{section_name.to_s.inspect}]);").strip end |
#parse_config ⇒ Object
Reloads the pfSense configuration on the device.
80 81 82 83 |
# File 'lib/shells/pf_shell_wrapper.rb', line 80 def parse_config exec 'parse_config(true);' self.config_parsed = true end |
#quit ⇒ Object
Exits the shell session immediately.
214 215 216 217 |
# File 'lib/shells/pf_shell_wrapper.rb', line 214 def quit raise Shells::NotRunning unless running? raise Shells::ShellBase::QuitNow end |
#reboot ⇒ Object
Exits the shell session immediately and requests a reboot of the pfSense device.
207 208 209 210 |
# File 'lib/shells/pf_shell_wrapper.rb', line 207 def reboot raise Shells::NotRunning unless running? raise Shells::PfSenseCommon::RestartNow end |
#set_config_section(section_name, values, message = '') ⇒ Object
Sets a configuration section to the pfSense device.
Returns the number of changes made to the configuration.
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
# File 'lib/shells/pf_shell_wrapper.rb', line 102 def set_config_section(section_name, values, = '') current_values = get_config_section(section_name) changes = generate_config_changes("$config[#{section_name.to_s.inspect}]", current_values, values) if changes&.any? if .to_s.strip == '' = "Updating #{section_name} section." end changes << "write_config(#{.inspect});" exec(*changes) (changes.size - 1) else 0 end end |