Skip to content

Commit

Permalink
bootstrap
Browse files Browse the repository at this point in the history
  • Loading branch information
tomkralidis committed Nov 18, 2024
1 parent 0f43e5e commit 7900c08
Show file tree
Hide file tree
Showing 13 changed files with 653 additions and 0 deletions.
24 changes: 24 additions & 0 deletions .github/workflows/flake8.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: flake8

on:
[ push, pull_request ]

jobs:
flake8_py3:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@master
- uses: actions/setup-python@v5
name: setup Python
with:
python-version: '3.10'
- name: Checkout pygeoapi-auth
uses: actions/checkout@master
- name: Install flake8
run: pip3 install flake8
- name: Run flake8
uses: suo/flake8-github-action@releases/v1
with:
checkName: 'flake8_py3'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
3 changes: 3 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
recursive-include pygeoapi_auth
include README.md
include requirements.txt
103 changes: 103 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# pygeoapi-auth

Python module to manage pygeoapi authorization

## Installation

pygeoapi-auth is best installed and used within a Python virtualenv.

### Requirements

* Python 3 and above
* Python [virtualenv](https://virtualenv.pypa.io) package

### Dependencies

Dependencies are listed in [requirements.txt](requirements.txt). Dependencies
are automatically installed during pygeoapi-auth's installation.

### Installing the Package

```bash
python3 -m venv my-env
cd my-env
. bin/activate
git clone https://github.com/cartologic/pygeoapi-auth.git
cd pygeoapi-auth
python3 setup.py install
```

## Running

### From the command line

```bash
# show all subcommands
pygeoapi-auth

# inject authorization into OpenAPI using Authelia
pygeoapi-auth openapi inject-auth local-openapi.yml authelia authelia-conf.yml

# inject authorization into OpenAPI using Authelia with an API prefix
pygeoapi-auth openapi inject-auth local-openapi.yml authelia authelia-conf.yml --api-prefix api

# inject authorization into OpenAPI using Authelia with an API prefix, writing to file
pygeoapi-auth openapi inject-auth local-openapi.yml authelia authelia-conf.yml --api-prefix api --output-file openapi-auth.yml

# if installed in the pygeoapi deployment environment, run as a plugin!
pygeoapi plugins openapi inject-auth local-openapi.yml authelia authelia-conf.yml --api-prefix api --output-file openapi-auth.yml
```

### Using the API from Python

TODO

## Development

### Setting up a Development Environment

Same as installing a package. Use a virtualenv. Also install developer
requirements:

```bash
pip3 install -r requirements-dev.txt
```

### Running Tests

```bash
# via setuptools
python3 setup.py test
# manually
cd tests
python3 run_tests.py
```

## Releasing

```bash
# update version
vi pygeoapi_auth/__init__.py
git commit -m 'update release version' pygeoapi_auth/__init__.py
# push changes
git push origin master
git tag -a x.y.z -m 'tagging release x.y.z'
# push tag
git push --tags
rm -fr build dist *.egg-info
python3 setup.py sdist bdist_wheel --universal
twine upload dist/*
```

### Code Conventions

* [PEP8](https://www.python.org/dev/peps/pep-0008)

### Bugs and Issues

All bugs, enhancements and issues are managed on [GitHub](https://github.com/geopython/pygeoapi-auth/issues).

## Contact

* [Tom Kralidis](https://github.com/tomkralidis)
* [Youssef Harby](https://github.com/Youssef-Harby)
43 changes: 43 additions & 0 deletions pygeoapi_auth/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
###################################################################
#
# Authors: Tom Kralidis <tomkralidis@gmail.com>
#
# Copyright (c) 2024 Tom Kralidis
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation
# files (the "Software"), to deal in the Software without
# restriction, including without limitation the rights to use,
# copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following
# conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# OTHER DEALINGS IN THE SOFTWARE.
#
###################################################################

import click

from pygeoapi_auth.openapi import openapi

__version__ = '0.0.1'


@click.group()
@click.version_option(version=__version__)
def cli():
pass


cli.add_command(openapi)
81 changes: 81 additions & 0 deletions pygeoapi_auth/auth/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
###################################################################
#
# Authors: Tom Kralidis <tomkralidis@gmail.com>
#
# Copyright (c) 2024 Tom Kralidis
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation
# files (the "Software"), to deal in the Software without
# restriction, including without limitation the rights to use,
# copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following
# conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# OTHER DEALINGS IN THE SOFTWARE.
#
###################################################################

from abc import ABC, abstractmethod
import importlib
import logging
from typing import IO

import yaml

LOGGER = logging.getLogger(__name__)


class AuthProvider(ABC):
def __init__(self, config: IO = None):
"""Initializer"""

self.config = yaml.safe_load(config)
self.resources = self.get_resources()

@abstractmethod
def get_resources(self):
raise NotImplementedError()

@abstractmethod
def is_resource_protected(
self, path: str, api_prefix: str = None) -> bool:

raise NotImplementedError()


def load_auth_provider(factory: str, config_file: str) -> AuthProvider:
"""
Load auth provider plugin
:param factory: `str` of dotted path of Python module/class
:param configuration: `str` of configuration of auth provider
:returns: AuthProvider object
"""

modulename = f'{__package__}.{factory}'
classname = AUTH_PROVIDERS[factory]

LOGGER.debug(f'module name: {modulename}')
LOGGER.debug(f'class name: {classname}')

module = importlib.import_module(modulename)

return getattr(module, classname)(config_file)


AUTH_PROVIDERS = {
'authelia': 'AutheliaAuthProvider'
}
58 changes: 58 additions & 0 deletions pygeoapi_auth/auth/authelia.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
###################################################################
#
# Authors: Tom Kralidis <tomkralidis@gmail.com>
#
# Copyright (c) 2024 Tom Kralidis
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation
# files (the "Software"), to deal in the Software without
# restriction, including without limitation the rights to use,
# copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following
# conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# OTHER DEALINGS IN THE SOFTWARE.
#
###################################################################

import logging
import re

from pygeoapi_auth.auth import AuthProvider

LOGGER = logging.getLogger(__name__)


class AutheliaAuthProvider(AuthProvider):
def get_resources(self):
print(self.config)
return [item for sublist in self.config['access_control']['rules']
for item in sublist['resources']]

def is_resource_protected(self, path: str, api_prefix: str = None) -> bool:
for resource in self.resources:
LOGGER.debug(f'Testing {path} against {resource}')
if api_prefix is not None:
path2 = f'/{api_prefix}{path}'
else:
path2 = path

LOGGER.debug(f'Generated path: {path2}')

if re.search(resource, path2):
LOGGER.debug(f'{path2} matches {resource}')
return True

return False
53 changes: 53 additions & 0 deletions pygeoapi_auth/cli_options.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
###################################################################
#
# Authors: Tom Kralidis <tomkralidis@gmail.com>
#
# Copyright (c) 2024 Tom Kralidis
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation
# files (the "Software"), to deal in the Software without
# restriction, including without limitation the rights to use,
# copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following
# conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# OTHER DEALINGS IN THE SOFTWARE.
#
###################################################################

import logging
import sys

import click


def OPTION_VERBOSITY(f):
logging_options = ['ERROR', 'WARNING', 'INFO', 'DEBUG']

def callback(ctx, param, value):
if value is not None:
logging.basicConfig(stream=sys.stdout,
level=getattr(logging, value))
return True

return click.option('--verbosity', '-v',
type=click.Choice(logging_options),
help='Verbosity',
callback=callback)(f)


def cli_callbacks(f):
f = OPTION_VERBOSITY(f)
return f
Loading

0 comments on commit 7900c08

Please sign in to comment.