Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
85 commits
Select commit Hold shift + click to select a range
76a64b8
Updates dockerfile for admin
kushaldas Sep 1, 2025
435698f
Adds default validity to trustmarktypes
kushaldas Sep 1, 2025
6dc98be
Reformats by ruff
kushaldas Sep 1, 2025
1311e7d
Adds correct function parameter
kushaldas Sep 1, 2025
32f3d2f
Adds initial /api/v1 API
kushaldas Sep 1, 2025
9337182
Fixes error handling in API
kushaldas Sep 1, 2025
f409ca8
Adds humanreadable as python dependency
kushaldas Sep 3, 2025
963b29d
Fixes format for linting
kushaldas Sep 3, 2025
466a28e
Adds router to API
kushaldas Sep 4, 2025
e14a82b
Adds pytest-django as dependency
kushaldas Sep 4, 2025
c97da83
Maps postgesql port to localhost for test running
kushaldas Sep 4, 2025
31d221f
Adds minimal python for rust testing
kushaldas Sep 4, 2025
9cbc48c
Uses dotenv for db host and port
kushaldas Sep 4, 2025
0077cd4
Adds pyproject.toml for admin
kushaldas Sep 4, 2025
78b2db6
Updates just commands
kushaldas Sep 4, 2025
c5cc6d9
Excludes db.json from gitignore
kushaldas Sep 4, 2025
e896484
Adds initial API tests
kushaldas Sep 4, 2025
19cc663
Updates tests action to use db
kushaldas Sep 4, 2025
3b6ea50
Reformats by ruff
kushaldas Sep 4, 2025
9857897
Adds keys for django ADMIN portal
kushaldas Sep 4, 2025
e56627b
Reformats code for linting
kushaldas Sep 4, 2025
ac58008
Renames tests Github action job
kushaldas Sep 4, 2025
9d436e3
Moves typings into admin
kushaldas Sep 4, 2025
64ecc81
Adds just command to run django test on container
kushaldas Sep 4, 2025
9da9f3c
Updates Python container
kushaldas Sep 4, 2025
ec91379
Updates requirements file
kushaldas Sep 4, 2025
c45dfe8
Adds TA_DEFAULTS for system
kushaldas Sep 4, 2025
2f4b787
Updates model based on new API
kushaldas Sep 4, 2025
fc418bb
Adds new api for creating trustmarktype
kushaldas Sep 4, 2025
b6711e0
Updates /trustmarktypes to get a list
kushaldas Sep 4, 2025
efd9ef1
Updates test for listing trustmarktypes
kushaldas Sep 4, 2025
6355aa9
Reformats by ruff
kushaldas Sep 4, 2025
4e5bfac
Updates test for list trustmarktypes
kushaldas Sep 4, 2025
0ccef92
Adds test for create trustmarktype
kushaldas Sep 4, 2025
f19e66e
Returns TrustMarkTypeOutScheme if create
kushaldas Sep 4, 2025
5bca327
Adds TrustMarkType creation tests
kushaldas Sep 4, 2025
53d694a
Filters DepricationWarning in tests
kushaldas Sep 5, 2025
5376a3c
Adds TrustMarkType update API
kushaldas Sep 5, 2025
9c81b24
Reformats by ruff
kushaldas Sep 7, 2025
f3f80df
Adds hget typing for redis
kushaldas Sep 9, 2025
13276f1
Adds TrustMark create API
kushaldas Sep 9, 2025
5ad9e54
Updates ty
kushaldas Sep 9, 2025
3aedef9
Adds test for double TrustMark
kushaldas Sep 9, 2025
2ab513f
Adds API endpoint to GET TrustMarkType
kushaldas Sep 9, 2025
b03eb17
Reformats by ruff
kushaldas Sep 9, 2025
1753f0e
Uses redis for test different than local
kushaldas Sep 9, 2025
28578dc
Adds redis dependency for tests
kushaldas Sep 9, 2025
af2b633
Sets redis location for tests
kushaldas Sep 9, 2025
3093904
Uses 6088 for redis for admin tests
kushaldas Sep 9, 2025
3856f67
Adds new columns to trustmark table
kushaldas Sep 15, 2025
a7c9fdc
Updates trustmark model for null
kushaldas Sep 15, 2025
a407902
Adds redis is admin container
kushaldas Sep 15, 2025
fd6edb4
Creates TrustMark via api
kushaldas Sep 15, 2025
b5b1b83
Reformats via ruff
kushaldas Sep 15, 2025
9d91544
Adds ALG for the JSON keys
kushaldas Sep 16, 2025
d6465ea
Adds API for trustmark lists
kushaldas Sep 16, 2025
89eaf22
Adds more options to justfile
kushaldas Sep 16, 2025
d5fd565
Adds trustmark renew and test
kushaldas Sep 16, 2025
230ef93
Fixes typo in docstring
kushaldas Sep 16, 2025
0ac6e87
Reformats based on ruff
kushaldas Sep 16, 2025
35ac3eb
Adds TrustMark update API and test
kushaldas Sep 17, 2025
71b3dbb
Lists TrustMarks per domain and tests
kushaldas Sep 17, 2025
5308281
Uses latest oidf_metadata_policy
kushaldas Sep 17, 2025
c972f9e
Fixes lint issues
kushaldas Sep 17, 2025
9629329
Runs ta in debug mode
kushaldas Sep 22, 2025
4bd204c
Uses a branch of oidfed_metadata_policy
kushaldas Sep 22, 2025
4c9fe20
Uses the new policy function
kushaldas Sep 22, 2025
83b4037
Adds more FIXME comments for inmor
kushaldas Sep 23, 2025
ea33d88
Adds example annotation for API docs
kushaldas Sep 23, 2025
a3c4592
Adds oidfpolicy as python dependency
kushaldas Sep 25, 2025
47578b6
Adds new entity model
kushaldas Sep 25, 2025
401e47a
Fetches and applies server policy on metadata
kushaldas Sep 25, 2025
71d6789
Adds example policy
kushaldas Sep 25, 2025
2564f56
Adds initial entity API
kushaldas Sep 25, 2025
326e6e3
Part of the code
kushaldas Sep 25, 2025
4dacdcc
Reformats via ruff
kushaldas Sep 25, 2025
8a44436
Disables the command for future
kushaldas Sep 25, 2025
c219365
Adds system's default valid_for for subordinate
kushaldas Sep 25, 2025
6b93468
Adds a future FIXME
kushaldas Sep 25, 2025
70a9858
Removes old views code
kushaldas Sep 25, 2025
4eba557
Updates on entity model
kushaldas Sep 25, 2025
6525393
Adds subordinate adding API
kushaldas Sep 25, 2025
dafb5dc
Adds more tests for entity.lib
kushaldas Sep 25, 2025
42c177c
Adds listing subordinates API
kushaldas Sep 25, 2025
14ede7c
Gets subordinate by id
kushaldas Sep 25, 2025
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
29 changes: 26 additions & 3 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,22 @@ on:
pull_request:

