Skip to content

Commit

Permalink
Initial load into GitHub.
Browse files Browse the repository at this point in the history
  • Loading branch information
randyoyarzabal committed Oct 9, 2017
1 parent d4c54c4 commit de01024
Show file tree
Hide file tree
Showing 24 changed files with 3,158 additions and 0 deletions.
112 changes: 112 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
# OSX and IDE related
.DS_Store
.idea

# Project releated
logs
logs/*
testDriver.py
bashTests.sh
config.ini

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
target/

# Jupyter Notebook
.ipynb_checkpoints

# pyenv
.python-version

# celery beat schedule file
celerybeat-schedule

# SageMath parsed files
*.sage.py

# dotenv
.env

# virtualenv
.venv
venv/
ENV/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/
14 changes: 14 additions & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
Legend: + : added, - : removed, * : fixed

https://github.com/randyoyarzabal/reach

v1.0.1 [5-Dec-2016]:
------------
+ Added prompt detection.
* Fixed a bug where Vyatta (configuration mode) prompt change was not being detected.
* Fixed "Host Duration" simulation display

v1.0.0 [4-Dec-2016]:
------------
+ Initial release.

1 change: 1 addition & 0 deletions CNAME
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
reach.rbpsiu.com
138 changes: 138 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
### Developers

- Randy Oyarzabal
- Francis Lan

### Tested Use Cases

- Firewall rules validation
- Network device configuration (e.g. Cisco, F5, Brocade etc. equipment)
- Firewall / host backups
- Middleware installation/support management
- Host package management
- User and Password management
- Multi-host File/State Search
- Monitoring

### Installation

See the [INSTALL.md](docs/installation/INSTALL.md) file in the `docs/installation/` folder.

### Sample Prerequisite Files

- [Inventory/hosts](docs/templates/hosts_file_sample.csv) file
- [Configuration](docs/templates/config_template.ini) file
- [Batch commands](docs/templates/sample_commands.csv) file

### Synopsis

./reach.py -?
./reach.py -v
./reach.py -a
./reach.py --cipher_text=<password>
./reach.py -b commands_file [-x] [-g] ...
./reach.py -c command [-d search_string [-r report_string]] [-w wait_string -p response_string] ...

Optionally, for any mode:
./reach.py [--config=<config_file>] [-i inventory_file] [-k column_key] [-x] [-g]

### Help / Usage

-? : This help screen
-v : Display version information only

### Operation Modes

-a : Access Check only
-b <commands file> : Run Batch Commands (comma separated file, see template for format/options)
-c <command> : Run Command

### Optional for all Modes

--config=<config_file> Override the default config.ini
-x : Enable SIMULATION (no connection/commands invoked)
-g : Enable DEBUG
-i <inventory_file> : Inventory (hosts) file (comma separated, define header key with -k)
-k <key_column> : [Required with -i] Column header of keys
-e <condition> : Filter hosts to process. Operators are supported: = equal, | or, ~ contains, & and.
Note: Reach does not support mixed (& and |) in this release.
Example conditions: 'Build=WHC0122' , 'Build=WHC0122&Host~app, 'Build=WHC0122|Host~app|Host~dom'

### Optional for Command (-c) Mode
##### *Note that for Batch Mode, these are internally defined in the commands file.*

-o : Show command console output (ignored in batch (-b option) mode)
-s : Run command as root (run 'sudo su -' first)
-h : Halt looping through hosts when first done string (-d) is found

##### The following can use hosts file column variables ($HF) delimited by '|':
##### *For example: '$HF_#' where # is the column number in the hosts file*

--username=<ssh_user> : Force user string instead of what is configured.
--password=<ssh_cipher-text password> : Force cipher-text password instead of what is configured.
--private_key=<ssh_rsa_key> : Force private RSA key file instead of what is configured.
-d <search_string> : Search for string in output (For example: 'Complete' or 'Nothing|Complete')
Can also use '$NF' to test for string is not found.
-r <report_string> : [Optional with same length as -d] Matching string to print to screen when -d match
For example: 'Installed|Not Installed'
-w <wait_string> : Wait string
-p <response_string> : [Required with same length as -w] Send a string when -w string is found
The following list of special markers can be used in -p:
$ENTER_KEY : '\n'
$RETURN_KEY : '\r'
$TAB_KEY : '\t'
$SPACE_KEY : ' '
$CT=<password in cipher text> : Used for sending passwords to the terminal like changing passwords
or sending Cisco ASA passwords in "enable" mode.

### Special mode only for changing passwords to cipher text
--cipher_text=<password> return the password in cipher text to put in the password file

### Examples

- Run 'yum -y install gdb' as root, look for the strings: 'Nothing' or 'Complete', then display
'Installed' or 'Not Installed' on the screen. Process hosts matching 'Build' column = 'WHC038'
./reach.py -c 'yum -y install gdb' -s -d 'Nothing|Complete' -r 'Installed|Not Installed' -e 'Build=WHC038'
-------------------------------------------------------------------------------
- Run 'sh ip route 10.143.92.134', look for the strings: 'bond0.' or 'bond0', then display
'Found in: $HF_1' ($HF_1 is the first column of the inventory) or 'Not Here' then halt the hosts loop
./reach.py -c "sh ip route 10.143.92.134" -d 'bond0.|bond0' -r 'Found in: $HF_1|Not Here' -h
-------------------------------------------------------------------------------
- Check access against all hosts in the inventory file
./reach.py -a
-------------------------------------------------------------------------------
- Force read a different inventory file making sure to define the header key for the IP to use
./reach.py -i 'vga_inventory.csv' -a -k 'Public IP'
-------------------------------------------------------------------------------
- Run a series of commands defined in a file (see template for proper format)
./reach.py -b 'vga_backups.csv'
-------------------------------------------------------------------------------
- Change password for a user (run this in simulation mode for an explanation)
./reach.py -c 'passwd randyo' -w 'New|Retype' -p 'mypass3|mypass3' -d 'successfully' -r 'Changed password'

### Helpful Tips

- Always be sure to run in SIMULATION (-x) mode first to see what the script is about to do!
NOTE: Some of the example below use specific details that may not pertain to your use and is
provided simply as a guide.
- Use the -r option in conjunction with -d to substitute results, optionally use: grep and/or sed to limit output.
Example: Find all hosts where 'vyatta' is found in the zones list.
./reach.py -c 'show zone-policy zone' -d 'vyatta|$NF' -r 'yes|no' | grep -E 'yes|no'
Or used the output in the logs/last_run-log.txt
You may then paste the output as a new column in your inventory file.
- Use bash aliases for different hosts inventory or use, for example:
alias prjA-Utility='reach.py --config=/util_hosts/projectA.ini'
alias prjB-Utility='reach.py --config=/util_hosts/projectB.ini'
alias home-Utility='reach.py --config=/util_hosts/combined.ini -e "Location=Home" --username=\$HF_5'
alias work-Utility='reach.py --config=/util_hosts/combined.ini -e "Location=Work"'
- You can even use a bash function of your favorite use, for example, to find the firewall that an IP belongs to:
function find_firewall { whcUtility -c "sh ip route $1" -d 'bond0.|bond0' \
-r 'Found in: $HF_1 - $HF_3 : $HF_5|Not Here' "${@:2}" -h; }
To use this: find_firewall <ip address>
If you're wondering what "${@:2}" means, it is a neat bash specific notation for handling additional
arguments you may want to use, like: -x (simulation) or -g (debug) etc.
- Be sure to set SSH_COMMAND_TIMEOUT higher than the longest anticipated command duration. But not too high because
if a command hangs, it will wait for that duration before timing out.

### Git Repository
[https://github.com/randyoyarzabal/reach](https://github.com/randyoyarzabal/reach)
1 change: 1 addition & 0 deletions _config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
theme: jekyll-theme-slate
61 changes: 61 additions & 0 deletions configs/config.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
; Change the settings below to suit your needs.
; No leading spaces are allowed and comments always start with a ";" (semi-colon).
; DO NOT change the name of the section header.

; You may create copies of this file and pass to the tool like this:
; ./reach.py --config_file=<config file>

[TOOL DEFAULTS] ; Do not change this!

; Optional, comment this if you want to be prompted each time for a user name to use
; Define the rest of the defaults values below to suit.
SSH_USER_NAME : testuser

; Optional, comment this if you want to be prompted each time for a password to use
; Cipher text rsa key passphrase or password
; To generate the cipher text: ./reach.py --cipher_text=<real password>
SSH_PASSWORD_CIPHER : XXXXXXXXXXX

; Optional, comment this if no RSA keys will be used
SSH_PRIVATE_KEY : /Users/randyo/.ssh/id_rsa

; Define default hosts inventory to use. It needs to be a comma separated file with a header row.
; Be sure to define the matching HOST_MARKER (text displayed when processing)
; and KEY_COLUMN (IP used for connections) below.
HOSTS_INPUT_FILE : /Users/randyo/dev/reach_hosts/my_inventory.csv

; Optional, will log in "logs" directory if this is commented.
LOGS_DIRECTORY : /Users/randyo/dev/reach/logs/

; Valid values: DEBUG, INFO, WARNING, ERROR, CRITICAL
LOG_LEVEL : DEBUG

; Define default key column for the IP address to use for connections.
KEY_COLUMN : IP Address

; Define the string format displayed when processing hosts.
; $HF_# where # is the column number from the file above.
HOST_MARKER : $HF_5 - $HF_1: $HF_3

; Safe to leave all as False or comment. Change to suit.
SHOW_HOST_DURATION : False
SHOW_CONSOLE_OUTPUT : False
RUN_IN_SIMULATION_MODE : False
DEBUG_FLAG : False
NO_DESTRUCTIVE_PROMPT : False

; Set this to True if you want to blindly trust hosts or False to use the system known_hosts file
TRUST_HOSTS : False

SSH_CONNECTION_TIMEOUT : 10

; Important to set this higher than your longest running command you plan to run. But set it too high
; Reach won't move to the next command if the command hangs.
SSH_COMMAND_TIMEOUT : 20

; Safe to leave commented. This is the prompt regex. These are characters to expect on hosts.
; Change only if you know what you're doing. Separate different prompt with |
; Example:
;PROMPT_REGEX : ([$#] |> )$
; Default is:
;PROMPT_REGEX : [$#>]( )?$
38 changes: 38 additions & 0 deletions docs/KNOWN_ISSUES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
Known Issues
------------

We've extensively tested Reach for production use for a variety of use cases against different target host
types such as Linux, Mac, Vyatta, and Cisco devices. However, we are aware of some issues and are continually
working towards enhancements. Here are known issues:

- Reach sends remote commands to a host via an SSH connection over a virtual terminal session. There is no easy
way to detect command completion. What we did (and is the commonly accepted solution) is to set a
personalized prompt and detect the prompt in the virtual terminal's output. This works great for common
commands but we are aware that some situations may lead to unexpected outcomes. Examples:

- Long running commands: Reach will timeout after SSH_COMMAND_TIMEOUT seconds. If you know some commands
are slow, make sure to set a high enough timeout value.
- Executing processes in the background. The command will immediately return but their output will
intertwine with the subsequent commands' output.
Possible solution: Redirect the background output to a file.
- Highly unlikely: the command's output matches the personalized prompt... and then hangs. In that case,
Reach wrongly assumes the command has completed and goes on to the next command or next host.
- The initial prompt is not '#', '$', '# ', or '$ ' and thus Reach will fail.
Solution: configure the PROMPT_REGEX value in config.ini

- If you are using Excel or any other spreadsheet program to edit CSV files, be careful of invisible characters
that are introduced when pasting formatted text like that of from the terminal. You may not see it, but
when you paste formatted text to Excel, it preserved formatting and therefore introducing invisible characters
that will later haunt you in the output or worse yet, the results from Reach. Solution: Always paste to a
text editor first, then copy/paste into Excel before exporting as CSV.

- Other potential issues:
- For commands that hang (e.g. telnet):
- Look for alternatives, for example, it is possible to force telnet to exit on successful connection:
like this: `echo B | telnet -e B 192.168.2.100 8443`, however this only works if the port is
listening. If it it's not, it will just hang at "Trying..."
- An alternative is to use nc. for example, `echo "QUIT" | nc -w 5 192.168.2.100 8443`, if
connected, it won't display any results, if not, it will display: "Ncat: Connection timed out."
You can then use the output as a done string (-d) condition.

If in doubt, always run tests on a single host before running against many and use simulation mode (-x) to verify the actions that will be performed.
Loading

0 comments on commit de01024

Please sign in to comment.