Source code for docker_leash.leash_server

# vim:set ts=4 sw=4 et:
"""Leash server plugin for docker.

This module is responsible for dispatching HTTP requests.
"""

import sys

from flask import jsonify, request

from . import app
from .exceptions import (InvalidRequestException, NoSuchCheckModuleException,
                         UnauthorizedException)
from .processor import Processor

sys.dont_write_bytecode = True


__version__ = '0.0.1.dev0'

[docs]def setup_app(application): """Initialize the application """ application.config["processor"] = Processor() application.config["processor"].load_config()
setup_app(app)
[docs]@app.route('/') def index(): """Main entry point. it respond to the `GET` method for the `/` uri.""" return "Docker Leash Plugin"
[docs]@app.route("/Plugin.Activate", methods=['POST']) def activate(): """Return implemented event system. It is used internally by the Docker daemon to indicate which event system is concerned by the plugin. In the case of this plugin, it return `authz`. See the `official docker documentation <https://docs.docker.com/engine/extend/plugin_api/#pluginactivate>`__. **Request**: .. sourcecode:: http GET /Plugin.Activate HTTP/1.1 Host: example.com Accept: application/json **Response**: .. sourcecode:: http HTTP/1.1 200 OK Vary: Accept Content-Type: application/json { "Implements": ["authz"] } :resheader Content-Type: application/json :status 200: valid response :rtype: :class:`flask.Response` """ return jsonify({'Implements': ['authz']})
[docs]@app.route("/AuthZPlugin.AuthZReq", methods=['POST']) def authz_request(): """Process a request for authorization. This is one of the main feature of this plugin. Depending on the configuration, the system, will allow or deny a request. For a specific user, if no configuration match the `RequestMethod` and the `RequestUri`, then the default action is to deny the request. .. seealso:: Function :func:`authz_response` for response authentication. .. seealso:: See `official docker documentation <https://docs.docker.com/engine/extend/plugins_authorization/#request-authorization>`__. **Request**: .. sourcecode:: http GET /AuthZPlugin.AuthZReq HTTP/1.1 Host: example.com Accept: application/json { "User": "mal", "AuthenticationMethod": "TLS", "RequestMethod": "POST", "RequestUri": "/v1.32/containers/json", "RequestHeaders": "<base64 encoded string>", "RequestBody": "<base64 encoded string>" } **Response**: .. sourcecode:: http HTTP/1.1 200 OK Vary: Accept Content-Type: application/json { "Allow": "true", "Msg": "Authorization granted", "Err": "Authorization granted" } :reqheader Accept: application/json :<json string User: The user identification :<json string AuthenticationMethod: The authentication method used :<json enum RequestMethod: The HTTP method (GET/DELETE/POST) :<json string RequestUri: The HTTP request URI including API version (e.g., /v1.32/containers/json) :<json map[string]string RequestHeaders: Request headers as key value pairs (without the authorization header) :<json []byte RequestBody: Raw request body :>json bool Allow: Boolean value indicating whether the request is allowed or denied :>json string Msg: Authorization message (will be returned to the client in case the access is denied) :>json string Err: Error message. Will be returned to the client in case the plugin encounter an error. The string value supplied may appear in logs, so should not include confidential information. :resheader Content-Type: application/json :status 200: valid response :status 400: malformed request :status 422: invalid parameters :rtype: :class:`flask.Response` """ try: app.config["processor"].run(request.data) except InvalidRequestException as error: app.logger.error("REQUEST DENIED: %s", error) return jsonify({ "Allow": False, "Msg": str(error) }) except UnauthorizedException as error: app.logger.error("REQUEST DENIED: %s", error) return jsonify({ "Allow": False, "Msg": str(error) }) except NoSuchCheckModuleException as error: # pragma: no cover app.logger.critical("REQUEST DENIED: %s", error) return jsonify({ "Allow": False, "Msg": str(error) }) # except BaseException as error: # pragma: no cover # app.logger.critical("REQUEST DENIED: %s", error) # return jsonify({ # "Allow": False, # "Msg": str(error) # }) app.logger.info("REQUEST ALLOWED") return jsonify({ "Allow": True, "Msg": "The authorization succeeded." })
[docs]@app.route("/AuthZPlugin.AuthZRes", methods=['POST']) def authz_response(): """Process a response for authorization. This is one of the main feature of this plugin. Depending on the configuration, the system, will allow or deny a request. .. Warning:: In the current version, we don't check any parameter, and always accept the request. In contrast to :func:`authz_response`, this endpoint is called after the action has been processed by the docker daemon. The request payload contains additional fields representing the response from the daemon. .. seealso:: Function :func:`authz_request` for request authentication. .. seealso:: Check the `official docker documentation <https://docs.docker.com/engine/extend/plugins_authorization/#response-authorization>`__. **Request**: .. sourcecode:: http GET /AuthZPlugin.AuthZReq HTTP/1.1 Host: example.com Accept: application/json { "User": "mal", "AuthenticationMethod": "TLS", "RequestMethod": "POST", "RequestUri": "/v1.32/containers/json", "RequestHeaders": "<base64 encoded string>", "RequestBody": "<base64 encoded string>", "ResponseStatusCode": "200", "ResponseHeaders": "<base64 encoded string>", "ResponseBody": "<base64 encoded string>" } **Response**: .. sourcecode:: http HTTP/1.1 200 OK Vary: Accept Content-Type: application/json { "Allow": "true", "Msg": "Authorization granted", "Err": "Authorization granted" } :reqheader Accept: application/json :<json string User: The user identification :<json string AuthenticationMethod: The authentication method used :<json enum RequestMethod: The HTTP method (GET/DELETE/POST) :<json string RequestUri: The HTTP request URI including API version (e.g., /v1.32/containers/json) :<json map[string]string RequestHeaders: Request headers as key value pairs (without the authorization header) :<json []byte RequestBody: Raw request body :<json int ResponseStatusCode: Status code from the docker daemon :<json map[string]string ResponseHeaders: Response headers as key value pairs :<json []byte ResponseBody: Raw docker daemon response body :>json bool Allow: Boolean value indicating whether the request is allowed or denied :>json string Msg: Authorization message (will be returned to the client in case the access is denied) :>json string Err: Error message. Will be returned to the client in case the plugin encounter an error. The string value supplied may appear in logs, so should not include confidential information. :resheader Content-Type: application/json :status 200: valid response :status 400: malformed request :status 422: invalid parameters :rtype: :class:`flask.Response` """ response = {"Allow": True} return jsonify(**response)