jobs:
lint:
tests:
runs-on: ubuntu-latest

services:
postgres:
image: postgres:14-alpine
env:
POSTGRES_HOST_AUTH_METHOD: trust
POSTGRES_USER: postgres
POSTGRES_DB: postgres
ports:
# will assign a random free host port
- 5432/tcp
# needed because the postgres container does not provide a healthcheck
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5

steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
Expand Down Expand Up @@ -37,5 +51,14 @@ jobs:
- name: Build TA appliation
run: cargo build

- name: Run tests for inmor
run: just test
- name: Run tests for inmor TA
run: just test-ta

- name: Run tests for inmor Admin API
run: just test-admin
env:
# use localhost for the host here because we are running the job on the VM.
# If we were running the job on in a container this would be postgres
DB_HOST: localhost
DB_PORT: ${{ job.services.postgres.ports[5432] }} # get randomly assigned published port
REDIS_LOCATION: "redis://localhost:6088/0"
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
/target
*.json
!db.json
!private.json
!public.json


# Byte-compiled / optimized / DLL files
Expand Down
5 changes: 2 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ tokio = { version = "1", features = ["full"] }
env_logger = "0.11.8"
log = "0.4.27"
base64 = "0.22"
oidfed_metadata_policy = "0.0.1"
oidfed_metadata_policy = { git = "https://github.com/SUNET/oidfed_metadata_policy", branch = "entity_policy"}
anyhow = "1.0.98"
toml = "0.9.0"
clap = { version = "4.5.41", features = ["derive"] }
Expand Down
6 changes: 3 additions & 3 deletions admin/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
FROM python:3.11
RUN apt update && apt install xmlsec1 -y
FROM python:3.13
RUN apt update && apt install xmlsec1 redis -y
ENV PYTHONUNBUFFERED=1
WORKDIR /code
#RUN bash .docker/scripts/setup-sass.sh
COPY ./requirements-dev.txt /code/
RUN pip install -r requirements-dev.txt
COPY . /code/
#COPY . /code/
1 change: 1 addition & 0 deletions admin/db.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[{"model": "trustmarks.trustmarktype", "pk": 1, "fields": {"tmtype": "https://sunet.se/does_not_exist_trustmark", "autorenew": true, "valid_for": 8760, "renewal_time": 48, "active": true}}, {"model": "trustmarks.trustmarktype", "pk": 2, "fields": {"tmtype": "https://example.com/trust_mark_type", "autorenew": true, "valid_for": 720, "renewal_time": 48, "active": true}}, {"model": "auth.permission", "pk": 1, "fields": {"name": "Can add trust mark type", "content_type": 1, "codename": "add_trustmarktype"}}, {"model": "auth.permission", "pk": 2, "fields": {"name": "Can change trust mark type", "content_type": 1, "codename": "change_trustmarktype"}}, {"model": "auth.permission", "pk": 3, "fields": {"name": "Can delete trust mark type", "content_type": 1, "codename": "delete_trustmarktype"}}, {"model": "auth.permission", "pk": 4, "fields": {"name": "Can view trust mark type", "content_type": 1, "codename": "view_trustmarktype"}}, {"model": "auth.permission", "pk": 5, "fields": {"name": "Can add trust mark", "content_type": 2, "codename": "add_trustmark"}}, {"model": "auth.permission", "pk": 6, "fields": {"name": "Can change trust mark", "content_type": 2, "codename": "change_trustmark"}}, {"model": "auth.permission", "pk": 7, "fields": {"name": "Can delete trust mark", "content_type": 2, "codename": "delete_trustmark"}}, {"model": "auth.permission", "pk": 8, "fields": {"name": "Can view trust mark", "content_type": 2, "codename": "view_trustmark"}}, {"model": "auth.permission", "pk": 9, "fields": {"name": "Can add subordinate", "content_type": 3, "codename": "add_subordinate"}}, {"model": "auth.permission", "pk": 10, "fields": {"name": "Can change subordinate", "content_type": 3, "codename": "change_subordinate"}}, {"model": "auth.permission", "pk": 11, "fields": {"name": "Can delete subordinate", "content_type": 3, "codename": "delete_subordinate"}}, {"model": "auth.permission", "pk": 12, "fields": {"name": "Can view subordinate", "content_type": 3, "codename": "view_subordinate"}}, {"model": "auth.permission", "pk": 13, "fields": {"name": "Can add log entry", "content_type": 4, "codename": "add_logentry"}}, {"model": "auth.permission", "pk": 14, "fields": {"name": "Can change log entry", "content_type": 4, "codename": "change_logentry"}}, {"model": "auth.permission", "pk": 15, "fields": {"name": "Can delete log entry", "content_type": 4, "codename": "delete_logentry"}}, {"model": "auth.permission", "pk": 16, "fields": {"name": "Can view log entry", "content_type": 4, "codename": "view_logentry"}}, {"model": "auth.permission", "pk": 17, "fields": {"name": "Can add permission", "content_type": 5, "codename": "add_permission"}}, {"model": "auth.permission", "pk": 18, "fields": {"name": "Can change permission", "content_type": 5, "codename": "change_permission"}}, {"model": "auth.permission", "pk": 19, "fields": {"name": "Can delete permission", "content_type": 5, "codename": "delete_permission"}}, {"model": "auth.permission", "pk": 20, "fields": {"name": "Can view permission", "content_type": 5, "codename": "view_permission"}}, {"model": "auth.permission", "pk": 21, "fields": {"name": "Can add group", "content_type": 6, "codename": "add_group"}}, {"model": "auth.permission", "pk": 22, "fields": {"name": "Can change group", "content_type": 6, "codename": "change_group"}}, {"model": "auth.permission", "pk": 23, "fields": {"name": "Can delete group", "content_type": 6, "codename": "delete_group"}}, {"model": "auth.permission", "pk": 24, "fields": {"name": "Can view group", "content_type": 6, "codename": "view_group"}}, {"model": "auth.permission", "pk": 25, "fields": {"name": "Can add user", "content_type": 7, "codename": "add_user"}}, {"model": "auth.permission", "pk": 26, "fields": {"name": "Can change user", "content_type": 7, "codename": "change_user"}}, {"model": "auth.permission", "pk": 27, "fields": {"name": "Can delete user", "content_type": 7, "codename": "delete_user"}}, {"model": "auth.permission", "pk": 28, "fields": {"name": "Can view user", "content_type": 7, "codename": "view_user"}}, {"model": "auth.permission", "pk": 29, "fields": {"name": "Can add content type", "content_type": 8, "codename": "add_contenttype"}}, {"model": "auth.permission", "pk": 30, "fields": {"name": "Can change content type", "content_type": 8, "codename": "change_contenttype"}}, {"model": "auth.permission", "pk": 31, "fields": {"name": "Can delete content type", "content_type": 8, "codename": "delete_contenttype"}}, {"model": "auth.permission", "pk": 32, "fields": {"name": "Can view content type", "content_type": 8, "codename": "view_contenttype"}}, {"model": "auth.permission", "pk": 33, "fields": {"name": "Can add session", "content_type": 9, "codename": "add_session"}}, {"model": "auth.permission", "pk": 34, "fields": {"name": "Can change session", "content_type": 9, "codename": "change_session"}}, {"model": "auth.permission", "pk": 35, "fields": {"name": "Can delete session", "content_type": 9, "codename": "delete_session"}}, {"model": "auth.permission", "pk": 36, "fields": {"name": "Can view session", "content_type": 9, "codename": "view_session"}}, {"model": "contenttypes.contenttype", "pk": 1, "fields": {"app_label": "trustmarks", "model": "trustmarktype"}}, {"model": "contenttypes.contenttype", "pk": 2, "fields": {"app_label": "trustmarks", "model": "trustmark"}}, {"model": "contenttypes.contenttype", "pk": 3, "fields": {"app_label": "entities", "model": "subordinate"}}, {"model": "contenttypes.contenttype", "pk": 4, "fields": {"app_label": "admin", "model": "logentry"}}, {"model": "contenttypes.contenttype", "pk": 5, "fields": {"app_label": "auth", "model": "permission"}}, {"model": "contenttypes.contenttype", "pk": 6, "fields": {"app_label": "auth", "model": "group"}}, {"model": "contenttypes.contenttype", "pk": 7, "fields": {"app_label": "auth", "model": "user"}}, {"model": "contenttypes.contenttype", "pk": 8, "fields": {"app_label": "contenttypes", "model": "contenttype"}}, {"model": "contenttypes.contenttype", "pk": 9, "fields": {"app_label": "sessions", "model": "session"}}]
131 changes: 90 additions & 41 deletions admin/entities/lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@

