Skip to content

Commit

Permalink
Merge pull request #26 from kiwix/create-worker-with-public-key
Browse files Browse the repository at this point in the history
create worker using public key
  • Loading branch information
elfkuzco authored Aug 2, 2024
2 parents cb5bac0 + a88be90 commit 45a8704
Show file tree
Hide file tree
Showing 7 changed files with 36 additions and 30 deletions.
8 changes: 4 additions & 4 deletions backend/src/mirrors_qa_backend/cli/worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,15 @@ def get_country_mapping(country_codes: list[str]) -> dict[str, str]:


def create_worker(
worker_id: str, private_key_data: bytes, initial_country_codes: list[str]
worker_id: str, public_key_data: bytes, initial_country_codes: list[str]
):
"""Create a worker in the DB.
Assigns the countries for a worker to run tests from.
"""
country_mapping = get_country_mapping(initial_country_codes)
private_key = serialization.load_pem_private_key(
private_key_data, password=None
public_key = serialization.load_pem_public_key(
public_key_data
) # pyright: ignore[reportReturnType]

with Session.begin() as session:
Expand All @@ -48,7 +48,7 @@ def create_worker(
session,
worker_id,
initial_country_codes,
private_key, # pyright: ignore [reportGeneralTypeIssues, reportArgumentType]
public_key, # pyright: ignore [reportGeneralTypeIssues, reportArgumentType]
)

logger.info(f"Created worker {worker_id} successfully")
Expand Down
8 changes: 3 additions & 5 deletions backend/src/mirrors_qa_backend/db/worker.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import datetime

from cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey
from cryptography.hazmat.primitives.asymmetric.rsa import RSAPublicKey
from sqlalchemy import select
from sqlalchemy.orm import Session as OrmSession

from mirrors_qa_backend.cryptography import (
generate_public_key,
get_public_key_fingerprint,
serialize_public_key,
)
Expand All @@ -31,13 +30,12 @@ def create_worker(
session: OrmSession,
worker_id: str,
country_codes: list[str],
private_key: RSAPrivateKey,
public_key: RSAPublicKey,
) -> Worker:
"""Creates a worker using RSA private key."""
"""Creates a worker using RSA public key."""
if get_worker_or_none(session, worker_id) is not None:
raise DuplicatePrimaryKeyError(f"A worker with id {worker_id} already exists.")

public_key = generate_public_key(private_key)
public_key_pkcs8 = serialize_public_key(public_key).decode(encoding="ascii")
worker = Worker(
id=worker_id,
Expand Down
8 changes: 4 additions & 4 deletions backend/src/mirrors_qa_backend/entrypoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,12 @@ def main():
CREATE_WORKER_CLI, help="Create a new worker.", parents=[worker_parser]
)
create_worker_cli.add_argument(
"private_key_file",
metavar="private-key-file",
"public_key_file",
metavar="public-key-file",
type=argparse.FileType("r", encoding="ascii"),
nargs="?",
default=sys.stdin,
help="RSA private key file (default: stdin).",
help="RSA public key file (default: stdin).",
)

subparsers.add_parser(
Expand All @@ -115,7 +115,7 @@ def main():
try:
create_worker(
args.worker_id,
bytes(args.private_key_file.read(), encoding="ascii"),
bytes(args.public_key_file.read(), encoding="ascii"),
args.countries if args.countries else [],
)
except Exception as exc:
Expand Down
4 changes: 2 additions & 2 deletions backend/tests/cli/test_worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@
],
)
def test_create_worker(
private_key_data: bytes,
public_key_data: bytes,
worker_id: str,
country_codes: list[str],
expectation: Any,
):
with expectation:
create_worker(worker_id, private_key_data, country_codes)
create_worker(worker_id, public_key_data, country_codes)
17 changes: 10 additions & 7 deletions backend/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,16 +96,19 @@ def private_key() -> RSAPrivateKey:


@pytest.fixture(scope="session")
def public_key(private_key: RSAPrivateKey) -> RSAPublicKey:
return private_key.public_key()
def public_key_data(private_key: RSAPrivateKey) -> bytes:
"""Serialize public key using PEM format."""
return private_key.public_key().public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo,
)


@pytest.fixture(scope="session")
def private_key_data(private_key: RSAPrivateKey) -> bytes:
return private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.PKCS8,
encryption_algorithm=serialization.NoEncryption(),
def public_key(public_key_data: bytes) -> RSAPublicKey:
"""Create public key using PEM format."""
return serialization.load_pem_public_key( # pyright: ignore[reportReturnType]
public_key_data
)


Expand Down
6 changes: 3 additions & 3 deletions backend/tests/db/test_worker.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import pytest
from cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey
from cryptography.hazmat.primitives.asymmetric.rsa import RSAPublicKey
from sqlalchemy.orm import Session as OrmSession

from mirrors_qa_backend.db.exceptions import RecordDoesNotExistError
from mirrors_qa_backend.db.models import Country, Worker
from mirrors_qa_backend.db.worker import create_worker, get_worker


def test_create_worker(dbsession: OrmSession, private_key: RSAPrivateKey):
def test_create_worker(dbsession: OrmSession, public_key: RSAPublicKey):
worker_id = "test"
countries = [
Country(code="ng", name="Nigeria"),
Expand All @@ -19,7 +19,7 @@ def test_create_worker(dbsession: OrmSession, private_key: RSAPrivateKey):
dbsession,
worker_id=worker_id,
country_codes=[country.code for country in countries],
private_key=private_key,
public_key=public_key,
)
assert new_worker.id == worker_id
assert new_worker.pubkey_fingerprint != ""
Expand Down
15 changes: 10 additions & 5 deletions dev/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,19 +61,24 @@ docker compose --profile worker up --build
```sh
openssl genrsa -out id_rsa 2048
```
The key name `id_rsa` is used as a bind mount in the compose file.
The key name `id_rsa` is used as a bind mount in the compose file for the worker container.

- Generate a public key for creating the worker on the database.
```sh
openssl rsa -in id_rsa -pubout -out pubkey.pem
```

- Assuming the backend service is up (`docker compose up backend`), create a worker and assign them a list of countries to test for.
If no countries are provided, all available countries in the DB wiil be assigned to the worker. You can update the countries using `mirrors-qa-backend update-worker`.

In this example, we create a worker named `test` to test for mirrors in France, United States and Canada using the private key file
named `id_rsa`.
In this example, we create a worker named `test` to test for mirrors in France, United States and Canada using the public key file
named `pubkey.pem`.
```sh
docker exec -i mirrors-qa-backend mirrors-qa-backend create-worker --countries=us,fr,ca test < ./id_rsa
docker exec -i mirrors-qa-backend mirrors-qa-backend create-worker --countries=us,fr,ca test < ./pubkey.pem
```
- Set the name of the worker to the `WORKER_ID` variable in the `.env` file.

- Start the services with the worker enabled using `docker compose up --profile worker up --build`
- Start the services with the worker enabled using `docker compose --profile worker up --build`

## Environment variables

Expand Down

0 comments on commit 45a8704

Please sign in to comment.