From 088211027a664676ca4f874c027311b2bf8b3fb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20Barto=C5=A1?= <bartos@cesnet.cz> Date: Sun, 18 Sep 2022 17:31:51 +0200 Subject: [PATCH] User's CN is always set equal to username There's no reason to make them different and this way it simplifies things (for example EasyRSA names certificate files by CN, but we usually identify user by its username). --- certificates.py | 8 ++++---- main.py | 27 ++++++++++++++------------- templates/add_edit_user.html | 1 - 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/certificates.py b/certificates.py index 818fad4..8b850e7 100644 --- a/certificates.py +++ b/certificates.py @@ -6,9 +6,9 @@ The CA is based on the Easy-RSA tool which is used to manage everything around t (all its config and data is in "<SOCTOOLS_BASE>/secrets/CA/"). When a new user is created, a private key and a certificate with his/her username as CN are generated by Easy-RSA -in the background (stored into ".../CA/issued/<username>.crt"). # TODO check +in the background (stored into ".../CA/issued/<CN>.crt"). The user is emailed with an URL containing a unique token allowing him/her to export and download the certificate and -private key in the .p12 format. # TODO other formats? +private key in the PKCS12 (.p12) and PEM (.key, .crt) formats. The linkage of these tokens to usernames is stored in a local file at: "<SOCTOOLS_BASE>/secrets/cert_access_tokens" Format: "token,username,expiration-time" per line @@ -72,7 +72,7 @@ class CertError(Exception): def generate_certificate(cn: str): """Generate a new x509 certificate for given user. - The certificate and associated private key are stored as file in the Easy-RSA directory: + The certificate and associated private key are stored as files in the Easy-RSA directory: - cert (pem): <CA_DIR>/issued/<cn>.crt - key (pem): <CA_DIR>/private/<cn>.key - both (p12): <CA_DIR>/private/<cn>.p12 @@ -174,7 +174,7 @@ def get_username_by_token(token: str) -> Optional[str]: # ========================= # Auxiliary functions -def _check_cn(cn): +def _check_cn(cn: str): """ Check CN validity - it must be possible to store it as a filename, without changing directory diff --git a/main.py b/main.py index fda7df5..5d8d0de 100644 --- a/main.py +++ b/main.py @@ -65,7 +65,7 @@ class UserAccount: email: str firstname: str lastname: str - cn: str + cn: str # preferably, CN should be the same as username (all users created via GUI satisfy it) dn: str kcid: Optional[str] = field(default=None) # keycloak ID ts_created: Optional[datetime] = field(default=None) # timezone-aware datetime in UTC @@ -85,7 +85,7 @@ class UserAccount: "lastName": self.lastname, "email": self.email, "attributes": { - "CN": [self.cn], # TODO: should be equal to username + "CN": [self.cn], "DN": [f"CN={self.cn}"] }, } @@ -241,11 +241,11 @@ def kc_delete_user(userid: str) -> None: class AddUserForm(FlaskForm): username = StringField("Username", validators=[DataRequired()]) - cn = StringField("Common name (CN)", validators=[DataRequired()]) + #cn = StringField("Common name (CN)", validators=[DataRequired()]) + # "CN" is set to "username", DN is constructed automatically from CN firstname = StringField("First name", validators=[]) lastname = StringField("Last name", validators=[]) email = StringField("Email", validators=[DataRequired(), Email()]) - # DN is constructed automatically from CN send_email = BooleanField("Automatically send email with an URL allowing the user to download his/her certificate.", default="checked", description="A certificate, signed by an internal SOCtools CA, is generated for each user. It allows " @@ -310,8 +310,9 @@ def add_user(): email=form_user.email.data, firstname=form_user.firstname.data, lastname=form_user.lastname.data, - cn=form_user.cn.data, - dn=f"CN={form_user.cn.data}") + # CN and DN are constructed from username + cn=form_user.username.data, + dn=f"CN={form_user.username.data}") # Generate certificate try: @@ -366,7 +367,7 @@ def add_user(): def edit_user(username: str): """Edit existing user. On GET show user details, on POST update user params with new values.""" try: - user = kc_get_user_by_name(username) # TODO catch exception + user = kc_get_user_by_name(username) except KeycloakError as e: flash(f'ERROR: {e}', "error") return redirect('/') @@ -377,12 +378,12 @@ def edit_user(username: str): if form_user.validate_on_submit(): # Form submitted and valid - perform account update new_user = UserAccount(username=form_user.username.data, - email=form_user.email.data, - firstname=form_user.firstname.data, - lastname=form_user.lastname.data, - cn=form_user.cn.data, - dn=f"CN={form_user.cn.data}", - kcid=keycloak_id) + email=form_user.email.data, + firstname=form_user.firstname.data, + lastname=form_user.lastname.data, + cn=form_user.username.data, + dn=f"CN={form_user.username.data}", + kcid=keycloak_id) # Keycloak try: kc_update_user(new_user) diff --git a/templates/add_edit_user.html b/templates/add_edit_user.html index 8cf5158..d95c09a 100644 --- a/templates/add_edit_user.html +++ b/templates/add_edit_user.html @@ -22,7 +22,6 @@ {{ form_user.username.label }} {{ form_user.username(size=20, readonly=True if user else False) }}<br> {{ form_user.firstname.label }} {{ form_user.firstname(size=20) }}<br> {{ form_user.lastname.label }} {{ form_user.lastname(size=20) }}<br> - {{ form_user.cn.label }} {{ form_user.cn(size=20) }}<br> {{ form_user.email.label }} {{ form_user.email(size=20) }}<br> {% if user %} <input type="submit" value="Update user"> -- GitLab