import httpx
from django.conf import settings
from jwcrypto import jwt
from jwcrypto import jwk, jwt
from jwcrypto.jwk import JWK, JWKSet
from jwcrypto.jwt import JWT
from oidfpolicy import apply_policy, merge_policies
from pydantic import BaseModel

from redis import Redis

INSIDE_CONTAINER = os.environ.get("INSIDE_CONTAINER")
Expand All @@ -22,78 +22,127 @@ class SubordinateRequest(BaseModel):
entity: str


def add_subordinate(entity_id: str, r: Redis) -> str:
def fetch_entity_configuration(
entityid: str, official_metadata: dict[Any, Any], keys: dict[Any, Any] | None = None
) -> tuple[JWT, JWKSet, str]:
"""Fetches the entity configuration and returns verified JWT.


:args entityid: str the entity_id

:returns: Tuple of JWT representation and JWKSet, and jwt in str format
"""
# Let us get the JWKS
if keys is not None:
keys_str = json.dumps(keys)
keyset = jwk.JWKSet.from_json(keys_str)
elif "openid_relying_party" in official_metadata:
keys_str = json.dumps(official_metadata["openid_relying_party"]["jwks"])
keyset = jwk.JWKSet.from_json(keys_str)
elif "openid_provider" in official_metadata:
keys_str = json.dumps(official_metadata["openid_provider"]["jwks"])
keyset = jwk.JWKSet.from_json(keys_str)
else:
raise ValueError("Missing JWKS")
resp = httpx.get(f"{entityid}/.well-known/openid-federation")
text = resp.text
jwt_net: JWT = jwt.JWT(jwt=text, key=keyset)
return jwt_net, keyset, text


