Git Product home page Git Product logo

restlos's Introduction

Content

About

RESTlos (german for completely, totally) is a generic Nagios api. Generic means, it can be used with every core that understands the nagios configuration syntax (for example icinga, shinken, etc). It provides a RESTful api for generating any standard nagios object, modify it or delete it.

There are also some convenient functions for reloading the core (via command file) or verify the actual configuration via the REST interface.

Current State

This code is currently in a state of beta testing. For me, everything works as expected. For you... maybe not! So, as usual this code is Open Source and so it comes with absolutely no warrenty. That means if you f... up you monitoring config: don't blame me!

Requirements

If you want to use LDAP authentication:

Quick Start

To get everything just up and running, install all of the required packages mentioned above, and check out the current version from github:

$ git clone https://github.com/Crapworks/RESTlos.git

In the newly created directory, edit the file config.json to fit your nagios/icinga/whatever configuration. To get everything running, you just need to change the properties nagios_main_cfg to your main core configuration file and output_dir to the direcory where the api should manage the object files (and where the user the api is running with has the sufficient rights of course).

If you have done so, fire it up!

$ ./restlosapi.py

Now point your browser to http://localhost:5000 (if you haven't changed the standard port). You should see a page, listing all available endpoints and the corresponding parameters. You can find some example api calls here.

If you are prompted for a password, the initial login credentials are admin:password. Very creative, isn't it?

Deployment

If you want to use it in a production environment, it's REALY recommended to deploy the api to a wsgi capable web server! Why?

  • The Werkzeug server shipped with Flask is single threaded
  • This python script is not trying to be a daemon at all
  • This api currently only supports basic auth and it is a VERY BAD IDEA(tm) to use basic auth over unencrypted HTTP.

To use this api with an apache web server, you need to install mod-wsgi. In the contrib directory you will find a sample apache configuration which can be placed in the conf.d directory. You will also find a file called application.py, which have to be placed in the same directory als the executable python script. This will load the api as a wsgi application into the web server.

As I already mentioned: PLEASE enable SSL for this application.

If anyone can provide configurations for nginx, etc. I would be happy to receive a pull request!

Authentication

As I already mentioned above, this api uses basic auth for authenticating users. To setup the authentication, you HAVE TO CHANGE THE CODE. But don't panic! Everyone who has a basic understanding of what a line or a character is should be able to handle this. So let's see how authentication works.

Authentication Modules

The authentication modules are located in the subfolder utils/authentication. Currently, there are two modules provided: AuthDict and AuthLDAP. AuthDict is the default authentication module and is defined in the __init__.py file. If you just want to grant a few users access to the api, just add some more users to the self.auth dictionary in the AuthDict class.

For authentication against a ldap server, the class AuthLDAP is located in the ldapauth.py in the same directory. You should be able to use this module without any modifications. However, this works for me. If you find some problems with the authentication, just open an issue or fix the code and send me a pull request.

The same applies if you write an additional authentication module (for MySQL or whatever).

Authentication Decorator

To actually use one of the authentication modules, the you have to add it to the decorator list of the view function. Currently there are only to seperate view functions (which are really classes which inherit from the Flask MethodView class): NagiosControlView and NagiosObjectView. The last one handles all of the request to generate/modify/delete objects, the first one is used to provide convenient functions for handling the core, like restarting or validation of the configuration files. It is possible to use different authentication backends for this two views.

The decorators are defined in the class header with the decorators = [...] attribute. The one which is active in the default config is Authentify which uses the AuthDict class by default. There is also a commented line which shows how to use the AuthLDAP class. Here you can add your custom authentication modules and their arguments.

Happy authenticating!

Disable Authentication

If you don't want authentication at all, just delete the decorators = [...] lines for the two classes mentioned above.

Config Files

The configuration file config.json, which has to be located in the same directory as the executable, controls the main behaivior. It uses the JSON sytnax, just like the api itself. The default configuration should fit for a standard Nagios installation on Debian/Ubuntu systems.

