Table of Contents
WebAPI
Let's try to make a quick win. We have to make a Proof Of Concept about something and writing a Web RestFul API is a good candidate.
Request
All Windows laptops in your company are supposed to execute a script every day. However you have a lot of tickets that may be explained by the fact that this daily script is not executed or too long and raises a kind of timeout.
Your idea is to log when the script starts and when it ends. A good one! However you have no idea how to quickly centralize these log files from all laptops. Why not a Web RestFul API?
Before going further: yes I know that a lot of solutions may solve this issue but the target is to make the POC in less than one hour. As I used to develop Web Restful API then it is my choice.
Architecture
Client side
From client side, we are going to use Powershell command as it is native to Windows 10.
- client_side.ps1
# init $who=whoami $computer=hostname $server="my-server.domain.com" # before the main command, let's call the API Invoke-WebRequest ("http://{2}:5000/my_command/start/{0}/{1}" -f ($who -replace "\\", "@"), $computer, $server) -Method POST # main command my_action # after the main command, let's call the API Invoke-WebRequest ("http://{2}:5000/my_command/end/{0}/{1}" -f ($who -replace "\\", "@"), $computer, $server) -Method POST
API returns something like this:
StatusCode : 201 StatusDescription : Created Content : {"user": "my_user", "action": "start", "ip_remote": "0.1.2.3", "computer": "my_computer"} RawContent : HTTP/1.1 201 Created Connection: close Content-Length: 115 Content-Type: application/json Date: Tue, 26 May 2020 13:46:28 GMT Server: gunicorn/20.0.4 {"user": "my_user", "action": "star... Forms : {} Headers : {[Connection, close], [Content-Length, 115], [Content-Type, application/json], [Date, Tue, 26 May 2020 13:46:28 GMT]...} Images : {} InputFields : {} Links : {} ParsedHtml : mshtml.HTMLDocumentClass RawContentLength : 115
If you are running linux laptop you can adapt the script with curl.
curl -i -XPOST --silent http://localhost:5000/my_command/start/toto/computer HTTP/1.1 201 CREATED Server: gunicorn Date: Fri, 16 Apr 2021 03:07:27 GMT Connection: close Content-Type: application/json Content-Length: 86 {"user": "toto", "action": "start", "ip_remote": "127.0.0.1", "computer": "computer"}
Server side
Run it
python3 -m venv venv source venv/bin/activate pip install -r requirements.txt gunicorn --bind 0.0.0.0:5000 wsgi:app
Logger
- logger.py
import logging logger = logging.getLogger('api') logger.setLevel(logging.DEBUG) # create file handler which logs even debug messages fh = logging.FileHandler('api.log') fh.setLevel(logging.INFO) # create console handler with a higher log level ch = logging.StreamHandler() ch.setLevel(logging.DEBUG) # create formatter and add it to the handlers formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s' ) ch.setFormatter(formatter) fh.setFormatter(formatter) # add the handlers to logger logger.addHandler(ch) logger.addHandler(fh)
WSGI
- wsgi.py
from api import app if __name__ == "__main__": app.run()
API
- api.py
from flask import Flask, request from flask_restful import Resource, Api from logger import logger app = Flask(__name__) api = Api(app) class HelloWorld(Resource): def post(self, user, action, computer): logger.info(f"{computer},{action},{user},{request.remote_addr}") return { "user": user, "action": action, "ip_remote": request.remote_addr, "computer": computer } api.add_resource( HelloWorld, '/my_command/<string:action>/<string:user>/<string:computer>' ) if __name__ == '__main__': app.run(debug=True, host="0.0.0.0")
Requirements
- requirements.txt
flake8 flask_restful gunicorn