def merge_our_policy_ontop_subpolicy(subpolicy: dict[Any, Any]) -> str | None:
"To verify that we can succesfully merge policies."
if settings.POLICY_DOCUMENT.get("metadata_policy", {}):
merged_policy = merge_policies(
json.dumps(settings.POLICY_DOCUMENT.get("metadata_policy", {})), json.dumps(subpolicy)
)
return merged_policy
return None


def apply_server_policy(metadata: str):
"Verifies that we can apply our policy on the metadata."
m = apply_policy(json.dumps(settings.POLICY_DOCUMENT), metadata)
return m


def create_subordinate_statement(
entityid: str, keyset: JWKSet, now: datetime, exp: datetime
) -> str:
"""Creates a signed Subordinate Statement"""
# This is the data we care for now
sub_data = {"iss": settings.TA_DOMAIN}
sub_data["sub"] = entityid
# Add any server metadata if available
if settings.POLICY_DOCUMENT.get("metadata", {}):
sub_data["metadata"] = settings.POLICY_DOCUMENT.get("metadata")
# This is the metadata policy of TA defined in the settings.py
if settings.POLICY_DOCUMENT.get("metadata_policy", {}):
sub_data["metadata_policy"] = settings.POLICY_DOCUMENT.get("metadata_policy")
# creation time
sub_data["iat"] = now.timestamp()
# Expiry time of the subordinate statement
sub_data["exp"] = exp.timestamp()
# The is the subordinate's keyset
sub_data["jwks"] = keyset.export(private_keys=False)

