pyrelukko 0.2.0__tar.gz → 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pyrelukko might be problematic. Click here for more details.
- pyrelukko-0.3.0/.gitlab-ci.yml +137 -0
- {pyrelukko-0.2.0 → pyrelukko-0.3.0}/PKG-INFO +2 -1
- pyrelukko-0.3.0/cicd/build-py-rf-image.sh +48 -0
- pyrelukko-0.3.0/cicd/run_docs_pages.sh +17 -0
- pyrelukko-0.3.0/cicd/run_pylint.sh +24 -0
- pyrelukko-0.3.0/cicd/run_pytest.sh +14 -0
- pyrelukko-0.3.0/cicd/run_shellcheck.sh +14 -0
- pyrelukko-0.3.0/container/Containerfile +5 -0
- pyrelukko-0.3.0/container/requirements.txt +3 -0
- {pyrelukko-0.2.0 → pyrelukko-0.3.0}/pyproject.toml +23 -1
- {pyrelukko-0.2.0 → pyrelukko-0.3.0}/src/pyrelukko/pyrelukko.py +1 -1
- pyrelukko-0.2.0/tests/conftest.py → pyrelukko-0.3.0/src/pyrelukko/testcontainers.py +29 -68
- {pyrelukko-0.2.0 → pyrelukko-0.3.0}/src/pyrelukko/version.py +1 -1
- pyrelukko-0.3.0/tests/cert/README.md +11 -0
- pyrelukko-0.3.0/tests/cert/relukko.crt +18 -0
- pyrelukko-0.3.0/tests/cert/relukko.csr +16 -0
- pyrelukko-0.3.0/tests/cert/relukko.key +28 -0
- pyrelukko-0.3.0/tests/cert/rootCA.crt +19 -0
- pyrelukko-0.3.0/tests/cert/rootCA.der +0 -0
- pyrelukko-0.3.0/tests/cert/rootCA.key +28 -0
- pyrelukko-0.3.0/tests/cert/rootCA.srl +1 -0
- pyrelukko-0.3.0/tests/conftest.py +70 -0
- {pyrelukko-0.2.0 → pyrelukko-0.3.0}/tests/test_relukko.py +4 -4
- pyrelukko-0.2.0/.pylintrc.toml +0 -9
- pyrelukko-0.2.0/tests/cert/README.md +0 -8
- pyrelukko-0.2.0/tests/cert/relukko.crt +0 -21
- pyrelukko-0.2.0/tests/cert/relukko.csr +0 -16
- pyrelukko-0.2.0/tests/cert/relukko.der +0 -0
- pyrelukko-0.2.0/tests/cert/relukko.key +0 -28
- pyrelukko-0.2.0/tests/cert/rootCA.crt +0 -21
- pyrelukko-0.2.0/tests/cert/rootCA.der +0 -0
- pyrelukko-0.2.0/tests/cert/rootCA.key +0 -28
- pyrelukko-0.2.0/tests/cert/rootCA.srl +0 -1
- {pyrelukko-0.2.0 → pyrelukko-0.3.0}/LICENSE +0 -0
- {pyrelukko-0.2.0 → pyrelukko-0.3.0}/README.md +0 -0
- {pyrelukko-0.2.0 → pyrelukko-0.3.0}/src/pyrelukko/__init__.py +0 -0
- {pyrelukko-0.2.0 → pyrelukko-0.3.0}/src/pyrelukko/retry.py +0 -0
- /pyrelukko-0.2.0/tests/cert/47615cfb.0 → /pyrelukko-0.3.0/tests/cert/5d868fca.0 +0 -0
- {pyrelukko-0.2.0 → pyrelukko-0.3.0}/tests/initdb.d/20240930160154_init.up.sql +0 -0
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
variables:
|
|
2
|
+
FF_TIMESTAMPS: true
|
|
3
|
+
BUILD_IMAGE:
|
|
4
|
+
description: Used in rules, if "true" and web triggered it builds the image!
|
|
5
|
+
value: "false"
|
|
6
|
+
options:
|
|
7
|
+
- "false"
|
|
8
|
+
- "true"
|
|
9
|
+
IMAGE_NAME: py-rf-image
|
|
10
|
+
IMAGE_TAG:
|
|
11
|
+
description: >-
|
|
12
|
+
The "tag" added to the image name for the test / lint image.
|
|
13
|
+
Remove this when you trigger by hand an image build and want it to use
|
|
14
|
+
the new built image with Git short sha tag (X icon on the right)!
|
|
15
|
+
value: "latest"
|
|
16
|
+
# RUN_DOCS_PUBLISH:
|
|
17
|
+
# description: >-
|
|
18
|
+
# Used in rules, if "true" and web triggered it generates the docs and
|
|
19
|
+
# publishes them!
|
|
20
|
+
# value: "false"
|
|
21
|
+
# options:
|
|
22
|
+
# - "false"
|
|
23
|
+
# - "true"
|
|
24
|
+
|
|
25
|
+
build-py-rf-image:
|
|
26
|
+
stage: build
|
|
27
|
+
image: docker:25
|
|
28
|
+
services:
|
|
29
|
+
- name: docker:25-dind
|
|
30
|
+
alias: docker
|
|
31
|
+
before_script:
|
|
32
|
+
- docker info
|
|
33
|
+
before_script:
|
|
34
|
+
- echo "Login to Gitlab container registry"
|
|
35
|
+
- echo "$CI_REGISTRY_PASSWORD" | docker login --username $CI_REGISTRY_USER --password-stdin $CI_REGISTRY
|
|
36
|
+
script:
|
|
37
|
+
- echo "Build container image..."
|
|
38
|
+
- ./cicd/build-py-rf-image.sh
|
|
39
|
+
- echo "Export IMAGE_TAG var to next stage!"
|
|
40
|
+
- echo "IMAGE_TAG=${CI_COMMIT_SHORT_SHA}" > image_tag.env
|
|
41
|
+
- echo "Build complete."
|
|
42
|
+
artifacts:
|
|
43
|
+
reports:
|
|
44
|
+
dotenv: image_tag.env
|
|
45
|
+
rules:
|
|
46
|
+
- if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
|
47
|
+
changes:
|
|
48
|
+
- .gitlab-ci.yml
|
|
49
|
+
- cicd/build-py-rf-image.sh
|
|
50
|
+
- container/**/*
|
|
51
|
+
- if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH
|
|
52
|
+
changes:
|
|
53
|
+
- .gitlab-ci.yml
|
|
54
|
+
- cicd/build-py-rf-image.sh
|
|
55
|
+
- container/**/*
|
|
56
|
+
- if: $CI_PIPELINE_SOURCE == "web" && $BUILD_IMAGE == "true"
|
|
57
|
+
when: always
|
|
58
|
+
|
|
59
|
+
run-pylint:
|
|
60
|
+
stage: test
|
|
61
|
+
image: "${CI_REGISTRY_IMAGE}/${IMAGE_NAME}:${IMAGE_TAG}"
|
|
62
|
+
rules:
|
|
63
|
+
- if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH
|
|
64
|
+
changes:
|
|
65
|
+
- src/**/*.py
|
|
66
|
+
- if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
|
67
|
+
changes:
|
|
68
|
+
- src/**/*.py
|
|
69
|
+
before_script:
|
|
70
|
+
- echo "Running PyLint."
|
|
71
|
+
script:
|
|
72
|
+
- ./cicd/run_pylint.sh
|
|
73
|
+
artifacts:
|
|
74
|
+
when: always
|
|
75
|
+
expire_in: 2 week
|
|
76
|
+
paths:
|
|
77
|
+
- pylint.out.*
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
run-pytest:
|
|
81
|
+
stage: test
|
|
82
|
+
image: "${CI_REGISTRY_IMAGE}/${IMAGE_NAME}:${IMAGE_TAG}"
|
|
83
|
+
rules:
|
|
84
|
+
- if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH
|
|
85
|
+
changes:
|
|
86
|
+
- src/**/*.py
|
|
87
|
+
- tests/test_*.py
|
|
88
|
+
- tests/conftest.py
|
|
89
|
+
- if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
|
90
|
+
changes:
|
|
91
|
+
- src/**/*.py
|
|
92
|
+
- tests/test_*.py
|
|
93
|
+
- tests/conftest.py
|
|
94
|
+
before_script:
|
|
95
|
+
- echo "Running PyTest."
|
|
96
|
+
script:
|
|
97
|
+
- ./cicd/run_pytest.sh
|
|
98
|
+
artifacts:
|
|
99
|
+
when: always
|
|
100
|
+
expire_in: 2 week
|
|
101
|
+
paths:
|
|
102
|
+
- pytest-junit.xml
|
|
103
|
+
reports:
|
|
104
|
+
junit: pytest-junit.xml
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
run-shellcheck:
|
|
108
|
+
stage: test
|
|
109
|
+
image: "${CI_REGISTRY_IMAGE}/${IMAGE_NAME}:${IMAGE_TAG}"
|
|
110
|
+
rules:
|
|
111
|
+
- if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH
|
|
112
|
+
changes:
|
|
113
|
+
- cicd/*.sh
|
|
114
|
+
- if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
|
115
|
+
changes:
|
|
116
|
+
- cicd/*.sh
|
|
117
|
+
before_script:
|
|
118
|
+
- echo "Running ShellCheck."
|
|
119
|
+
script:
|
|
120
|
+
- ./cicd/run_shellcheck.sh
|
|
121
|
+
|
|
122
|
+
# pages:
|
|
123
|
+
# stage: deploy
|
|
124
|
+
# image: "${CI_REGISTRY_IMAGE}/${IMAGE_NAME}:${IMAGE_TAG}"
|
|
125
|
+
# rules:
|
|
126
|
+
# - if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
|
127
|
+
# changes:
|
|
128
|
+
# - src/**/*.py
|
|
129
|
+
# - if: $CI_PIPELINE_SOURCE == "web" && $RUN_DOCS_PUBLISH == "true"
|
|
130
|
+
# when: always
|
|
131
|
+
# before_script:
|
|
132
|
+
# - echo "Running Docs generation and publishing..."
|
|
133
|
+
# script:
|
|
134
|
+
# - ./cicd/run_docs_pages.sh
|
|
135
|
+
# artifacts:
|
|
136
|
+
# paths:
|
|
137
|
+
# - public
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: pyrelukko
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Relukko client.
|
|
5
5
|
Author-email: Reto Zingg <g.d0b3rm4n@gmail.com>
|
|
6
6
|
Requires-Python: >=3.12
|
|
@@ -11,6 +11,7 @@ Classifier: License :: OSI Approved :: MIT License
|
|
|
11
11
|
Classifier: Topic :: Internet :: WWW/HTTP
|
|
12
12
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
13
13
|
Requires-Dist: requests >=2.32.3
|
|
14
|
+
Requires-Dist: websockets >= 13.1
|
|
14
15
|
Project-URL: Homepage, https://gitlab.com/relukko/pyrelukko
|
|
15
16
|
Project-URL: Issues, https://gitlab.com/relukko/pyrelukko/-/issues
|
|
16
17
|
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
|
|
3
|
+
set -e
|
|
4
|
+
|
|
5
|
+
SCRIPT_DIR=$(dirname "$(readlink -f "$0")")
|
|
6
|
+
REPO_DIR="${SCRIPT_DIR}/.."
|
|
7
|
+
CONTAINER_DIR="${REPO_DIR}/container"
|
|
8
|
+
CONTAINER_CMD="docker"
|
|
9
|
+
|
|
10
|
+
# IMAGE_NAME should normally come from .gitlab-ci.yml file,
|
|
11
|
+
# set default for local usage.
|
|
12
|
+
if [ -z "${IMAGE_NAME+x}" ]; then
|
|
13
|
+
IMAGE_NAME=py-rf-image-local
|
|
14
|
+
fi
|
|
15
|
+
|
|
16
|
+
cd "${CONTAINER_DIR}" || exit
|
|
17
|
+
|
|
18
|
+
${CONTAINER_CMD} build -t "${IMAGE_NAME}:latest" --file Containerfile .
|
|
19
|
+
|
|
20
|
+
${CONTAINER_CMD} images
|
|
21
|
+
|
|
22
|
+
if [ -n "${CI_REGISTRY_IMAGE}" ]; then
|
|
23
|
+
# In Gitlab
|
|
24
|
+
|
|
25
|
+
# Tag with Git commit short sha and push
|
|
26
|
+
IMAGE_WITH_GIT_SHA="${CI_REGISTRY_IMAGE}/${IMAGE_NAME}:${CI_COMMIT_SHORT_SHA}"
|
|
27
|
+
echo "IMAGE_WITH_GIT_SHA: ${IMAGE_WITH_GIT_SHA}"
|
|
28
|
+
|
|
29
|
+
${CONTAINER_CMD} tag "${IMAGE_NAME}:latest" "${IMAGE_WITH_GIT_SHA}"
|
|
30
|
+
${CONTAINER_CMD} push "${IMAGE_WITH_GIT_SHA}"
|
|
31
|
+
|
|
32
|
+
if [ "${CI_COMMIT_BRANCH}" = "${CI_DEFAULT_BRANCH}" ]; then
|
|
33
|
+
# We run in default branch, also tag with latest
|
|
34
|
+
# Tag with "latest" (overwrites last 'latest' in registry) and push
|
|
35
|
+
IMAGE_WITH_LATEST="${CI_REGISTRY_IMAGE}/${IMAGE_NAME}:latest"
|
|
36
|
+
|
|
37
|
+
echo "Tag image with as 'latest': ${IMAGE_WITH_LATEST}"
|
|
38
|
+
|
|
39
|
+
${CONTAINER_CMD} tag "${IMAGE_NAME}:latest" "${IMAGE_WITH_LATEST}"
|
|
40
|
+
${CONTAINER_CMD} push "${IMAGE_WITH_LATEST}"
|
|
41
|
+
fi
|
|
42
|
+
else
|
|
43
|
+
echo "Runs locally, no pushing!"
|
|
44
|
+
fi
|
|
45
|
+
|
|
46
|
+
cd -
|
|
47
|
+
|
|
48
|
+
# vim:set softtabstop=4 shiftwidth=4 tabstop=4 expandtab:
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
SCRIPT_DIR=$(dirname "$(readlink -f "$0")")
|
|
4
|
+
REPO_DIR="${SCRIPT_DIR}/.."
|
|
5
|
+
PUBLIC_DIR="${REPO_DIR}/public"
|
|
6
|
+
|
|
7
|
+
# Main script execution
|
|
8
|
+
main() {
|
|
9
|
+
mkdir -p "${PUBLIC_DIR}"
|
|
10
|
+
# libdoc --pythonpath ./src Relukko "${PUBLIC_DIR}/index.html"
|
|
11
|
+
echo "Not Implemented yet"
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
# Execute the main function
|
|
15
|
+
main
|
|
16
|
+
|
|
17
|
+
# vim:set softtabstop=4 shiftwidth=4 tabstop=4 expandtab:
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
SCRIPT_DIR=$(dirname "$(readlink -f "$0")")
|
|
4
|
+
REPO_DIR="${SCRIPT_DIR}/.."
|
|
5
|
+
|
|
6
|
+
# Main script execution
|
|
7
|
+
main() {
|
|
8
|
+
pylint --verbose \
|
|
9
|
+
--rcfile "${REPO_DIR}/pyproject.toml" \
|
|
10
|
+
--output-format=json:pylint.out.json,parseable:pylint.out.txt,text \
|
|
11
|
+
"${REPO_DIR}"
|
|
12
|
+
pylint_exit_code=$?
|
|
13
|
+
|
|
14
|
+
pylint-json2html \
|
|
15
|
+
-o "${REPO_DIR}/pylint.out.html" \
|
|
16
|
+
"${REPO_DIR}/pylint.out.json"
|
|
17
|
+
|
|
18
|
+
return ${pylint_exit_code}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
# Execute the main function
|
|
22
|
+
main
|
|
23
|
+
|
|
24
|
+
# vim:set softtabstop=4 shiftwidth=4 tabstop=4 expandtab:
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
SCRIPT_DIR=$(dirname "$(readlink -f "$0")")
|
|
4
|
+
REPO_DIR="${SCRIPT_DIR}/.."
|
|
5
|
+
|
|
6
|
+
# Main script execution
|
|
7
|
+
main() {
|
|
8
|
+
pytest --junit-xml "${REPO_DIR}/pytest-junit.xml"
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
# Execute the main function
|
|
12
|
+
main
|
|
13
|
+
|
|
14
|
+
# vim:set softtabstop=4 shiftwidth=4 tabstop=4 expandtab:
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
SCRIPT_DIR=$(dirname "$(readlink -f "$0")")
|
|
4
|
+
REPO_DIR="${SCRIPT_DIR}/.."
|
|
5
|
+
|
|
6
|
+
# Main script execution
|
|
7
|
+
main() {
|
|
8
|
+
shellcheck "${REPO_DIR}"/cicd/*.sh
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
# Execute the main function
|
|
12
|
+
main
|
|
13
|
+
|
|
14
|
+
# vim:set softtabstop=4 shiftwidth=4 tabstop=4 expandtab:
|
|
@@ -17,6 +17,7 @@ requires-python = ">=3.12"
|
|
|
17
17
|
dynamic = ["version", "description"]
|
|
18
18
|
dependencies = [
|
|
19
19
|
"requests >=2.32.3",
|
|
20
|
+
"websockets >= 13.1",
|
|
20
21
|
]
|
|
21
22
|
|
|
22
23
|
[tool.flit.sdist]
|
|
@@ -36,4 +37,25 @@ testpaths = [
|
|
|
36
37
|
]
|
|
37
38
|
pythonpath = [
|
|
38
39
|
"src",
|
|
39
|
-
]
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
[tool.tox]
|
|
43
|
+
requires = ["tox>=4.23"]
|
|
44
|
+
env_list = ["3.13", "3.12"]
|
|
45
|
+
|
|
46
|
+
[tool.tox.env_run_base]
|
|
47
|
+
description = "Run test under {base_python}"
|
|
48
|
+
commands = [["pytest"]]
|
|
49
|
+
deps = ["httpx", "pytest", "testcontainers"]
|
|
50
|
+
set_env = { VIRTUALENV_DISCOVERY = "pyenv" }
|
|
51
|
+
pass_env = [ "TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE", "DOCKER_HOST" ]
|
|
52
|
+
|
|
53
|
+
[tool.pylint.main]
|
|
54
|
+
# Files or directories to be skipped. They should be base names, not paths.
|
|
55
|
+
ignore = ["LICENSE", "pyproject.toml", "version.py",
|
|
56
|
+
"README.md", "demo.py", "conftest.py", ".tox"]
|
|
57
|
+
|
|
58
|
+
# Files or directories matching the regular expression patterns are skipped. The
|
|
59
|
+
# regex matches against base names, not paths. The default value ignores Emacs
|
|
60
|
+
# file locks
|
|
61
|
+
ignore-patterns = ["^\\.#", "^test_"]
|
|
@@ -151,7 +151,7 @@ class RelukkoClient:
|
|
|
151
151
|
|
|
152
152
|
def _setup_ws_url(self, ws_url: str) -> Url:
|
|
153
153
|
url = ws_url.replace("http", "ws", 1)
|
|
154
|
-
return parse_url(f"{url}/
|
|
154
|
+
return parse_url(f"{url}/ws/broadcast")
|
|
155
155
|
|
|
156
156
|
def _setup_base_url(self, base_url: Union[Url, str]) -> Url:
|
|
157
157
|
if isinstance(base_url, str):
|
|
@@ -1,24 +1,31 @@
|
|
|
1
|
+
# pylint: skip-file
|
|
2
|
+
"""
|
|
3
|
+
Testcontainers to be used in PyTests, for a fixture see tests/conftest.py
|
|
4
|
+
(relukko_backend):
|
|
5
|
+
|
|
6
|
+
@pytest.fixture(scope="session")
|
|
7
|
+
def relukko_backend():
|
|
8
|
+
with Network() as rl_net:
|
|
9
|
+
with RelukkoDbContainer(net=rl_net, initdb_dir=INITDB_DIR,
|
|
10
|
+
image="postgres:16", hostname="relukkodb") as _db:
|
|
11
|
+
db_url = "postgresql://relukko:relukko@relukkodb/relukko"
|
|
12
|
+
with RelukkoContainer(rl_net, db_url=db_url) as backend:
|
|
13
|
+
relukko = RelukkoClient(
|
|
14
|
+
base_url=backend.get_api_url(), api_key="somekey")
|
|
15
|
+
yield relukko, backend
|
|
16
|
+
"""
|
|
1
17
|
import socket
|
|
2
|
-
import ssl
|
|
3
|
-
import threading
|
|
4
18
|
from pathlib import Path
|
|
5
|
-
from typing import List
|
|
6
19
|
|
|
7
|
-
import pytest
|
|
8
20
|
from testcontainers.core.network import Network
|
|
9
21
|
from testcontainers.core.waiting_utils import wait_container_is_ready
|
|
10
22
|
from testcontainers.generic import ServerContainer
|
|
11
23
|
from testcontainers.postgres import PostgresContainer
|
|
12
24
|
|
|
13
|
-
from pyrelukko import RelukkoClient
|
|
14
|
-
|
|
15
|
-
SCRIPT_DIR = Path(__file__).parent.absolute()
|
|
16
|
-
INITDB_DIR = SCRIPT_DIR / "initdb.d"
|
|
17
|
-
|
|
18
25
|
|
|
19
26
|
class RelukkoContainer(ServerContainer):
|
|
20
27
|
def __init__(self, net: Network,
|
|
21
|
-
image="registry.gitlab.com/relukko/relukko:0.
|
|
28
|
+
image="registry.gitlab.com/relukko/relukko:0.10.0", db_url=None):
|
|
22
29
|
self.db_url = db_url
|
|
23
30
|
self.net = net
|
|
24
31
|
super(RelukkoContainer, self).__init__(image=image, port=3000)
|
|
@@ -39,12 +46,22 @@ class RelukkoContainer(ServerContainer):
|
|
|
39
46
|
|
|
40
47
|
|
|
41
48
|
class RelukkoDbContainer(PostgresContainer):
|
|
42
|
-
def __init__(
|
|
49
|
+
def __init__(
|
|
50
|
+
self, net: Network,
|
|
51
|
+
initdb_dir: Path,
|
|
52
|
+
image: str = "postgres:latest",
|
|
53
|
+
port: int = 5432,
|
|
54
|
+
username: str | None = None,
|
|
55
|
+
password: str | None = None,
|
|
56
|
+
dbname: str | None = None,
|
|
57
|
+
driver: str | None = "psycopg2",
|
|
58
|
+
**kwargs) -> None:
|
|
43
59
|
self.net = net
|
|
60
|
+
self.initdb_dir = initdb_dir
|
|
44
61
|
super().__init__(image, port, username, password, dbname, driver, **kwargs)
|
|
45
62
|
|
|
46
63
|
def _configure(self) -> None:
|
|
47
|
-
self.with_volume_mapping(
|
|
64
|
+
self.with_volume_mapping(self.initdb_dir, "/docker-entrypoint-initdb.d", "Z")
|
|
48
65
|
self.with_env("POSTGRES_USER", "relukko")
|
|
49
66
|
self.with_env("POSTGRES_PASSWORD", "relukko")
|
|
50
67
|
self.with_env("POSTGRES_DB", "relukko")
|
|
@@ -71,59 +88,3 @@ class RelukkoDbContainer(PostgresContainer):
|
|
|
71
88
|
buf = sock.recv(40)
|
|
72
89
|
if len(buf) == 0 and "SCRAM-SHA" not in buf:
|
|
73
90
|
raise ConnectionError
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
@pytest.fixture(scope="session")
|
|
77
|
-
def relukko_backend():
|
|
78
|
-
with Network() as rl_net:
|
|
79
|
-
with RelukkoDbContainer(net=rl_net,
|
|
80
|
-
image="postgres:16", hostname="relukkodb") as _db:
|
|
81
|
-
db_url = "postgresql://relukko:relukko@relukkodb/relukko"
|
|
82
|
-
with RelukkoContainer(rl_net, db_url=db_url) as backend:
|
|
83
|
-
relukko = RelukkoClient(
|
|
84
|
-
base_url=backend.get_api_url(), api_key="somekey")
|
|
85
|
-
yield relukko, backend
|
|
86
|
-
|
|
87
|
-
@pytest.fixture(scope="function")
|
|
88
|
-
def tls_listener():
|
|
89
|
-
|
|
90
|
-
certfile = SCRIPT_DIR / "cert" / "relukko.crt"
|
|
91
|
-
keyfile = SCRIPT_DIR / "cert" / "relukko.key"
|
|
92
|
-
|
|
93
|
-
def run_server(port_info: List, keep_running: threading.Event):
|
|
94
|
-
# Create a TCP socket
|
|
95
|
-
with socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) as sock:
|
|
96
|
-
sock.bind(("127.0.0.1", 0))
|
|
97
|
-
sock.listen(5) # Listen for incoming connections
|
|
98
|
-
|
|
99
|
-
_, assigned_port = sock.getsockname()
|
|
100
|
-
port_info.append(assigned_port)
|
|
101
|
-
|
|
102
|
-
# Wrap the socket with TLS
|
|
103
|
-
context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
|
|
104
|
-
context.load_cert_chain(certfile=certfile, keyfile=keyfile)
|
|
105
|
-
with context.wrap_socket(sock, server_side=True) as ssock:
|
|
106
|
-
|
|
107
|
-
ssock.settimeout(1)
|
|
108
|
-
|
|
109
|
-
while keep_running.is_set():
|
|
110
|
-
try:
|
|
111
|
-
client_socket, _ = ssock.accept()
|
|
112
|
-
client_socket.sendall(b"Hello, TLS Client!")
|
|
113
|
-
client_socket.close()
|
|
114
|
-
except Exception as _:
|
|
115
|
-
continue
|
|
116
|
-
|
|
117
|
-
port_info = []
|
|
118
|
-
keep_running = threading.Event()
|
|
119
|
-
keep_running.set()
|
|
120
|
-
thread = threading.Thread(target=run_server, args=(port_info, keep_running))
|
|
121
|
-
thread.start()
|
|
122
|
-
|
|
123
|
-
while not port_info:
|
|
124
|
-
pass
|
|
125
|
-
|
|
126
|
-
yield thread, port_info[0]
|
|
127
|
-
|
|
128
|
-
keep_running.clear()
|
|
129
|
-
thread.join()
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
# pylint: disable=all
|
|
2
|
-
__version__ = "0.
|
|
2
|
+
__version__ = "0.3.0"
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# How To
|
|
2
|
+
```
|
|
3
|
+
openssl req -subj '/CN=Relukko CA' -x509 -sha256 -days 7300 -noenc -newkey rsa:2048 -keyout rootCA.key -out rootCA.crt -addext keyUsage=critical,cRLSign,digitalSignature,keyCertSign
|
|
4
|
+
|
|
5
|
+
ln -s rootCA.crt "$(openssl x509 -hash -noout -in rootCA.crt).0"
|
|
6
|
+
|
|
7
|
+
openssl req -subj '/CN=relukko' -newkey rsa:2048 -noenc -keyout relukko.key -out relukko.csr -addext keyUsage=critical,digitalSignature,keyEncipherment,keyAgreement -addext extendedKeyUsage=critical,serverAuth
|
|
8
|
+
|
|
9
|
+
openssl x509 -req -CA rootCA.crt -CAkey rootCA.key -in relukko.csr -out relukko.crt -days 7299 -CAcreateserial
|
|
10
|
+
openssl x509 -inform PEM -in rootCA.crt -outform DER -out rootCA.der
|
|
11
|
+
```
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
|
2
|
+
MIIC9zCCAd+gAwIBAgIUXFQN+AOO7KFdiVNVFman8BLkRfkwDQYJKoZIhvcNAQEL
|
|
3
|
+
BQAwFTETMBEGA1UEAwwKUmVsdWtrbyBDQTAeFw0yNDExMTYyMTM5MTNaFw00NDEx
|
|
4
|
+
MTAyMTM5MTNaMBIxEDAOBgNVBAMMB3JlbHVra28wggEiMA0GCSqGSIb3DQEBAQUA
|
|
5
|
+
A4IBDwAwggEKAoIBAQCljry3blOWFJRdinzcH4XzRnvKlhhofBhtRsPH+pvjmrHO
|
|
6
|
+
v52rXj1XeHqXaEBevhNiN7lP5eg2UgOrs0KAVXYR2Na9Mxrh8ACX+IqeEJF9BKgO
|
|
7
|
+
4t2RvItDU3SWxV3dIYMasBhe/iDXDKKZd/jVOiluL9zuxo9ltDagZxc72jWMnvrO
|
|
8
|
+
lvlnZVEtH4n9i+hnx1daWRZG87DjO6d8I8F8nX6NTqJgBlrRm8jlcq2N/G8eHTFq
|
|
9
|
+
OrLY4xk4CF+aVExpJrEGprfhNkbE025tJIbGNM9Xv+W0sI/nhEwJdv4ifEP/b+44
|
|
10
|
+
n+KHrAurOboFYmRcoZ9Vn4C1KuYBvDOpgkwOs1wtAgMBAAGjQjBAMB0GA1UdDgQW
|
|
11
|
+
BBSy6DZz/N1PW1mkQY7HUj3Fz6yZOjAfBgNVHSMEGDAWgBT+sHazfmyczKb0BV6r
|
|
12
|
+
Z1JQ8Sfx9zANBgkqhkiG9w0BAQsFAAOCAQEAL1c1l3Azna1mh86haErurYk3EsiH
|
|
13
|
+
KDGprRubdB5qfpa2GdAkhitp9juKYdKGdw877eOl5z7AMeMWAA8WXQ3z7jkQkUhU
|
|
14
|
+
9wsZxNyHQajq6Lo9KsRxZiRKZX/fxagcnDem+4xTvzSlJoAT5p/CO5E31odwWkZN
|
|
15
|
+
bg79I36nk87opISXzNAbMBcbQEV5R8l4PzNGs/DcrLzTC66FKxHHzyih4mlBF5mS
|
|
16
|
+
/sMY5l9QNaJHKPK7fKZ5yxohkda7tDwtb5p0bbEUQlMeZIQ8r/go1b7/ppXXM5ei
|
|
17
|
+
mTDcwKgeOBgVujqhvgGXOKtcHVfkrqcID+qgDMxYd7XXE/icGF3zmnHwDQ==
|
|
18
|
+
-----END CERTIFICATE-----
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
-----BEGIN CERTIFICATE REQUEST-----
|
|
2
|
+
MIICkDCCAXgCAQAwEjEQMA4GA1UEAwwHcmVsdWtrbzCCASIwDQYJKoZIhvcNAQEB
|
|
3
|
+
BQADggEPADCCAQoCggEBAKWOvLduU5YUlF2KfNwfhfNGe8qWGGh8GG1Gw8f6m+Oa
|
|
4
|
+
sc6/natePVd4epdoQF6+E2I3uU/l6DZSA6uzQoBVdhHY1r0zGuHwAJf4ip4QkX0E
|
|
5
|
+
qA7i3ZG8i0NTdJbFXd0hgxqwGF7+INcMopl3+NU6KW4v3O7Gj2W0NqBnFzvaNYye
|
|
6
|
+
+s6W+WdlUS0fif2L6GfHV1pZFkbzsOM7p3wjwXydfo1OomAGWtGbyOVyrY38bx4d
|
|
7
|
+
MWo6stjjGTgIX5pUTGkmsQamt+E2RsTTbm0khsY0z1e/5bSwj+eETAl2/iJ8Q/9v
|
|
8
|
+
7jif4oesC6s5ugViZFyhn1WfgLUq5gG8M6mCTA6zXC0CAwEAAaA5MDcGCSqGSIb3
|
|
9
|
+
DQEJDjEqMCgwDgYDVR0PAQH/BAQDAgOoMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMB
|
|
10
|
+
MA0GCSqGSIb3DQEBCwUAA4IBAQBfEyjmGQtITqSsmoAQXEb11Cm/olsL5w6kEzgr
|
|
11
|
+
/0K8ASvDvW+3yJ3U9OBngvgh6iQCJjYaixb8NtQS7yVWYEqJoaA0Hp1q0QDmRS/l
|
|
12
|
+
MDLe2cILgbLQUKOf1jLtYsLG93Lb74HSGztjIIEoi3Wgrm5LLGc/cd28q8yw5c/j
|
|
13
|
+
s1EntUHeNWCYAUIRvwmt+1UPcc8EBHH2DugGz2verzARdvLWAajL5r9ZIJkkU0kY
|
|
14
|
+
fh5gnmVb6I6RtIXhWcXMUL9nBwzPCyJMd4cC/fueC+HxzLNhGldvVxj3cg7W57vR
|
|
15
|
+
QnbG/qcJYN5WGhoHrWIiI90GufG4jifVvyQeBC/vQcymRlAL
|
|
16
|
+
-----END CERTIFICATE REQUEST-----
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
-----BEGIN PRIVATE KEY-----
|
|
2
|
+
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCljry3blOWFJRd
|
|
3
|
+
inzcH4XzRnvKlhhofBhtRsPH+pvjmrHOv52rXj1XeHqXaEBevhNiN7lP5eg2UgOr
|
|
4
|
+
s0KAVXYR2Na9Mxrh8ACX+IqeEJF9BKgO4t2RvItDU3SWxV3dIYMasBhe/iDXDKKZ
|
|
5
|
+
d/jVOiluL9zuxo9ltDagZxc72jWMnvrOlvlnZVEtH4n9i+hnx1daWRZG87DjO6d8
|
|
6
|
+
I8F8nX6NTqJgBlrRm8jlcq2N/G8eHTFqOrLY4xk4CF+aVExpJrEGprfhNkbE025t
|
|
7
|
+
JIbGNM9Xv+W0sI/nhEwJdv4ifEP/b+44n+KHrAurOboFYmRcoZ9Vn4C1KuYBvDOp
|
|
8
|
+
gkwOs1wtAgMBAAECggEAAlGzzikAoqYfc7wywBDXLkXjClhpN2t6zYStTbhlvyQ4
|
|
9
|
+
9rgdJA9CC9JI+1gVqlrkyB5j0IOPg27i+y1PBblMwF0mf7t+/KiOEl+3R2J2VODZ
|
|
10
|
+
q6Dp110KB8bCdLGg/TqqZld02/D/S98ZY83eezqUZbH/cqVu6rVbaSQdWyeh7Bow
|
|
11
|
+
0rfnMV2537JpZVXzmVDGhlhKcgKjJFkzdW4Zv34lMSOCAAeByrIJtPEoQrJ7MQOj
|
|
12
|
+
9WpwYN+JN4YeP1FWXIG3Ah7ivFsCMZN9MEvXWMcEnAqSHhXXyRzJnJh4jBrigfM1
|
|
13
|
+
JeqDWgiMlCLP5Z2CwA8ahTnJZAYBJUfeFiNHBYC1sQKBgQDjoTCIlCr7UyLkxaJr
|
|
14
|
+
+IY65tl0jjWiEEvSZ9E+fqqesAsABGE8Po1ZEA7VZNViFf+4ttuBZLngmm/YVBvV
|
|
15
|
+
Ok+hf1HSDsvNhon7oIIa7cxlYGKH2Lf6tq8ovtt7IXRknInbbxh6+CoMm5Yc1KXp
|
|
16
|
+
XRCApfeBEoQdM2N2TRLUL+pPkQKBgQC6MQ9L3zMEr2yXrkyi2wmqBMMaSHCM5Zuh
|
|
17
|
+
ifQSFjJfkarh2y0KN7I73HR6KJVMVRVSmARi/QgN8tEvaXjCvVN67re4mDiZ5rC+
|
|
18
|
+
uIx903tkuKR4ruC1DE96NtsM1VNh1mUa2ndPULztpqPXhMCPspMltH4KbJHLo/iv
|
|
19
|
+
MaRHu2Ps3QKBgDGluIYxeuZyDYxEJtbRz8UNEKTBV6VPVJpBlnvA+Mm/r8aDLgoL
|
|
20
|
+
wpyIShP0+C16itno2Btysq/wPzC5t5BcNX4N3PSp0X20OGgva/EfqJL74MGsXQRL
|
|
21
|
+
0AxdBFXoyBAhrFe19WrssY8qaCVFpCIv8Cd/C2qVdUdBLBJjYRXylXJhAoGBAIPX
|
|
22
|
+
z5QTReYwbj3uD5hWcD5zRtBqsUAkKpM1w523GA5ycMWj1P3iOJSI4/XInQfDS+kD
|
|
23
|
+
ej+6GyT9Z0Eid3+2XtGzDmdpatMX9tnmhp1mzn6g/N30P2wUfob1JyGsQXILRebB
|
|
24
|
+
AjEo48+I64XmHBDlC6tsZr/s50SDJMqx5TliKT0FAoGAeqqC57jD2bj8Srs1Xa9p
|
|
25
|
+
JDZdS1DU/HthIngHTlud/rvOs2koVbIKRAHqxoBn2TCii6srFf7nHgLZ4iDOiyHF
|
|
26
|
+
eOb52GaYYKQNiSF77LUV0wdxmwwhm3h6hRYgt52nT1JVHH6rilZ64e2mevPX5H1T
|
|
27
|
+
CVvlmUZTRqXOidoSGMkO3sQ=
|
|
28
|
+
-----END PRIVATE KEY-----
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
|
2
|
+
MIIDGzCCAgOgAwIBAgIURXOBbBP+BSnq15fqso3+0Wkwt2swDQYJKoZIhvcNAQEL
|
|
3
|
+
BQAwFTETMBEGA1UEAwwKUmVsdWtrbyBDQTAeFw0yNDExMTYyMTM4MDVaFw00NDEx
|
|
4
|
+
MTEyMTM4MDVaMBUxEzARBgNVBAMMClJlbHVra28gQ0EwggEiMA0GCSqGSIb3DQEB
|
|
5
|
+
AQUAA4IBDwAwggEKAoIBAQDSDxl9hWmwLjTwJTHTH55HwNFKDMHXjiMmig2SMVCE
|
|
6
|
+
Y9fRYNms46CU+ulGGr8TMqXExb3J1ywE/HB8PBYoPKvAmPBHrquXT03A64fXl30q
|
|
7
|
+
IcnRHsJymxmUQV7yQxyfIXHT57NGUBauRhYSG8enbTNPbwByAdDAK6z0/41mMPbz
|
|
8
|
+
NFSXR89+ZkYf0CfKkvi/lPGdC80rS9LokLvDniVT50ir4CurhzndBP/U82nTMxvr
|
|
9
|
+
+Q2/TQmxbzeHOpa4ZCD2OBAHNXAGgV1qltnhvmbn+zYEK+vt9ZSb6lRUXWBWUvkn
|
|
10
|
+
TRCy3lMHu27q5h8Gzzxvi0Ct2lJ02poZG98QlXoAto+RAgMBAAGjYzBhMB0GA1Ud
|
|
11
|
+
DgQWBBT+sHazfmyczKb0BV6rZ1JQ8Sfx9zAfBgNVHSMEGDAWgBT+sHazfmyczKb0
|
|
12
|
+
BV6rZ1JQ8Sfx9zAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjANBgkq
|
|
13
|
+
hkiG9w0BAQsFAAOCAQEAASuRdyC8zk+FD3DO8vO3bpxiewqjSjQ0cE/t2XU3floV
|
|
14
|
+
r6Lp1bS+IjpeKIYzTg3+DdIMGub8piCh7JcU5ru1Ef0/xwtmCCUB/rOcYwfa2nHj
|
|
15
|
+
w7sc+njSnmdpISCyUV9Yxsqs+b2eQOMj/D28R5c2vf7QIYQMJivqa44TrMy57mJP
|
|
16
|
+
Tu+Y4stHZnfrnlggScfjn+dKjT58awyI0UVPr80YWZuSIDx26CREP41X8SJ5qRMN
|
|
17
|
+
K6KFXxN/PJhl/Y5axV/k/omRXd1FusUaC8yGk5E4zCs7cvbhG830FVIM19zbVSKg
|
|
18
|
+
SF6Dvx3mEWraHyBls9e+FYQIxB5FEJz9KGZdsOSjcQ==
|
|
19
|
+
-----END CERTIFICATE-----
|
|
Binary file
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
-----BEGIN PRIVATE KEY-----
|
|
2
|
+
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDSDxl9hWmwLjTw
|
|
3
|
+
JTHTH55HwNFKDMHXjiMmig2SMVCEY9fRYNms46CU+ulGGr8TMqXExb3J1ywE/HB8
|
|
4
|
+
PBYoPKvAmPBHrquXT03A64fXl30qIcnRHsJymxmUQV7yQxyfIXHT57NGUBauRhYS
|
|
5
|
+
G8enbTNPbwByAdDAK6z0/41mMPbzNFSXR89+ZkYf0CfKkvi/lPGdC80rS9LokLvD
|
|
6
|
+
niVT50ir4CurhzndBP/U82nTMxvr+Q2/TQmxbzeHOpa4ZCD2OBAHNXAGgV1qltnh
|
|
7
|
+
vmbn+zYEK+vt9ZSb6lRUXWBWUvknTRCy3lMHu27q5h8Gzzxvi0Ct2lJ02poZG98Q
|
|
8
|
+
lXoAto+RAgMBAAECggEAMnh7TOv5xWGMyah+LLZ7nszm3G5tQr/9lRx1f0tHB9A/
|
|
9
|
+
gijNlFtK8ZDJ7NSvVUsFhl5mp/EBvB71XfxH7JoLQGbe0LJYuy3MRk6xIG1fHvjo
|
|
10
|
+
V00XNlcq0bLVP8s9PMTZ5yrUKdBDatMfKXGwSnuT6QGIL1xdTlcQIvul+0hHhY58
|
|
11
|
+
+QGhB1HJASChg13OjLFwDhjiUqH1rkr8WjFspZZIm+SrwXUZTr6PYkF4E1cBcsWT
|
|
12
|
+
4PLCYKTZTKKr3D0UVa5ipOkp/ZIgWqRk1SACn84G1/AkmBpgv+0XgZz8kZ0Ju+9W
|
|
13
|
+
sPQV/fxXYpvnM/cvkHBAnvWDp4N3VX648zez7t+f2wKBgQD7guX7G5LdtLB/Crlx
|
|
14
|
+
uyAhkJyvc8Ttt11HCf2T/k6oqhATt9014NlJYQY2pVlyoyEQEb1Pe919ei+UpVVt
|
|
15
|
+
Ahaanw5xveOeGdjc2YJIqQV4mqc/daEXFfyLU+3dCzTKB4AXaIT09If5mna46Ou/
|
|
16
|
+
q1UW96cH/SqLC5Z3CyUhqwIvfwKBgQDVztB2P1KBH45lOT1oP/vPxYklUSokA/g+
|
|
17
|
+
VRw3pB8Wmm86fSxQ1lEvMViVf/tyrc+dpvNS+7quNzc0U/2+vpMcLjBkS9EpxAMy
|
|
18
|
+
hPDwZPnPXHKHnC/ET9WWO+wVaCTienGSVaTDTToeKo71Oesi1etHkLl0aWEMp8vo
|
|
19
|
+
gYGPM+/I7wKBgF0dNhXEPJhWF+3Aw60mcRvcFRYjzymO9DqjqTzMLsTkyTTzojMb
|
|
20
|
+
PnabNBixGK+HU2tGlgbCPdsBjHIEz96eok22Szuy6H0U5qPE5yYNZVgkMX0eCHiq
|
|
21
|
+
jCfs96gZSP7uze5cpLSnf1vaYs/Mc9MvFD5/i1g60zBNJvSFrMaNMC7zAoGBANNp
|
|
22
|
+
y+GQ3aEGNgRLZDgIRJN/DQyURCoWrsnb2KoAJClyjZd1HHPWZ7JVhfVV9qm/yjJm
|
|
23
|
+
WeXtOft4Z6LbhmWtBcPwvDMAcRNuWYcDw0bBYe6zyB/lxanFEzqZh+jm8MntLw32
|
|
24
|
+
l5PycgxQIsnC+omYoyxBo8/DP46HAO6n2Bdk0K6LAoGACP/UfrAg4Hyqi0jJcusl
|
|
25
|
+
Led0R3Fl0dw5i2N9PB++PUajt5LFhXXGHeOQnTlYbeJ/ioJgRS/k6W7MH43zP0me
|
|
26
|
+
wIYrVmazCewXwcIZiRv3ees73OsAVrn/yl17+u4KkVlXi0me8Opljl4/MS8026rE
|
|
27
|
+
iKMsJnco7XH/vaS9MrrrOvE=
|
|
28
|
+
-----END PRIVATE KEY-----
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
5C540DF8038EECA15D8953551666A7F012E445F9
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import socket
|
|
2
|
+
import ssl
|
|
3
|
+
import threading
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from typing import List
|
|
6
|
+
|
|
7
|
+
import pytest
|
|
8
|
+
from testcontainers.core.network import Network
|
|
9
|
+
|
|
10
|
+
from pyrelukko import RelukkoClient
|
|
11
|
+
from pyrelukko.testcontainers import RelukkoContainer, RelukkoDbContainer
|
|
12
|
+
|
|
13
|
+
SCRIPT_DIR = Path(__file__).parent.absolute()
|
|
14
|
+
INITDB_DIR = SCRIPT_DIR / "initdb.d"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@pytest.fixture(scope="session")
|
|
18
|
+
def relukko_backend():
|
|
19
|
+
with Network() as rl_net:
|
|
20
|
+
with RelukkoDbContainer(net=rl_net, initdb_dir=INITDB_DIR,
|
|
21
|
+
image="postgres:16", hostname="relukkodb") as _db:
|
|
22
|
+
db_url = "postgresql://relukko:relukko@relukkodb/relukko"
|
|
23
|
+
with RelukkoContainer(rl_net, db_url=db_url) as backend:
|
|
24
|
+
relukko = RelukkoClient(
|
|
25
|
+
base_url=backend.get_api_url(), api_key="somekey")
|
|
26
|
+
yield relukko, backend
|
|
27
|
+
|
|
28
|
+
@pytest.fixture(scope="function")
|
|
29
|
+
def tls_listener():
|
|
30
|
+
|
|
31
|
+
certfile = SCRIPT_DIR / "cert" / "relukko.crt"
|
|
32
|
+
keyfile = SCRIPT_DIR / "cert" / "relukko.key"
|
|
33
|
+
|
|
34
|
+
def run_server(port_info: List, keep_running: threading.Event):
|
|
35
|
+
# Create a TCP socket
|
|
36
|
+
with socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) as sock:
|
|
37
|
+
sock.bind(("127.0.0.1", 0))
|
|
38
|
+
sock.listen(5) # Listen for incoming connections
|
|
39
|
+
|
|
40
|
+
_, assigned_port = sock.getsockname()
|
|
41
|
+
port_info.append(assigned_port)
|
|
42
|
+
|
|
43
|
+
# Wrap the socket with TLS
|
|
44
|
+
context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
|
|
45
|
+
context.load_cert_chain(certfile=certfile, keyfile=keyfile)
|
|
46
|
+
with context.wrap_socket(sock, server_side=True) as ssock:
|
|
47
|
+
|
|
48
|
+
ssock.settimeout(1)
|
|
49
|
+
|
|
50
|
+
while keep_running.is_set():
|
|
51
|
+
try:
|
|
52
|
+
client_socket, _ = ssock.accept()
|
|
53
|
+
client_socket.sendall(b"Hello, TLS Client!")
|
|
54
|
+
client_socket.close()
|
|
55
|
+
except Exception as _:
|
|
56
|
+
continue
|
|
57
|
+
|
|
58
|
+
port_info = []
|
|
59
|
+
keep_running = threading.Event()
|
|
60
|
+
keep_running.set()
|
|
61
|
+
thread = threading.Thread(target=run_server, args=(port_info, keep_running))
|
|
62
|
+
thread.start()
|
|
63
|
+
|
|
64
|
+
while not port_info:
|
|
65
|
+
pass
|
|
66
|
+
|
|
67
|
+
yield thread, port_info[0]
|
|
68
|
+
|
|
69
|
+
keep_running.clear()
|
|
70
|
+
thread.join()
|
|
@@ -32,7 +32,7 @@ def _check_tls(ssl_ctx: ssl.SSLContext, port):
|
|
|
32
32
|
|
|
33
33
|
def _check_has_serial_no(ssl_ctx: ssl.SSLContext):
|
|
34
34
|
serial_numbers = [x["serialNumber"] for x in ssl_ctx.get_ca_certs()]
|
|
35
|
-
assert "
|
|
35
|
+
assert "4573816C13FE0529EAD797EAB28DFED16930B76B" in serial_numbers
|
|
36
36
|
|
|
37
37
|
|
|
38
38
|
def test_init_relukko_client():
|
|
@@ -152,7 +152,7 @@ def test_reconfigure_relukko_client():
|
|
|
152
152
|
"https://relukko", api_key="secret-key")
|
|
153
153
|
|
|
154
154
|
assert relukko.base_url == parse_url("https://relukko")
|
|
155
|
-
assert relukko.ws_url == parse_url("wss://relukko/
|
|
155
|
+
assert relukko.ws_url == parse_url("wss://relukko/ws/broadcast")
|
|
156
156
|
assert relukko.session.headers['X-api-Key'] == "secret-key"
|
|
157
157
|
|
|
158
158
|
default_ctx = ssl.create_default_context()
|
|
@@ -191,7 +191,7 @@ def test_reconfigure_relukko_client_extended():
|
|
|
191
191
|
assert relukko.session.trust_env == False
|
|
192
192
|
assert relukko.session.cookies == cookies
|
|
193
193
|
assert relukko.base_url == parse_url("https://relukko")
|
|
194
|
-
assert relukko.ws_url == parse_url("wss://relukko/
|
|
194
|
+
assert relukko.ws_url == parse_url("wss://relukko/ws/broadcast")
|
|
195
195
|
assert relukko.session.headers['X-api-Key'] == "my-API-key"
|
|
196
196
|
http_adapter: HTTPAdapter = relukko.session.adapters.get("http://")
|
|
197
197
|
assert http_adapter.max_retries.total == 100
|
|
@@ -233,7 +233,7 @@ def test_init_relukko_client_extented():
|
|
|
233
233
|
assert relukko.session.trust_env == False
|
|
234
234
|
assert relukko.session.cookies == cookies
|
|
235
235
|
assert relukko.base_url == parse_url("http://relukko")
|
|
236
|
-
assert relukko.ws_url == parse_url("ws://relukko/
|
|
236
|
+
assert relukko.ws_url == parse_url("ws://relukko/ws/broadcast")
|
|
237
237
|
assert relukko.session.headers['X-api-Key'] == "my-API-key"
|
|
238
238
|
assert relukko.ssl_ctx is None
|
|
239
239
|
http_adapter: HTTPAdapter = relukko.session.adapters.get("http://")
|
pyrelukko-0.2.0/.pylintrc.toml
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
[tool.pylint.main]
|
|
2
|
-
# Files or directories to be skipped. They should be base names, not paths.
|
|
3
|
-
ignore = ["LICENSE", "pyproject.toml", "version.py",
|
|
4
|
-
"README.md", "demo.py", "conftest.py"]
|
|
5
|
-
|
|
6
|
-
# Files or directories matching the regular expression patterns are skipped. The
|
|
7
|
-
# regex matches against base names, not paths. The default value ignores Emacs
|
|
8
|
-
# file locks
|
|
9
|
-
ignore-patterns = ["^\\.#", "^test_"]
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
# How To
|
|
2
|
-
```
|
|
3
|
-
openssl req -x509 -sha256 -days 7300 -noenc -newkey rsa:2048 -keyout rootCA.key -out rootCA.crt
|
|
4
|
-
ln -s rootCA.crt "$(openssl x509 -hash -noout -in rootCA.crt)"
|
|
5
|
-
openssl req -newkey rsa:2048 -noenc -keyout relukko.key -out relukko.csr
|
|
6
|
-
openssl x509 -req -CA rootCA.crt -CAkey rootCA.key -in relukko.csr -out relukko.crt -days 7299 -CAcreateserial
|
|
7
|
-
openssl x509 -inform PEM -in rootCA.crt -outform DER -out rootCA.der
|
|
8
|
-
```
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
-----BEGIN CERTIFICATE-----
|
|
2
|
-
MIIDeDCCAmCgAwIBAgIUIG2mO1IxfM3wqiLLFCO+6ubGdHswDQYJKoZIhvcNAQEL
|
|
3
|
-
BQAwVDELMAkGA1UEBhMCWFgxFTATBgNVBAcMDERlZmF1bHQgQ2l0eTEcMBoGA1UE
|
|
4
|
-
CgwTRGVmYXVsdCBDb21wYW55IEx0ZDEQMA4GA1UEAwwHUmVsdWtrbzAeFw0yNDEx
|
|
5
|
-
MTMxNTQxNTdaFw00NDExMDcxNTQxNTdaMFQxCzAJBgNVBAYTAlhYMRUwEwYDVQQH
|
|
6
|
-
DAxEZWZhdWx0IENpdHkxHDAaBgNVBAoME0RlZmF1bHQgQ29tcGFueSBMdGQxEDAO
|
|
7
|
-
BgNVBAMMB3JlbHVra28wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCr
|
|
8
|
-
89++zNQs+MG5opoCTWq/QxAJsr9Uul598XoQFXn1N/d/JOeSosy8BNvb1RXsr5sp
|
|
9
|
-
sNJbJEun6OPFtUoVczUtivS99XNchWPjEQ18w22aiLcwl/uOrdfxWj04yEfKmejN
|
|
10
|
-
ZXFrShhAWRGfc3fi2hD0Y5mtbS7T5iqaYzm4U5UDVFizVPnSgPFXMAiat/VQGvBF
|
|
11
|
-
cv5IpBjXOJGkLZTzmFlW61T6m+MJGXF59CLC6vL6QJCqQpSUWG9UM00R8L2pQ1b8
|
|
12
|
-
HLKYUuJ+vp4WVYwYyz769BNG4OG3IkdqIHKDFWBXFVmKaUkX9aAul4BOitKy4XFc
|
|
13
|
-
8eu653lbkVnRHb01RaP7AgMBAAGjQjBAMB0GA1UdDgQWBBSEFybZBM4O7khSofZl
|
|
14
|
-
0oAT+CSXEjAfBgNVHSMEGDAWgBRAo64Da82emF0q53wCdj4wbFTmMDANBgkqhkiG
|
|
15
|
-
9w0BAQsFAAOCAQEAs+zaKt8VqLoVT0OT24Oxyzc+/A0h4BYq3kYD11BaUJ6oKqQu
|
|
16
|
-
57FRKi0ZWxNSNCbzrwi6W+qNgIXtvSHWk4+BKxzqDVG6LCIuNn4bbvlQMGuTWctY
|
|
17
|
-
ndArPxdKvN9AXeCvam+5XKcA5OJY/naoho7fSoGh2Zgkq9HS7DlKxfBW2GEY0mp8
|
|
18
|
-
jeuxvBvh4xw/YuESVFbKedglaoNFf+aP44zL47Wn9QJcLqByGpTV472j238ObUFi
|
|
19
|
-
k47o+v4Qt7nkJDOcx7ic//uLTcb/1rv1SppYpKr3YJ5fLspzMMPpTQbkt2H8hLiZ
|
|
20
|
-
+1jj5GIoDgLi+/uxBgYQs78jEOIKkWO6EjwGUw==
|
|
21
|
-
-----END CERTIFICATE-----
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
-----BEGIN CERTIFICATE REQUEST-----
|
|
2
|
-
MIICmTCCAYECAQAwVDELMAkGA1UEBhMCWFgxFTATBgNVBAcMDERlZmF1bHQgQ2l0
|
|
3
|
-
eTEcMBoGA1UECgwTRGVmYXVsdCBDb21wYW55IEx0ZDEQMA4GA1UEAwwHcmVsdWtr
|
|
4
|
-
bzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKvz377M1Cz4wbmimgJN
|
|
5
|
-
ar9DEAmyv1S6Xn3xehAVefU3938k55KizLwE29vVFeyvmymw0lskS6fo48W1ShVz
|
|
6
|
-
NS2K9L31c1yFY+MRDXzDbZqItzCX+46t1/FaPTjIR8qZ6M1lcWtKGEBZEZ9zd+La
|
|
7
|
-
EPRjma1tLtPmKppjObhTlQNUWLNU+dKA8VcwCJq39VAa8EVy/kikGNc4kaQtlPOY
|
|
8
|
-
WVbrVPqb4wkZcXn0IsLq8vpAkKpClJRYb1QzTRHwvalDVvwcsphS4n6+nhZVjBjL
|
|
9
|
-
Pvr0E0bg4bciR2ogcoMVYFcVWYppSRf1oC6XgE6K0rLhcVzx67rneVuRWdEdvTVF
|
|
10
|
-
o/sCAwEAAaAAMA0GCSqGSIb3DQEBCwUAA4IBAQCHkmw8bBBI9pOrlCrJ2u3sGdlx
|
|
11
|
-
3ZbW/+kGdsQ8Odb/pIHkLLKpu5yNLEey/U4EZyWSNewYDUKfS2FIyMN2c38QAex6
|
|
12
|
-
1Y9qPK74RzUB68ki7XKtp+GAGqVb0axxRe0IuBwc9d5jl6zjltcpdutAIIgXcJgg
|
|
13
|
-
8QPnfpz7Skhjjm/duTVp0rurWsPztQdDpkrcY3c49vuTLA5uKwfa//cPAOmVGwqq
|
|
14
|
-
TMICj+0M2S+bgg9Ksph1IsDxxuIm1aa2EFnF5XRbJn9aOSdyfBkKoZz9ttgu1hP4
|
|
15
|
-
+hPe8S3ekUyJiZAglSI1qJOkpyw14EDIhwJvE9FG5eN/mU8wS1/GU+vhZWKN
|
|
16
|
-
-----END CERTIFICATE REQUEST-----
|
|
Binary file
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
-----BEGIN PRIVATE KEY-----
|
|
2
|
-
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCr89++zNQs+MG5
|
|
3
|
-
opoCTWq/QxAJsr9Uul598XoQFXn1N/d/JOeSosy8BNvb1RXsr5spsNJbJEun6OPF
|
|
4
|
-
tUoVczUtivS99XNchWPjEQ18w22aiLcwl/uOrdfxWj04yEfKmejNZXFrShhAWRGf
|
|
5
|
-
c3fi2hD0Y5mtbS7T5iqaYzm4U5UDVFizVPnSgPFXMAiat/VQGvBFcv5IpBjXOJGk
|
|
6
|
-
LZTzmFlW61T6m+MJGXF59CLC6vL6QJCqQpSUWG9UM00R8L2pQ1b8HLKYUuJ+vp4W
|
|
7
|
-
VYwYyz769BNG4OG3IkdqIHKDFWBXFVmKaUkX9aAul4BOitKy4XFc8eu653lbkVnR
|
|
8
|
-
Hb01RaP7AgMBAAECggEAF22KShjmkwavf7HfnDmyYMMWhSO//XTJBA1/DSrylg5d
|
|
9
|
-
NQsGVsxslZ9vLyP4sT9PJjPWbUmO2fPuo1TVy6y0jZ3K8Qi8rNnrEphpBzB/Qe38
|
|
10
|
-
+5dxfu6WUebIGZucFca42SdITTm9VSMYNhU0O98XLp0AEV4jYlvlPmoPhrAzSM50
|
|
11
|
-
lEIuriNhqHuqZhXN0jPYI1jZDS5JVi2PlbgyO1125BBMsCMLfhW+wcme/Y/VAySc
|
|
12
|
-
pNkvK3aHeWJUXEeVKuNfn5878PqeD6ZPjl9Hyq3lj6yOauIO/PCdIwm+2qjzrYsy
|
|
13
|
-
IBhjFFEoMGofgz+KV7olZu9by38ZzhW7nZGGe+zbgQKBgQDmFyzzxz3/BF7FKTXL
|
|
14
|
-
v6uVNkGpMGH8EQE1H+YJXTiSaqf/3ZrsXyBsbA6YBanKBXcY/F0PhQ7e/rjtqaGU
|
|
15
|
-
OtekNTHSgosdbJgVX88EjfIa4/rbZPUsX6qRJBuDVOCcCZC1PyFBT2ehKYlIPHS0
|
|
16
|
-
klbXo57pYzgDnzrYPr6UWbCZewKBgQC/UMGNvqJXszYZe3hjd9Ek9oSJMThfpfXn
|
|
17
|
-
opNhCNHKZ8+xqry602TqIwyStYc7elB57R547ZR4kttT8iM1E7ZOoLRPP0r/FjOS
|
|
18
|
-
scpCAk5ouVG9RZaUvTIbvzdEifEOt1Vf0RgIG3Y4DBqtotNoymqyT5wzuxyJQm1E
|
|
19
|
-
683UVIbXgQKBgQCLPJ0UTI7kwtVCxIRsbum7WuDzLHcvHW84obwIEKSKXgaaHJWC
|
|
20
|
-
0rIBSoauUkcEHLiMozMBkEiGg2iPUaaY197k3NfwhtT+kleaH6dcHzXSNgH5QCfp
|
|
21
|
-
mV7ThCEuIW/mnRc3xyMtrYqNiWAtGYCaQTBSQA6LN2KPNo1ajOWxSnFG/wKBgQC2
|
|
22
|
-
9rBksq/nV4ihjidwWSI3S1stKVlUgA9QW3a/EgQwol9K9pJPyeN019gqZljSVQOp
|
|
23
|
-
10+RLwUS2r/O5H8vP47WW3KVZ1593emsnUNlJXd/R9wYOvjrfpTxXEmqzpEvFb4c
|
|
24
|
-
SIfHGRxSNaE99b5hNVQc+23TO1rrGhAOHcVXDw92AQKBgQDCMEcIcwHx+ahVZbEb
|
|
25
|
-
bAyWLwYxQFRStmYKbYBtEMFW39atRmc0wdAG0my/0cUyHUIfWbHvP5oTfyAthV9G
|
|
26
|
-
8G0qBk5fPhh6hfNRFMb2j1AqnZ3CadoBZq2HelTTUqt4UgU9Y4iDco+4ew34Uw76
|
|
27
|
-
2ki1bKXiJKkJYlk14AMrzckDUQ==
|
|
28
|
-
-----END PRIVATE KEY-----
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
-----BEGIN CERTIFICATE-----
|
|
2
|
-
MIIDiTCCAnGgAwIBAgIUeLTh5JgTZlG0dbwtCICijkg1MWwwDQYJKoZIhvcNAQEL
|
|
3
|
-
BQAwVDELMAkGA1UEBhMCWFgxFTATBgNVBAcMDERlZmF1bHQgQ2l0eTEcMBoGA1UE
|
|
4
|
-
CgwTRGVmYXVsdCBDb21wYW55IEx0ZDEQMA4GA1UEAwwHUmVsdWtrbzAeFw0yNDEx
|
|
5
|
-
MTMxNTM3MDBaFw00NDExMDgxNTM3MDBaMFQxCzAJBgNVBAYTAlhYMRUwEwYDVQQH
|
|
6
|
-
DAxEZWZhdWx0IENpdHkxHDAaBgNVBAoME0RlZmF1bHQgQ29tcGFueSBMdGQxEDAO
|
|
7
|
-
BgNVBAMMB1JlbHVra28wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQD4
|
|
8
|
-
PWQPjCCXOvZYUDpYhZHR4Nw0ErkZEZWtPMyoBnyGkYwqK1SrHCcIYQL8C22dN1rn
|
|
9
|
-
VdFvCVH13fQHz1SJ/v3jkS+9IiOUDenXpZP/G0pprTbLGh33aaQU53EqvO1T2CAA
|
|
10
|
-
zIAVdme0cihOB+KL2A5bDzP9fu+c0ddn+N++ZgcqBHMYmZKIGJv5QZ+i+/1xrGqQ
|
|
11
|
-
/znwV7RuBGms8fxA3x4Y4ELUzIHMpbXbQn95qC9u7ee4odQ5KjR1M0oocPKOYBGa
|
|
12
|
-
/Dqnhd3Wx0lHR3No8HgC4TBfxruhs+NZtRyInOTFr99TWbBx+zrDvxecM/5j/AnH
|
|
13
|
-
WHka8xMQSxJUeoXtlFT/AgMBAAGjUzBRMB0GA1UdDgQWBBRAo64Da82emF0q53wC
|
|
14
|
-
dj4wbFTmMDAfBgNVHSMEGDAWgBRAo64Da82emF0q53wCdj4wbFTmMDAPBgNVHRMB
|
|
15
|
-
Af8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQACdVeJ/CnXpY4t568bQRxIr+t3
|
|
16
|
-
IqeIqJVg1nt6OaB/EJPJil/lvJD8bjO5W5uXAnbkv26i0Q89KFZH3xKFHRmL/zR+
|
|
17
|
-
0YPcbi3LmQ+NY6LtH1GtBlRiobROfSp8/GxTrGxqMGHHxBdY+v8lPiK1LHTE99ik
|
|
18
|
-
cl8qF+DQMGeliPQcg9rLgXagymEc9oS3OgxjL7Al4/P8bLkdC/hxk+cEUFCXUX4v
|
|
19
|
-
z/PAFnHwEeJPiiNYG+hpQQRloVncynEwhBr/pGGMdLGaFBje41kn9Ss2anc+YaiW
|
|
20
|
-
DyoDLuQkCcRrUvc2dCGMZs0KaCv8i61QWGNy8suGq6nrXW9A57JhS7ak8xg9
|
|
21
|
-
-----END CERTIFICATE-----
|
|
Binary file
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
-----BEGIN PRIVATE KEY-----
|
|
2
|
-
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQD4PWQPjCCXOvZY
|
|
3
|
-
UDpYhZHR4Nw0ErkZEZWtPMyoBnyGkYwqK1SrHCcIYQL8C22dN1rnVdFvCVH13fQH
|
|
4
|
-
z1SJ/v3jkS+9IiOUDenXpZP/G0pprTbLGh33aaQU53EqvO1T2CAAzIAVdme0cihO
|
|
5
|
-
B+KL2A5bDzP9fu+c0ddn+N++ZgcqBHMYmZKIGJv5QZ+i+/1xrGqQ/znwV7RuBGms
|
|
6
|
-
8fxA3x4Y4ELUzIHMpbXbQn95qC9u7ee4odQ5KjR1M0oocPKOYBGa/Dqnhd3Wx0lH
|
|
7
|
-
R3No8HgC4TBfxruhs+NZtRyInOTFr99TWbBx+zrDvxecM/5j/AnHWHka8xMQSxJU
|
|
8
|
-
eoXtlFT/AgMBAAECggEAeQhprIDsdP/dE4MOZ5G8XsHNa6BDWlsuCLivqi77cRsu
|
|
9
|
-
5XKaBhGkYFv4eg5SZAiUzF0Vz5cSPJf6vwISHHRUsqtbxNIL2ciM3sVO6t+SAQNg
|
|
10
|
-
x1cVDEgYJc8QaL+T0UD7nZgXzR8dgif0ydLjXL67hR9dAHhu+J2BcqKv6KPTU2LB
|
|
11
|
-
KWbCcLkY4PdCGwSNuvyPokc3Fo8U40Lm8tcWQ6sFV/+bv6+ShWhsb5Dx7sfVoijf
|
|
12
|
-
YikzFc7sEHb//nH2+C/FoCqneDPYl8lVH9zKYis4xWcA68bNwyfWpaQLXo32DKYq
|
|
13
|
-
rZxnwnawtU5b+t+TVp1DcCjOM3vaodeKI3Gqq5SjBQKBgQD/Sy33WOK+qelkvJxb
|
|
14
|
-
IcyP3U/ijNpWP3UidYGmmpTBP5UdaXyObX1G4nmfQjDad080jPpP/r350Tr0Xi2s
|
|
15
|
-
6wZBw0HoTZrZw5MQQKRQyh0Hg5VHHoHbD97UuLGGZ+Yc/hSWWfuDQHeV5Ami+VXD
|
|
16
|
-
TCYZGhtsjY9lUfUWYcsdcOA1fQKBgQD47TcVSC+3/8zKd2AAJeYrpx6wL/5X/4Zn
|
|
17
|
-
U0VeBxfF6MjQlu3avnwi6MxjkuB4KJAgWVHvJspJaS8ilIJN5qBsivphtfD0RV+d
|
|
18
|
-
UW9DCzoDUlU/AmNMD+stylgziSWoG9rzcY7P71izRE1tGGsgOXvZS5xUHzqWBwg6
|
|
19
|
-
MtYB4EQNKwKBgQCTUBVpKmBE9xTXbUKoD5vT1Df5mZ+PrzRvOvEiawa1cHQiMbGP
|
|
20
|
-
Gjz0/1CBBpfcKIaK42K5cFy9X++t/P5MTp4gqoRIgSd+yyz8buCiQc54fIRSMpdq
|
|
21
|
-
CgFiLGU8Eo4lYrQMgkXw2e1nj9vDsC698B331CnI/PKm26EaVjn3dh/anQKBgGxB
|
|
22
|
-
FWRu+TmmyBQA6EIIOVogmqr6pDz2xienQhKLOR57huGX0acAkhHIdiKTnIUE9vDq
|
|
23
|
-
h0Re9TgJw1LhjO1976RkqFDYBArnJJbQ9HcOqdMJ+kKlsjNA9QD773GyIitCueyH
|
|
24
|
-
JRluuH91o8pfBS+FcEPmqvy2fA8EzeIpe4JjWpTzAoGAQHoipuzDbhb02XMqioc+
|
|
25
|
-
UCsa6erj3kGrBUiFcvNutTG+oVq3qXOebOc9bCZcGHwsm0fgX5zk1XgY+IRfCWJY
|
|
26
|
-
X14DQfLMBi/vObDXH9BaoVvc50EPSBW0V5k2aXavJ6XelbBXSI33bzGb+5wAltI/
|
|
27
|
-
CFKf5ePEAi3jE69yYnTwbdc=
|
|
28
|
-
-----END PRIVATE KEY-----
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
206DA63B52317CCDF0AA22CB1423BEEAE6C6747B
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|