diff --git a/certificates.py b/certificates.py index 818fad4490806fcf5fb78d9a7318013c33d6a2a3..8b850e73a205e5b90c0815fc8e897cf82adbd82d 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 fda7df51825ac0c1243b5a834595b6dc022b25d0..5d8d0de9aca6ab623f0ab4fa6e6320c9fce7a71c 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 8cf5158de49b8007dfc4b8c098b50ea158c609a1..d95c09aa1e9d4e34a18ec4a23f69675df9e95901 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">