key = settings.SIGNING_PRIVATE_KEY

# TODO: fix the alg value for other types of keys of TA/I
token = jwt.JWT(
header={"alg": "RS256", "kid": key.kid, "typ": "entity-statement+jwt"}, claims=sub_data
)
token.make_signed_token(key)
token_data = token.serialize()
return token_data


def update_redis_with_subordinate(
entity_id: str, jwt_text: str, sub_metadata: dict[str, Any], signed_statement: str, r: Redis
) -> None:
"""Adds a new subordinate to the federation.

This creates a subordinate statement by the TA as iss and adds the metadata of the entity (subordinate).
https://openid.net/specs/openid-federation-1_0.html#name-fetch-subordinate-statement-

:args entity_id: The entity_id to be added
:args keyset: The keyset of the subordinate
:args jwt_text: The str version of the JWT of the subordinate.
:args sub_metadata: The subordinate's metadata
:args singed_statement: The signed subordinate statement.
:args r: Redis class from Django

:returns: String version of the signed JWT
"""
resp = httpx.get(f"{entity_id}/.well-known/openid-federation")
text = resp.text
jwt_net: JWT = jwt.JWT.from_jose_token(text)
# FIXME: In future we will need the proper key to verify the signature and use only
# validated contain.
payload = json.loads(jwt_net.token.objects.get("payload").decode("utf-8"))

# TODO: Verify that the authority_hints matches with the inmor's entity_id.

# This is the data we care for now
sub_data = {"iss": settings.TA_DOMAIN}
# We don't need this for subordinate statement
# sub_data["authority_hints"] = payload.get("authority_hints")
metadata = payload.get("metadata")
if metadata:
if sub_metadata:
# We should mark what kind of entity it is, for the /list endpoint
# The treewalking code will visit the entity later, but this is to make sure
# that we have some information storied at the first check.
if "openid_relying_party" in metadata:
if "openid_relying_party" in sub_metadata:
# Mweans RP
_ = r.sadd("inmor:rp", entity_id)
logger.info(f"{entity_id} added as RP to memory database.")
elif "openid_provider" in metadata:
elif "openid_provider" in sub_metadata:
# Means OP
_ = r.sadd("inmor:op", entity_id)
logger.info(f"{entity_id} added as OP to memory database.")
else: # means "federation_entity" in metadata:
# Means we have a TA/IA
_ = r.sadd("inmor:taia", entity_id)

sub_data["metadata"] = metadata

