deft/notes/cisco_ft_securex_registration.org
2021-12-22 15:51:54 +01:00

8.4 KiB

Cisco FT SecureX Simplified Registration

tags
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

Estimate: 1 release cycles after the list is provided.

The solution is to use a blacklist of domains where any user could create multiple email accounts pseudo-anonymously.

Details: https://github.com/advthreat/response/issues/979

Question is about where to put the list?

Estimate: 1 release cycles depends on ops

I suggest the list should be a single file in tenzin-config that should be used on all environments.

Support allow-list exceptions for some Cisco user.

Estimate: 1 release cycles after the list is provided.

Typically we should allow some users with an email like some-user+XXX@gmail.com

Support, search admin with same email domain

Estimate: 1 release cycle. Note: Work in progress

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.

  1. Search via text match.

The algorithm should look a bit like:

;; 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))

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

Estimate: 4 release cycles

We need to create another Entity for access request to an Org.

(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
     :approver-id UserId
     :approver-email UserEmail ;; email of the approver
     :updated-at DateTime
     })))

When a user request access to an organization. We should create this object in DB.

Login Account Management Page

Estimate: 4 release cycles

See Figma: https://www.figma.com/file/Bz3m25kpWXpdct7AnhmNsW/SXSO-Registeration?node-id=759%3A5926

We should change the login flow, so the user might see an intermediate login account management page. On this login account management page the user should see:

  1. account selection
  2. pending invites
  3. matching orgs

To give an idea here is an example of what it will look like:

Select Account:
  - account-1
  - account-2
Pending Invites:
  - invite for org-1
  - invite for org-2 (expired) [ask for renewal]
Matching Orgs:
  - org-4
  - org-5

Behavior

If the user is only part of 1 org, and has no invite, and not matching org. He should not see that page and be redirected directly to his account.

If the user is only part of 1 org, and has matching org, it is not clear if we should display that page?

If all other cases, the "login account management page"

Note also that if we have a pending invite on a matching email domain org. The pending invite should take the priority when displaying the org.

Question
  1. pending invite expired
  2. matching org

What should we present the user?

  1. renew invite (send an email to the inviter)
  2. request access to the org
  3. both 1 and 2

Technical details

When the user see this page, we know the UserIdentity only.

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:

POST
/iroh/iroh-auth/request-org-access

Accept: application/json
Content-Type: application/json
User-Agent: ob-http
Authorization: Bearer ${user-identity-jwt}

{"org-id":"the-id-of-the-org-the-user-request-access-to"}

After this call the user-identity-jwt should contain enough data to retrieve:

  • 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

Estimate: 4 release cycle after email+html templates

  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)

Notes

Need to be able to trigger a new request to join after 7 days.

Org Requests CRUD API for Admins of the Orgs

Estimate: 3 release cycle after mail templates + text

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:

{"role":"admin"}

During the call, should:

  1. Create a new user with:
{: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
 }
  1. Send an email to user confirming his access was granted.

TODO have an email template + text.

Reject the Org Access

POST /iroh/user-mgmt/org-requests/<id>/reject Reject the access

This call should update the OrgAccessRequest object by patching with:

{:udpated-at (now)
 :approver-id (get-in req [:identity :user :id])
 :approver-email (get-in req [:identity :user :email])
 :status :rejected}

Then send an email to user confirming his access was denied.

TODO have an email template + text.

UI Revamp.

Estimate: 2 release cycle after email+html templates

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. Typically, the look and feel is different for all pages. So we might probably take care of the OAuth2 authorization pages as well as the error pages.

TODO have UI templates for every page of the workflow.