The most important key are:

nagios_main_cfg

Full path to the main configuration file of the core (nagios.cfg, icinga.cfg, etc.)

nagios_bin

Full path to the core executable (ex: /usr/sbin/icinga). Needed for config checks.

output_dir

Full path to the directory where the configuration files generated by the api should be placed

In consequence minimal configuration file would look like this

{
    "nagios_main_cfg": "/etc/icinga/icinga.cfg",
    "output_dir": "/etc/icinga/objects"
}

The two other available keys are:

port

set the port where the stand alone application should listen for incoming tcp connections

logging

control the loggin behavior of the application. This dictionary is directly passed to logging.config.dictConfig(). For a complete overview of the available options see: The official documentation of the logging Module. By default, the application logs DEBUG output to stdout and everything with level WARN or higher goes to syslog with the daemon fascility.

Example API Calls

There are some example api calls available in the Wiki.

restlos's People

Contributors

crapworks avatar petrovicboban avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

restlos's Issues

API crushes on control?restart

Trying to restart nagios from api by sending commands as you showed in examples and api crusshes.

Here is the request

 curl -X POST -H "content-type: application/json" -v 'http://admin:[email protected]:5000/control?restart'

* About to connect() to monitor.lanbilling.ru port 5000 (#0)
*   Trying 192.168.x.1... Connection refused
* couldn't connect to host
* Closing connection #0
curl: (7) couldn't connect to host
[andruss@example ~]# curl -X POST -H "content-type: application/json" -v 'http://admin:[email protected]:5000/control?restart'
* About to connect() to monitor.example.com port 5000 (#0)
*   Trying 192.168.x.1... connected
* Connected to monitor.lanbilling.ru (192.168.x.1) port 5000 (#0)
* Server auth using Basic with user 'admin'
> POST /control?restart HTTP/1.1
> Authorization: Basic YWRtaW46cGFzc3dvcmQ=
> User-Agent: curl/7.19.7 (i386-redhat-linux-gnu) libcurl/7.19.7 NSS/3.21 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2
> Host: andruss.example.net:5000
> Accept: */*
> content-type: application/json
> 
* Empty reply from server

and api itself running everything is ok

[root@dhcp restlos]# python2.7 /opt/restlos/restlosapi.py 5000
 * starting restlos V0.3
 * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)

but when above curl command is sent got the following:

Traceback (most recent call last):
  File "/opt/restlos/restlosapi.py", line 363, in 
    app.run(port=config['port'],host='0.0.0.0')
  File "/usr/local/lib/python2.7/site-packages/flask/app.py", line 843, in run
    run_simple(host, port, self, **options)
  File "/usr/local/lib/python2.7/site-packages/werkzeug/serving.py", line 694, in run_simple
    inner()
  File "/usr/local/lib/python2.7/site-packages/werkzeug/serving.py", line 659, in inner
    srv.serve_forever()
  File "/usr/local/lib/python2.7/site-packages/werkzeug/serving.py", line 499, in serve_forever
    HTTPServer.serve_forever(self)
  File "/usr/local/lib/python2.7/SocketServer.py", line 238, in serve_forever
    self._handle_request_noblock()
  File "/usr/local/lib/python2.7/SocketServer.py", line 297, in _handle_request_noblock
    self.handle_error(request, client_address)
  File "/usr/local/lib/python2.7/SocketServer.py", line 295, in _handle_request_noblock
    self.process_request(request, client_address)
  File "/usr/local/lib/python2.7/SocketServer.py", line 321, in process_request
    self.finish_request(request, client_address)
  File "/usr/local/lib/python2.7/SocketServer.py", line 334, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "/usr/local/lib/python2.7/SocketServer.py", line 651, in __init__
    self.handle()
  File "/usr/local/lib/python2.7/site-packages/werkzeug/serving.py", line 216, in handle
    rv = BaseHTTPRequestHandler.handle(self)
  File "/usr/local/lib/python2.7/BaseHTTPServer.py", line 340, in handle
    self.handle_one_request()
  File "/usr/local/lib/python2.7/site-packages/werkzeug/serving.py", line 251, in handle_one_request
    return self.run_wsgi()
  File "/usr/local/lib/python2.7/site-packages/werkzeug/serving.py", line 193, in run_wsgi
    execute(self.server.app)
  File "/usr/local/lib/python2.7/site-packages/werkzeug/serving.py", line 181, in execute
    application_iter = app(environ, start_response)
  File "/usr/local/lib/python2.7/site-packages/flask/app.py", line 2000, in __call__
    return self.wsgi_app(environ, start_response)
  File "/usr/local/lib/python2.7/site-packages/flask/app.py", line 1991, in wsgi_app
    response = self.make_response(self.handle_exception(e))
  File "/usr/local/lib/python2.7/site-packages/flask/app.py", line 1559, in handle_exception
    handler = self._find_error_handler(InternalServerError())
  File "/usr/local/lib/python2.7/site-packages/flask/app.py", line 1476, in _find_error_handler
    .get(code))
  File "/usr/local/lib/python2.7/site-packages/flask/app.py", line 1465, in find_handler
    handler = handler_map.get(cls)
AttributeError: 'function' object has no attribute 'get'

pynag (0.9.1)

Hi,
It seem pynag has some changes and the following code can not work now
self.command_file = Model.Control.Command.find_command_file(config['nagios_main_cfg'])
.......
Model.Control.Command.restart_program(command_file=self.command_file)

I have to change them as the following to make work.

self.command_file = Control.Command.find_command_file(config['nagios_main_cfg'])
.......
Control.Command.restart_program(command_file=self.command_file)

If anyone encounter the same problem, maybe it helps

Problem adding timeperiod

$ cat /tmp/timeperiods 
[
  {
    "thursday" : "00:00-24:00", 
    "wednesday" : "00:00-24:00", 
    "friday" : "00:00-24:00", 
    "sunday" : "00:00-24:00", 
    "alias": "Always-2", 
    "monday" : "00:00-24:00", 
    "tuesday" : "00:00-24:00", 
    "timeperiod_name": "24x7-2", 
    "saturday" : "00:00-24:00"
  }
]

$ curl -X POST -d @/tmp/timeperiods  -H "content-type: application/json" 'http://admin:[email protected]:8080/timeperiod'
{
  "results": [
    {
      "404": "unknown attribute: monday"
    }
  ], 
  "summary": {
    "failed": 1, 
    "succeeded": 0, 
    "total": 1
  }
}

unknown attribute: monday wtf??
However, it is possible that this is related to pynag issue I've submited.

AttributeError: 'function' object has no attribute 'get'

$ curl -H "content-type: application/json" 'http://admin:[email protected]/host?host_name=app' returns
curl: (52) Empty reply from server

Application crashes with:

\# ./restlosapi.py   


 \* starting restlos V0.3
 \* Running on http://0.0.0.0:80/ (Press CTRL+C to quit)
91.222.7.8 - - [12/Aug/2016 12:10:13] "GET /host HTTP/1.1" 200 -
Traceback (most recent call last):
  File "./restlosapi.py", line 363, in <module>
    app.run(host='0.0.0.0', port=config['port'])
  File "/usr/lib64/python2.7/site-packages/flask/app.py", line 843, in run
    run_simple(host, port, self, **options)
  File "/usr/lib/python2.7/site-packages/werkzeug/serving.py", line 694, in run_simple
    inner()
  File "/usr/lib/python2.7/site-packages/werkzeug/serving.py", line 659, in inner
    srv.serve_forever()
  File "/usr/lib/python2.7/site-packages/werkzeug/serving.py", line 499, in serve_forever
    HTTPServer.serve_forever(self)
  File "/usr/lib64/python2.7/SocketServer.py", line 238, in serve_forever
    self._handle_request_noblock()
  File "/usr/lib64/python2.7/SocketServer.py", line 297, in _handle_request_noblock
    self.handle_error(request, client_address)
  File "/usr/lib64/python2.7/SocketServer.py", line 295, in _handle_request_noblock
    self.process_request(request, client_address)
  File "/usr/lib64/python2.7/SocketServer.py", line 321, in process_request
    self.finish_request(request, client_address)
  File "/usr/lib64/python2.7/SocketServer.py", line 334, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "/usr/lib64/python2.7/SocketServer.py", line 649, in __init__
    self.handle()
  File "/usr/lib/python2.7/site-packages/werkzeug/serving.py", line 216, in handle
    rv = BaseHTTPRequestHandler.handle(self)
  File "/usr/lib64/python2.7/BaseHTTPServer.py", line 340, in handle
    self.handle_one_request()
  File "/usr/lib/python2.7/site-packages/werkzeug/serving.py", line 251, in handle_one_request
    return self.run_wsgi()
  File "/usr/lib/python2.7/site-packages/werkzeug/serving.py", line 193, in run_wsgi
    execute(self.server.app)
  File "/usr/lib/python2.7/site-packages/werkzeug/serving.py", line 181, in execute
    application_iter = app(environ, start_response)
  File "/usr/lib64/python2.7/site-packages/flask/app.py", line 2000, in __call__
    return self.wsgi_app(environ, start_response)
  File "/usr/lib64/python2.7/site-packages/flask/app.py", line 1991, in wsgi_app
    response = self.make_response(self.handle_exception(e))
  File "/usr/lib64/python2.7/site-packages/flask/app.py", line 1559, in handle_exception
    handler = self._find_error_handler(InternalServerError())
  File "/usr/lib64/python2.7/site-packages/flask/app.py", line 1476, in _find_error_handler
    .get(code))
  File "/usr/lib64/python2.7/site-packages/flask/app.py", line 1465, in find_handler
    handler = handler_map.get(cls)
AttributeError: 'function' object has no attribute 'get'

It''s python 2.7.5, and Flask 0.11.1
This also happens when I try to create some hosts.

Custom macro

Can I handle custom macro (create/remove/update) with RESTlos ?

Help with deploymet

Could you advise on installation to production.

To use this api with an apache web server, you need to install mod-wsgi.

Done

httpd -M | grep wsgi
Syntax OK
 wsgi_module (shared)

In the contrib directory you will find a sample apache configuration which can be placed in the conf.d directory.

Done. Also copied all files to
/opt/restols
as mentioned in /opt/restlos/contrib/restlos-directory.
Then on next step.

You will also find a file called application.py, which have to be placed in the same directory as the executable python script.This will load the api as a wsgi application into the web server.

Err, didn't found it.

[andruss@serv restlos]# find /opt/restlos/ -name "application"

Then i head to to http://nagios.domain.net/restlos

And got 503 error

Inside apache error log

[Tue Aug 16 15:46:48 2016] [error] [client 192.168.1.222] (13)Permission denied: mod_wsgi (pid=19069): Unable to connect to WSGI daemon process 'restlos' on '/etc/httpd/logs/wsgi.19065.0.1.sock' after multiple attempts.

ls -lh /etc/httpd/logs/

srwx------ 1 apache root    0 Aug 16 16:06 wsgi.21577.0.1.sock

i.e is avalible '/etc/httpd/logs/wsgi.19065.0.1.sock' but it 0 bytes.

What permissions should be for /etc/httpd/logs/wsgi.19065.0.1.sock and should be restlos running in background ?

__contains added to querystring parameters

  1. Thanks for restlos

  2. When giving parameters to objectview, they are given a suffix of __contains, thus making it hard to to host?host_name=a to get a host called a without getting a lot of extra results.

Would it be possible remove that suffix and let the connecting program add __contains if a wildcard is wanted ?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.