# This is the metadata policy of TA defined in the settings.py
sub_data["metadata_policy "] = settings.METADATA_POLICY

# We don't need trustmarks for the subordinate statements.
# We don't need trustmarks for the subordinate statements.
# trust_marks = payload.get("trust_marks")
# if trust_marks:
# sub_data["trust_marks"] = trust_marks

# Default we keep the same expiry of the subordinate entity configuration
sub_data["exp"] = payload.get("exp")
sub_data["sub"] = payload.get("sub")
# creation time
sub_data["iat"] = datetime.now().timestamp()
sub_data["jwks"] = [settings.SIGNING_PUBLIC_KEY]

key = settings.SIGNING_PRIVATE_KEY

# TODO: fix the alg value for other types of keys of TA/I
token = jwt.JWT(
header={"alg": "RS256", "kid": key.kid, "typ": "entity-statement+jwt"}, claims=sub_data
)
token.make_signed_token(key)
token_data = token.serialize()
# Now we should set it in the redis
_ = r.hset("inmor:subordinates", sub_data["sub"], token_data)
_ = r.hset("inmor:subordinates:jwt", sub_data["sub"], text)
_ = r.hset("inmor:subordinates", entity_id, signed_statement)
_ = r.hset("inmor:subordinates:jwt", entity_id, jwt_text)
# Add the entity in the queue for walking the tree (if any)
_ = r.lpush("inmor:newsubordinate", entity_id)
return token_data


def self_validate(token: jwt.JWT) -> dict[str, Any]:
Expand Down
4 changes: 2 additions & 2 deletions admin/entities/management/commands/readd_subordinates.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import djclick as click
from django_redis import get_redis_connection
from entities.lib import add_subordinate

from entities.models import Subordinate


Expand All @@ -13,5 +13,5 @@ def command():
subs = Subordinate.objects.all()
for sub in subs:
# Means we can reissue this one
add_subordinate(sub.entityid, con)
# TODO: reissue and save here
click.secho(f"Reissued {sub.entityid}")
13 changes: 11 additions & 2 deletions admin/entities/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Generated by Django 5.2.3 on 2025-07-04 14:01
# Generated by Django 5.2.6 on 2025-09-25 15:47

import django.db.models.functions.datetime
from django.db import migrations, models
Expand Down Expand Up @@ -27,10 +27,19 @@ class Migration(migrations.Migration):
models.DateTimeField(db_default=django.db.models.functions.datetime.Now()),
),
("entityid", models.CharField(unique=True)),
("valid_for", models.IntegerField(default=8760)),
("autorenew", models.BooleanField(default=False)),
("metadata", models.CharField()),
("jwks", models.CharField(null=True)),
("required_trustmarks", models.CharField(null=True)),
("active", models.BooleanField(default=True)),
("statement", models.CharField(null=True)),
],
options={
"indexes": [
models.Index(fields=["entityid"], name="entities_su_entityi_0bfba0_idx")
models.Index(fields=["entityid"], name="entities_su_entityi_0bfba0_idx"),
models.Index(fields=["valid_for"], name="entities_su_valid_f_e25cdc_idx"),
models.Index(fields=["autorenew"], name="entities_su_autoren_f0d71e_idx"),
],
},
),
Expand Down
9 changes: 9 additions & 0 deletions admin/entities/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,20 @@ class Subordinate(models.Model):
id: int
added = models.DateTimeField(db_default=Now())
entityid = models.CharField(unique=True)
valid_for = models.IntegerField(default=8760) # Means 365 days
autorenew = models.BooleanField(default=False)
metadata = models.CharField()
jwks = models.CharField(null=True)
required_trustmarks = models.CharField(null=True)
active = models.BooleanField(default=True)
statement = models.CharField(null=True)

def __str__(self):
return self.entityid

class Meta:
indexes = [
models.Index(fields=["entityid"]),
models.Index(fields=["valid_for"]),
models.Index(fields=["autorenew"]),
]
10 changes: 1 addition & 9 deletions admin/entities/urls.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,3 @@
from django.urls import path

from . import views

app_name = "entities"

urlpatterns = [
path("", views.index, name="index"),
path("add/", views.add_subordinate_entity, name="add"),
path("list/", views.list_subordinates, name="list"),
]
urlpatterns = []
Loading
Loading