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

Possibility for no authentication #464

Merged
merged 22 commits into from
Aug 31, 2023
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ docker
!docker/actinia-core-dev/actinia.cfg
!docker/actinia-core-dev/endpoints.csv
!docker/actinia-core-tests/actinia-test.cfg
!docker/actinia-core-tests/actinia-test-noauth.cfg
.github
.travis
.travis.yml
Expand Down
2 changes: 2 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# E402 module level import not at top of file
# E501 line too long (80 > 79 characters)
# F401 '.health_check.health_check' imported but unused
# F811 redefinition of unused 'verify_password' from line 55
# F821 undefined name 'QFile'
# W605 invalid escape sequence '\<'

Expand Down Expand Up @@ -30,6 +31,7 @@ per-file-ignores =
./src/actinia_core/core/interim_results.py: W605
./src/actinia_core/core/list_grass_modules.py: F821
./src/actinia_core/testsuite.py: F401
./src/actinia_core/rest/base/user_auth.py: F811
./src/actinia_core/rest/ephemeral_processing.py: W605
./src/actinia_core/processing/actinia_processing/ephemeral_renderer_base/*: E501
./src/actinia_core/processing/actinia_processing/ephemeral_with_export/raster_export.py: E501
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,4 @@ docker/redis_queue_data/dump.rdb
!docker/actinia-core-dev/actinia.cfg
!docker/actinia-core-dev/endpoints.csv
!docker/actinia-core-tests/actinia-test.cfg
!docker/actinia-core-tests/actinia-test-noauth.cfg
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,8 @@ unittest:
devtest:
sh ./tests_with_redis.sh dev

noauthtest:
sh ./tests_with_redis.sh noauth

integrationtest:
sh ./tests_with_redis.sh integrationtest
1 change: 1 addition & 0 deletions docker/actinia-core-tests/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ RUN grass --tmp-location EPSG:4326 --exec g.extension -s \
# copy needed files and configs for test
COPY docker/actinia-core-alpine/actinia.cfg /etc/default/actinia
COPY docker/actinia-core-tests/actinia-test.cfg /etc/default/actinia_test
COPY docker/actinia-core-tests/actinia-test-noauth.cfg /etc/default/actinia_test_noauth

RUN pip3 install pytest pytest-cov

Expand Down
44 changes: 44 additions & 0 deletions docker/actinia-core-tests/actinia-test-noauth.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
[GRASS]
grass_gis_start_script = /usr/local/bin/grass
grass_database = /actinia_core/grassdb
grass_user_database = /actinia_core/userdata
grass_tmp_database = /actinia_core/workspace/temp_db
grass_resource_dir = /actinia_core/resources
grass_addon_path = /root/.grass8/addons/
grass_gis_base = /usr/local/grass
grass_modules_xml_path = /usr/local/grass/gui/wxpython/xml/module_items.xml
grass_default_location = nc_spm_08

[API]
plugins = []
force_https_urls = True
authentication = False

[LIMITS]
max_cell_limit = 22500000
process_time_limt = 60
process_num_limit = 20
number_of_workers = 3

[REDIS]
redis_server_url = localhost
redis_server_port = 6379
redis_queue_server_url = localhost
redis_queue_server_port = 6379
worker_queue_name = actinia_job
worker_logfile = /actinia_core/workspace/tmp/actinia_worker_test.log

[LOGGING]
log_interface = fluentd
log_fluent_host = fluentd
log_fluent_port = 24224
log_level = 1

[MISC]
tmp_workdir = /actinia_core/workspace/tmp
download_cache = /actinia_core/workspace/download_cache
secret_key = token_signing_key_changeme

[MANAGEMENT]
default_user = user
default_user_group = group
anikaweinmann marked this conversation as resolved.
Show resolved Hide resolved
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,12 @@ API_Docs = "https://redocly.github.io/redoc/?url=https://actinia.mundialis.de/la

[tool.pytest.ini_options]
minversion = "6.0"
addopts = "--cov actinia_core --cov-report term-missing --verbose --tb=line -x"
addopts = "--cov actinia_core --cov-report term-missing --verbose --tb=line -x -s"
testpaths = [
"tests",
]
markers = [
"dev: test current in development",
"unittest: completely independent test",
"noauth: tests for actinia without authentication",
]
11 changes: 7 additions & 4 deletions src/actinia_core/core/common/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# performance processing of geographical data that uses GRASS GIS for
# computational tasks. For details, see https://actinia.mundialis.de/
#
# Copyright (c) 2016-2018 Sören Gebbert and mundialis GmbH & Co. KG
# Copyright (c) 2016-2023 Sören Gebbert and mundialis GmbH & Co. KG
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -116,9 +116,9 @@
from actinia_api import API_VERSION, URL_PREFIX

__license__ = "GPLv3"
__author__ = "Sören Gebbert, Julia Haas"
__author__ = "Sören Gebbert, Julia Haas, Anika Weinmann"
__copyright__ = (
"Copyright 2016-2021, Sören Gebbert and mundialis GmbH & Co. KG"
"Copyright 2016-2023, Sören Gebbert and mundialis GmbH & Co. KG"
)
__maintainer__ = "mundialis"

Expand Down Expand Up @@ -165,11 +165,14 @@
}
}
]
else:
elif global_config.AUTHENTICATION:
# Set the security definition in an unconventional way
flask_api._swagger_object["securityDefinitions"] = {
"basicAuth": {"type": "basic"}
}
flask_api._swagger_object["security"] = [{"basicAuth": []}]

auth = HTTPBasicAuth()
else:
# No authentication
auth = HTTPBasicAuth()
11 changes: 9 additions & 2 deletions src/actinia_core/core/common/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# performance processing of geographical data that uses GRASS GIS for
# computational tasks. For details, see https://actinia.mundialis.de/
#
# Copyright (c) 2016-2018 Sören Gebbert and mundialis GmbH & Co. KG
# Copyright (c) 2016-2023 Sören Gebbert and mundialis GmbH & Co. KG
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -34,7 +34,7 @@
__license__ = "GPLv3"
__author__ = "Sören Gebbert, Anika Weinmann"
__copyright__ = (
"Copyright 2016-2022, Sören Gebbert and mundialis GmbH & Co. KG"
"Copyright 2016-2023, Sören Gebbert and mundialis GmbH & Co. KG"
)
__maintainer__ = "mundialis GmbH & Co. KG"

Expand Down Expand Up @@ -320,6 +320,8 @@ def __init__(self):
self.PLUGINS = []
# ENDPOINTS_CONFIG: configuration csv file for endpoints
self.ENDPOINTS_CONFIG = None
# AUTHENTICATION: If set False no authentication is needed
self.AUTHENTICATION = True

"""
KEYCLOAK: has only to be set if keycloak server is configured with
Expand Down Expand Up @@ -560,6 +562,7 @@ def write(self, path=DEFAULT_CONFIG_PATH):
config.set("API", "FORCE_HTTPS_URLS", str(self.FORCE_HTTPS_URLS))
config.set("API", "PLUGINS", str(self.PLUGINS))
config.set("API", "ENDPOINTS_CONFIG", str(self.ENDPOINTS_CONFIG))
config.set("API", "AUTHENTICATION", str(self.AUTHENTICATION))

config.add_section("KEYCLOAK")
config.set(
Expand Down Expand Up @@ -810,6 +813,10 @@ def read(self, path=DEFAULT_CONFIG_PATH):
self.ENDPOINTS_CONFIG = config.get(
"API", "ENDPOINTS_CONFIG"
)
if config.has_option("API", "AUTHENTICATION"):
self.AUTHENTICATION = config.getboolean(
"API", "AUTHENTICATION"
)

if config.has_section("KEYCLOAK"):
if config.has_option("KEYCLOAK", "CONFIG_PATH"):
Expand Down
80 changes: 80 additions & 0 deletions src/actinia_core/core/common/user_noauth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# -*- coding: utf-8 -*-
#######
# actinia-core - an open source REST API for scalable, distributed, high
# performance processing of geographical data that uses GRASS GIS for
# computational tasks. For details, see https://actinia.mundialis.de/
#
# Copyright (c) 2023 mundialis GmbH & Co. KG
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#
#######

"""
User management for no authentication
"""

# from passlib.apps import custom_app_context as pwd_context
# import jwt
# from datetime import datetime, timezone, timedelta
from actinia_core.core.common.config import global_config
from actinia_core.core.redis_user import redis_user_interface
from actinia_core.core.common.user import ActiniaUser


__author__ = "Anika Weinmann"
__copyright__ = "Copyright 2023, mundialis GmbH & Co. KG"
__maintainer__ = "mundialis GmbH & Co. KG"


class ActiniaUserNoAuth(ActiniaUser):
"""
The Actinia Core user management class for no authentication
"""

db = redis_user_interface

def __init__(self):
"""Constructor
Initialize and create a user object for no authentication.
"""
self.user_id = global_config.DEFAULT_USER
self.user_group = global_config.DEFAULT_USER_GROUP
self.password_hash = None
self.user_role = "superadmin"
self.permissions = None
self.cell_limit = global_config.MAX_CELL_LIMIT
self.accessible_datasets = {
"nc_spm_08": ["PERMANENT", "user1", "landsat"],
"ECAD": ["PERMANENT"],
"latlong_wgs84": ["PERMANENT"],
}
self.accessible_modules = global_config.MODULE_ALLOW_LIST
self.process_num_limit = global_config.PROCESS_NUM_LIMIT
self.process_time_limit = global_config.PROCESS_TIME_LIMT

@staticmethod
def create_user():
"""Create a new user object for no authentication and initialize it

Returns:
actinia_core_api.common.user_noauth.ActiniaUserNoAuth:
A new user object in case of success, or None in case of failure
"""
user = ActiniaUserNoAuth()
user.hash_password("")

if user.commit() is True:
return user
return None
21 changes: 17 additions & 4 deletions src/actinia_core/rest/base/user_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
# performance processing of geographical data that uses GRASS GIS for
# computational tasks. For details, see https://actinia.mundialis.de/
#
# Copyright (c) 2016-2018 Sören Gebbert and mundialis GmbH & Co. KG
# Copyright (c) 2016-2023 Sören Gebbert and mundialis GmbH & Co. KG
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -33,16 +33,29 @@
from actinia_core.core.common.app import auth
from actinia_core.core.common.keycloak_user import ActiniaKeycloakUser
from actinia_core.core.common.user import ActiniaUser
from actinia_core.core.common.user_noauth import ActiniaUserNoAuth
from actinia_core.core.messages_logger import MessageLogger

__license__ = "GPLv3"
__author__ = "Sören Gebbert, Julia Haas"
__author__ = "Sören Gebbert, Julia Haas, Anika Weinmann"
__copyright__ = (
"Copyright 2016-2022, Sören Gebbert and mundialis GmbH & Co. KG"
"Copyright 2016-2023, Sören Gebbert and mundialis GmbH & Co. KG"
)
__maintainer__ = "mundialis"


if not global_config.AUTHENTICATION:
# No authentication
@auth.login_required
def login_required(a, b):
return False

@auth.verify_password
def verify_password(username_or_token, password):
g.user = ActiniaUserNoAuth.create_user()
return True


if global_config.KEYCLOAK_CONFIG_PATH:

@auth.verify_token
Expand All @@ -63,7 +76,7 @@ def verify_token(token):
return True


if global_config.KEYCLOAK_CONFIG_PATH is None:
if global_config.KEYCLOAK_CONFIG_PATH is None and global_config.AUTHENTICATION:

@auth.verify_password
def verify_password(username_or_token, password):
Expand Down
Loading