Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

build: merge develop to master #7

Merged
merged 12 commits into from
Mar 28, 2024
Merged
27 changes: 27 additions & 0 deletions .github/workflows/run_tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: Run peasant tests

on: [push, pull_request]

jobs:
build:

runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]

steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
pip install --upgrade pip
pip install -r requirements/basic.txt
pip install -r requirements/all.txt
pip install -r requirements/tests.txt
- name: Run python unit tests
run: |
PYTHONPATH=$PYTHONPATH:. python tests/runtests.py
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.

Copyright 2020 Flavio Goncalves Garcia
Copyright 2020-2024 Flavio Garcia

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
2 changes: 2 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
include README.md
include LICENSE
include requirements/all.txt
include requirements/basic.txt
include requirements/tornado.txt
21 changes: 11 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,29 @@
Peasant is a protocol abstraction of how to control agents that need to
communicate with a central entity or entities.

We define agents as peasants and central entities(bases) as bastions.
We define agents as peasants and central entities (bases) as bastions.

This project won't define the implementation, security level neither levels of
redundancies but instead a minimal contract of what should be implemented.
Peasant will define some transport definition to help developer with basic http
methods (i.e. head, post, get, etc), and avoid code duplication. Security level
and your business should be implemented.

A bastion/peasant relationship could be defined as stateful or not. If stateful
it is necessary to implement a session control in the bastion where peasants
need to perform knocks(as knock at the door) in order to get permission or a
valid session. In a stateless case we just ignore any knock implementation.
need to perform knocks (as knock at the door) to get permission or a valid
session. In a stateless case we just ignore any knock implementation.

What must be implemented in the protocol are nonce generation, consumption and
validation on both sides and a directory list of available resources offered by
a bastion for peasants to consume.
validation on both sides. A directory list of available resources offered by
a bastion for peasants to consume could also be useful to have.

## Support

