deft/notes/cisco_ft_securex_registration.org

217 lines
6.3 KiB
Org Mode
Raw Normal View History

:PROPERTIES:
:ID: 1208f09c-d37d-4e6b-9110-151f3c6b7d34
:END:
#+TITLE: Cisco FT SecureX Simplified Registration
#+Author: Yann Esposito
#+Date: [2021-12-07]
- tags :: [[id:299643a7-00e5-47fb-a987-3b9278e89da3][Auth]]
- source :: https://github.com/advthreat/response/issues/821
- dashboard :: https://github.com/advthreat/iroh/projects/32
* Technical Plan
** Support private email vs public emails
The solution is to use a blacklist of domains where any user could create
multiple email accounts pseudo-anonymously.
** Support, search admin with same email domain
We should be able given an email from a user, to find all the orgs for
which at least one of its admin has a matching domain name.
1. Most efficient: add an invisible field =email-domain= to all users. This
should be lower-case, and we will need a migration.
Doing this we could have a faster match than using string related queries.
Problems, users can login in the same user, with the same public email with
different emails.
This should be rare.
2. Search via text match.
The algorithm should look a bit like:
#+begin_src clojure
;; only when this is an unknown user
;; so a single approval will prevent the user to see this page.
(let [user-email ,,,
domain (string/replace user-email #".*@" "")
users (matching-admins domain) ;; returns a potentially big list of admin users
indexed-orgs (group-by :org-id users)]
(vals indexed-orgs))
#+end_src
Once this list of orgs is found.
We should also check the list of pending or rejected OrgAccessRequest for this user in
order to prevent the user to request access multiple time.
** Support Org request to admins
We need to create another Entity for access request to an Org.
#+begin_src clojure
(s/defschema OrgAccessRequest
(st/merge
{:id UUID
:idp-mapping IdPMapping
:user-email s/Str
:org-id s/Str
:status (s/enum :pending :accepted :rejected)
:created-at DateTime}
(st/optional-keys
{:user-name s/Str
:user-nick s/Str
:approved-by UserId
:approved-by-email UserEmail ;; email of the approver
:updated-at DateTime
:approval-message s/Str ;; optional free text approver can write to justify rejection
})))
#+end_src
When a user request access to an organization.
We should create this object in DB.
** Support the mechanism to create a new Org Access Request
After the UserIdentity is known and after retrieving the matching orgs, and
matching org access requests for this UserIdentity.
We should allow the user to create new OrgAccessRequest.
The way to do this is to create a new POST endpoint.
As the user will not have any JWT at this point.
We might probably build a "UserIdentity JWT" and trust it.
So the webpage could make request on behalf of a UserIdentity and not a User.
There should be an endpoint:
#+begin_src http
POST
/iroh/iroh-auth/request-org-access
Accept: application/json
Content-Type: application/json
User-Agent: ob-http
Authorization: Bearer ${user-jwt}
{"org-id":"the-id-of-the-org-the-user-request-access-to"}
#+end_src
After this call the user-jwt should contain the following informations;
- =idp-mapping=
- =user-email=
- all other metas, as user-name, user-nick, etc…
With this, and if every check matches:
1. There is a known active admin of this org with an email with the same domain name
2. The org is active
We should:
1. create a new =OrgAccessRequest= object in DB.
2. Send emails (see next section)
** Email Notification of Org Request Accesses
1. List all the admins of the requested org.
2.a. If there is fewer admins than a number that could be configured in the
node configuration. Then we send an email to all admins.
2.b. If there are more admins than this specific number, then we randomly
chose this maximal number of admins and send them an email notification.
*TODO* Have an email template (both HTML and Text)
** Org Requests CRUD API for Admins of the Orgs
There should be a CRUD API restricted to the ~admin/user-mgmt/org-requests~ scope:
- ~GET /iroh/user-mgmt/org-requests~ list pending org access requests
- ~GET /iroh/user-mgmt/org-requests/<id>~ read a single org access request
- ~POST /iroh/user-mgmt/org-requests/<id>/accept~ Grant the access
- ~POST /iroh/user-mgmt/org-requests/<id>/reject~ Reject the access
*** List
~GET /iroh/user-mgmt/org-requests~
If no parameter is provided, only list pending =OrgAccessRequests= of the org
of the caller.
Otherwise we could pass the query-parameter =status= with the following
value(s):
- =pending=
- =accepted=
- =rejected=
Note we should probably support duplicate statuses.
Ex:
~GET /iroh/user-mgmt/org-requests?status=accepted&status=pending~
*** Read
~GET /iroh/user-mgmt/org-requests/org-request-id~
Should returns a 404 if not found or the single Org Access Request object.
*** Accept the Org Access
~POST /iroh/user-mgmt/org-requests/<id>/accept~ Grant the access
The body should contain the role (either =admin= or =user=) with the following schema:
#+begin_src js
{"role":"admin"}
#+end_src
During the call, should:
1. Create a new user with:
#+begin_src clojure
{:user-id (gen-uuid)
:org-id (:org-id org-access-request)
:user-email (:user-email org-access-request)
:idp-mappings [(:idp-mapping org-access-request)]
:user-name (:user-name org-access-request)
:user-nick (:user-nick org-access-request)
:role (get-in request [:body :role])
:enabled? true
}
#+end_src
2. Send an email to user confirming his access was granted.
*TODO* have an email template
*** Reject the Org Access
~POST /iroh/user-mgmt/org-requests/<id>/reject~ Reject the access
The body should contain the role (either =admin= or =user=) with the following schema:
#+begin_src js
{"approval-message":"optional free text an admin could provide"}
#+end_src
This call should update the =OrgAccessRequest= object with the field
=approval-message= provided by the end user.
A great care should be made about removing every dangerous symbol in the
message in order to prevent any kind of attack from the approver to the
user requesting access. Typically, by putting an
2. Send an email to user confirming his access was granted.
*TODO* have an email template
** UI Revamp.
All the page shown during login are hosted in IROH.
So we should revamp all pages and we should probably, take great attention
to every shown webpage.
*TODO* have UI templates for every page of the workflow.