Automatoes is one of
Peasant is one of
[Candango Open Source Group](http://www.candango.org/projects/)
initiatives. Available under the
[Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.html).

This web site and all documentation is licensed under
This website and all documentation are licensed under
[Creative Commons 3.0](http://creativecommons.org/licenses/by/3.0/).

Copyright © 2020 Flavio Goncalves Garcia
Copyright © 2020-2024 Flavio Garcia
10 changes: 5 additions & 5 deletions peasant/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
# -*- coding: UTF-8 -*-
#
# Copyright 2020-2022 Flávio Gonçalves Garcia
# Copyright 2020-2024 Flavio Garcia
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand All @@ -14,12 +12,14 @@
# See the License for the specific language governing permissions and
# limitations under the License.

__author__ = "Flavio Goncalves Garcia <piraz@candango.org>"
__version__ = (0, 6)
__author__ = "Flavio Garcia <piraz@candango.org>"
__version__ = (0, 6, 1)
__licence__ = "Apache License V2.0"


def get_version():
if isinstance(__version__[-1], str):
return '.'.join(map(str, __version__[:-1])) + __version__[-1]
return ".".join(map(str, __version__))


Expand Down
125 changes: 116 additions & 9 deletions peasant/client.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
# -*- coding: UTF-8 -*-
#
# Copyright 2020 Flavio Goncalves Garcia
# Copyright 2020-2024 Flavio Garcia
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand All @@ -14,24 +12,24 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import copy
import logging
from peasant import get_version
from urllib.parse import urlencode

logger = logging.getLogger(__name__)


class PeasantTransport(object):

_peasant: 'Peasant'
class PeasantTransport:

def __init__(self):
self._peasant = None
_peasant: "Peasant"

@property
def peasant(self):
return self._peasant

@peasant.setter
def peasant(self, peasant):
def peasant(self, peasant: "Peasant"):
self._peasant = peasant

def get(self, path, **kwargs):
Expand Down Expand Up @@ -99,3 +97,112 @@ async def directory(self):
"asynchronously.")
await future
return self._directory_cache


tornado_installed = False
try:
from tornado.httpclient import HTTPRequest
from tornado import version as tornado_version
from tornado.httputil import url_concat
from tornado.httpclient import AsyncHTTPClient, HTTPClientError
tornado_installed = True

def get_tornado_request(url, **kwargs):
""" Return a HTTPRequest to help with AsyncHTTPClient and HTTPClient
execution. The HTTPRequest will use the provided url combined with path
if provided. The HTTPRequest method will be GET by default and can be
changed if method is informed.
If form_urlencoded is defined as True a Content-Type header will be
added to the request with application/x-www-form-urlencoded value.

:param str url: Base url to be set to the HTTPRequest
:key form_urlencoded: If the true will add the header Content-Type
application/x-www-form-urlencoded to the form. Default is False.
:key method: Method to be used by the HTTPRequest. Default it GET.
:key path: If informed will add the path to the base url informed.
Default is None.
:return HTTPRequest:
"""
method = kwargs.get("method", "GET")
path = kwargs.get("path", None)
form_urlencoded = kwargs.get("form_urlencoded", False)
if not url.endswith("/"):
url = f"{url}/"
if path is not None and path != "/":
url = f"{url}{path}" % ()
request = HTTPRequest(url, method=method)
if form_urlencoded:
request.headers.add("Content-Type",
"application/x-www-form-urlencoded")
return request
except ImportError:
pass


class TornadoTransport(PeasantTransport):

def __init__(self, bastion_address):
super().__init__()
if not tornado_installed:
logger.warn("TornadoTransport cannot be used without tornado "
"installed.\nIt is necessary to install peasant "
"with extras modifiers all or tornado.\n\n Ex: pip "
"install peasant[all] or pip install peasant[tornado]"
"\n\nInstalling tornado manually will also work.\n")
raise NotImplementedError
self._client = AsyncHTTPClient()
self._bastion_address = bastion_address
self._directory = None
self.user_agent = (f"Peasant/{get_version()}"
f"Tornado/{tornado_version}")
self._basic_headers = {
'User-Agent': self.user_agent
}

def _get_path(self, path, **kwargs):
query_string = kwargs.get('query_string')
if query_string:
path = url_concat(path, query_string)

def _get_headers(self, **kwargs):
headers = copy.deepcopy(self._basic_headers)
_headers = kwargs.get('headers')
if _headers:
headers.update(_headers)
return headers

async def get(self, path, **kwargs):
path = self._get_path(path, **kwargs)
request = get_tornado_request(self._bastion_address, path=path)
headers = self._get_headers(**kwargs)
request.headers.update(headers)
try:
result = await self._client.fetch(request)
except HTTPClientError as error:
result = error.response
return result

async def head(self, path, **kwargs):
path = self._get_path(path, **kwargs)
request = get_tornado_request(path, method="HEAD")
headers = self._get_headers(**kwargs)
request.headers.update(headers)
try:
result = await self._client.fetch(request)
except HTTPClientError as error:
result = error.response
return result

async def post(self, path, **kwargs):
path = self._get_path(path, **kwargs)
form_data = kwargs.get("form_data", {})
request = get_tornado_request(path, method="POST",
form_urlencoded=True)
headers = self._get_headers(**kwargs)
request.headers.update(headers)
request.body = urlencode(form_data)
try:
result = await self._client.fetch(request)
except HTTPClientError as error:
result = error.response
return result
4 changes: 1 addition & 3 deletions peasant/security/ec.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
# -*- coding: UTF-8 -*-
#
# Copyright 2020-2022 Flávio Gonçalves Garcia
# Copyright 2020-2024 Flavio Garcia
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand Down
4 changes: 1 addition & 3 deletions peasant/security/jwk.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
# -*- coding: UTF-8 -*-
#
# Copyright 2020-2022 Flávio Gonçalves Garcia
# Copyright 2020-2024 Flavio Garcia
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand Down
4 changes: 1 addition & 3 deletions peasant/security/keyring.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
# -*- coding: UTF-8 -*-
#
# Copyright 2020-2022 Flávio Gonçalves Garcia
# Copyright 2020-2024 Flavio Garcia
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand Down
4 changes: 1 addition & 3 deletions peasant/security/rsa.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
# -*- coding: UTF-8 -*-
#
# Copyright 2020-2022 Flávio Goncalves Garcia
# Copyright 2020-2024 Flavio Garcia
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand Down
4 changes: 1 addition & 3 deletions peasant/server.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
# -*- coding: UTF-8 -*-
#
# Copyright 2020 Flavio Goncalves Garcia
# Copyright 2020-2024 Flavio Garcia
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand Down
2 changes: 2 additions & 0 deletions requirements/all.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
-r basic.txt
-r tornado.txt
4 changes: 2 additions & 2 deletions requirements/basic.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
cartola>=0.14
cryptography==36.0.1
cartola>=0.18
cryptography==42.0.5
2 changes: 1 addition & 1 deletion requirements/development.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
-r basic.txt
-r all.txt
-r tests.txt
3 changes: 1 addition & 2 deletions requirements/tests.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
behave==1.2.6
firenado[all]>=0.2.2
firenado[all]>=0.9.4
1 change: 1 addition & 0 deletions requirements/tornado.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
tornado >= 6.3
3 changes: 1 addition & 2 deletions scripts/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,5 @@
##
## Author: Flavio Garcia <piraz@candango.org>

python setup.py bdist_wheel --universal
python setup.py sdist
python -m build
rm -rf build
14 changes: 10 additions & 4 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env python
#
# Copyright 2020 Flavio Garcia
# Copyright 2020-2024 Flavio Garcia
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -57,6 +57,10 @@ def resolve_requires(requirements_file):
url="https://github.com/candango/peasant",
author=peasant.get_author(),
author_email=peasant.get_author_email(),
extras_require={
'all': resolve_requires("requirements/all.txt"),
'tornado': resolve_requires("requirements/tornado.txt"),
},
classifiers=[
"Development Status :: 1 - Planning",
"License :: OSI Approved :: Apache Software License",
Expand All @@ -65,15 +69,17 @@ def resolve_requires(requirements_file):
"Intended Audience :: Developers",
"Intended Audience :: System Administrators",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.5",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3 :: Only",
"Topic :: Software Development :: Libraries :: Application Frameworks"
],
packages=find_packages(),
package_dir={'peasant': "peasant"},
python_requires=">= 3.8",
include_package_data=True,
install_requires=resolve_requires("requirements/basic.txt")
)
Loading